00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <stdlib.h>
00041 #include <string.h>
00042 #include <stdarg.h>
00043 #include <stdio.h>
00044 #include <fcntl.h>
00045 #include <errno.h>
00046
00047 #include <elf_abi.h>
00048 #include <elf_mips.h>
00049 #include <sys/types.h>
00050 #include <sys/stat.h>
00051
00052 #include <sys/mman.h>
00053 #include "ir_prof.h"
00054 #include "ir_graph_util.h"
00055
00056 #define MALLOC(nbytes) \
00057 malloc((size_t)(nbytes))
00058
00059 #define REALLOC(ptr, size) \
00060 realloc((void *)(ptr), (size_t)(size))
00061
00062 char *raw_bits;
00063 struct stat statb;
00064 int fd_counts, fd;
00065
00066 #define TRUE 1
00067 #define FALSE 0
00068 #define EEOF -1
00069 #define NOT_FOUND -1
00070
00071 #define FILE_OTHER 0
00072 #define FILE_EXECUTABLE 1
00073 #define FILE_RELOCATABLE 2
00074 #define FILE_ARCHIVE 3
00075
00076 #define ST_NONE 0
00077 #define ST_NAME 1
00078 #define ST_BIND 2
00079 #define ST_OTHER 3
00080 #define ST_TYPE 4
00081 #define ST_SHNDX 5
00082
00083
00084 static char *infile = NULL;
00085 static char *tool_name = NULL;
00086 static char *sect_name = NULL;
00087 static int dump_flag = 0;
00088 static int callgraph_flag = 0;
00089 static int sort_flag = 0;
00090 static int verbose_flag = 0;
00091 static void *dummy;
00092 static int num_argc = 0;
00093
00094 static unsigned warn_flag = FALSE;
00095 static unsigned sect_index = 0;
00096 static unsigned targ32_flag = 0;
00097 static counts_entry *carray;
00098
00099 typedef struct {
00100 char *name;
00101 ADDR size;
00102 } proc_info;
00103
00104 static proc_info *parray;
00105 static int num_proc;
00106
00107 Elf64_Ehdr *p_elf_header;
00108 Elf64_Shdr *p_sect_header;
00109
00110 __uint64_t g_text_start;
00111 __uint64_t g_text_end;
00112 __uint64_t g_text_size;
00113 __uint64_t g_textlo_index;
00114
00115 #define ELF_TARG_32() (p_elf_header->e_ident[EI_CLASS] == ELFCLASS32)
00116
00117 #define ASSERT(EX, p) if (!(EX)) sysfatal(p)
00118
00119
00120 void usage()
00121 {
00122
00123 fprintf(stderr, "%s: Usage is: %s options... countsfile\n options are:\n", tool_name, tool_name);
00124 fprintf(stderr, "\t-ebinaryname\n");
00125 }
00126
00127
00128 void
00129 warn(char * const s, ...)
00130 {
00131 va_list ap;
00132 FILE *stream;
00133
00134 warn_flag = TRUE ;
00135 stream = stderr;
00136 fprintf(stream, "%s: WARNING: ", tool_name);
00137
00138 va_start(ap, s);
00139 _doprnt(s, ap, stream);
00140 fprintf(stream, " [%s]", infile);
00141 fputs(".\n", stream);
00142 fflush(stream);
00143 }
00144
00145
00146 void sysfatal(char * const s, ...)
00147 {
00148 va_list ap;
00149 FILE *stream;
00150
00151 stream = stderr;
00152
00153 int err_num = errno;
00154 errno = 0;
00155
00156 char *err_str = strerror(err_num);
00157
00158 if (err_num == EEOF) {
00159 fprintf(stream, "%s: %s, ", tool_name, "unexpected end of file");
00160 }
00161 else if (errno == 0) {
00162 fprintf(stream, "%s: %s, ", tool_name, strerror(errno));
00163 }
00164 else {
00165 fprintf(stream, "%s: error code %d, ", tool_name, err_num);
00166 }
00167
00168 va_start(ap, s);
00169 _doprnt(s, ap, stream);
00170 fprintf(stream, " [%s]", infile);
00171 fputs(".\n", stream);
00172
00173 exit(1);
00174 }
00175
00176
00177 void command_line (int argc, char **argv)
00178 {
00179 register char **av, **ave;
00180 char *addrs_name = NULL;
00181 char *counts_name = NULL;
00182 int index = 1;
00183
00184 num_argc = argc;
00185 for (av = &argv[1], ave = argv + argc; av != ave; index++) {
00186 register char *arg = *av++;
00187 if (arg[0] == '-') {
00188 register char *name = &arg[1];
00189
00190 if (strcmp(name, "h") == 0) {
00191 usage();
00192 exit(1);
00193 }
00194 else if (name[0] == 'e') {
00195 infile = &arg[2];
00196 num_argc--;
00197 }
00198 else if (name[0] == 'd') {
00199 dump_flag = 1;
00200 num_argc--;
00201 }
00202 else if (name[0] == 'g') {
00203 callgraph_flag = 1;
00204 num_argc--;
00205 }
00206 else if (name[0] == 's') {
00207 sort_flag = 1;
00208 num_argc--;
00209 }
00210 else if (name[0] == 'v') {
00211 verbose_flag = 1;
00212 num_argc--;
00213 }
00214 }
00215
00216 }
00217 }
00218
00219
00220 char *
00221 open_file(char * const objname)
00222 {
00223 char *raw_bits;
00224 int fd;
00225
00226 fd = open(objname, O_RDWR, 0755);
00227 if (fd < 0)
00228 return 0;
00229
00230 if (fstat(fd, &statb) != 0)
00231 return 0;
00232
00233 if ((void *)(raw_bits =
00234 (caddr_t)mmap( 0,
00235 statb.st_size,
00236 PROT_WRITE,
00237 MAP_SHARED,
00238 fd,
00239 0)) == (void *)-1) {
00240 raw_bits = (char *)malloc (statb.st_size);
00241 if (!raw_bits)
00242 return 0;
00243
00244 if (read(fd, raw_bits, statb.st_size) != statb.st_size)
00245 return 0;
00246 }
00247 return raw_bits;
00248
00249 }
00250
00251
00252 void close_file(char *raw_bits)
00253 {
00254 extern long *_end;
00255 unsigned long new_offset;
00256
00257
00258
00259
00260 free(p_elf_header);
00261 free(p_sect_header);
00262
00263 new_offset = (unsigned long)raw_bits;
00264 if (munmap ((caddr_t)raw_bits,statb.st_size) == -1)
00265 free(raw_bits);
00266
00267 close(fd);
00268
00269 }
00270
00271
00272 Elf64_Ehdr *
00273 make_elfheader(char *raw_bits)
00274 {
00275 Elf64_Ehdr *p_ehdr, *tmpp_ehdr;
00276
00277
00278
00279
00280 tmpp_ehdr = (Elf64_Ehdr *)raw_bits;
00281 targ32_flag = (tmpp_ehdr->e_ident[EI_CLASS] == ELFCLASS32);
00282
00283 p_ehdr = (Elf64_Ehdr *)malloc(sizeof(Elf64_Ehdr));
00284 if (!(p_ehdr)) {
00285 sysfatal("malloc unable to allocate %d bytes",
00286 sizeof(Elf64_Ehdr));
00287 }
00288
00289 if (targ32_flag) {
00290 register unsigned i;
00291 Elf32_Ehdr *p32_ehdr = (Elf32_Ehdr *)raw_bits;
00292
00293 for (i = 0; i<EI_NIDENT; i++) {
00294 p_ehdr->e_ident[i] = p32_ehdr->e_ident[i];
00295 }
00296 p_ehdr->e_type = (Elf64_Half)p32_ehdr->e_type;
00297 p_ehdr->e_machine = (Elf64_Half)p32_ehdr->e_machine;
00298 p_ehdr->e_version = (Elf64_Word)p32_ehdr->e_version;
00299 p_ehdr->e_entry = (Elf64_Addr)p32_ehdr->e_entry;
00300 p_ehdr->e_phoff = (Elf64_Off )p32_ehdr->e_phoff;
00301 p_ehdr->e_shoff = (Elf64_Off )p32_ehdr->e_shoff;
00302 p_ehdr->e_flags = (Elf64_Word)p32_ehdr->e_flags;
00303 p_ehdr->e_ehsize = (Elf64_Half)p32_ehdr->e_ehsize;
00304 p_ehdr->e_phentsize = (Elf64_Half)p32_ehdr->e_phentsize;
00305 p_ehdr->e_phnum = (Elf64_Half)p32_ehdr->e_phnum;
00306 p_ehdr->e_shentsize = (Elf64_Half)p32_ehdr->e_shentsize;
00307 p_ehdr->e_shnum = (Elf64_Half)p32_ehdr->e_shnum;
00308 p_ehdr->e_shstrndx = (Elf64_Half)p32_ehdr->e_shstrndx;
00309 }
00310 else {
00311 Elf64_Ehdr *p64_ehdr = (Elf64_Ehdr *)raw_bits;
00312 memcpy((void *)p_ehdr, p64_ehdr, sizeof(Elf64_Ehdr));
00313 }
00314
00315 return(p_ehdr);
00316 }
00317
00318
00319 Elf64_Shdr *
00320 make_sectheader(char *raw_bits)
00321 {
00322 Elf64_Shdr *p_shdr;
00323 unsigned sect_count;
00324
00325 if (targ32_flag) {
00326 unsigned i;
00327 Elf32_Ehdr *p32_ehdr = (Elf32_Ehdr *)raw_bits;
00328 Elf32_Shdr *p32_shdr = (Elf32_Shdr *)(raw_bits+p32_ehdr->e_shoff);
00329
00330 sect_count = p32_ehdr->e_shnum;
00331
00332 p_shdr = (Elf64_Shdr *)malloc(sizeof(Elf64_Shdr) * sect_count);
00333 if (!(p_shdr)) {
00334 sysfatal("malloc unable to allocate %d bytes",
00335 sizeof(Elf64_Phdr) * sect_count);
00336 }
00337
00338 for (i = 0; i < sect_count; i++) {
00339 p_shdr[i].sh_name = (Elf64_Word)p32_shdr[i].sh_name;
00340 p_shdr[i].sh_type = (Elf64_Word)p32_shdr[i].sh_type;
00341 p_shdr[i].sh_flags = (Elf64_Xword)p32_shdr[i].sh_flags;
00342 p_shdr[i].sh_addr = (Elf64_Addr)p32_shdr[i].sh_addr;
00343 p_shdr[i].sh_offset = (Elf64_Off)p32_shdr[i].sh_offset;
00344 p_shdr[i].sh_size = (Elf64_Xword)p32_shdr[i].sh_size;
00345 p_shdr[i].sh_link = (Elf64_Word)p32_shdr[i].sh_link;
00346 p_shdr[i].sh_info = (Elf64_Word)p32_shdr[i].sh_info;
00347 p_shdr[i].sh_addralign = (Elf64_Xword)p32_shdr[i].sh_addralign;
00348 p_shdr[i].sh_entsize = (Elf64_Xword)p32_shdr[i].sh_entsize;
00349 }
00350 }
00351 else {
00352 Elf64_Ehdr *p64_ehdr = (Elf64_Ehdr *)raw_bits;
00353 Elf64_Shdr *p64_shdr = (Elf64_Shdr *)(raw_bits+p64_ehdr->e_shoff);
00354
00355 sect_count = p64_ehdr->e_shnum;
00356
00357 p_shdr = (Elf64_Shdr *)malloc(sizeof(Elf64_Shdr) * sect_count);
00358 if (!(p_shdr)) {
00359 sysfatal("malloc unable to allocate %d bytes",
00360 sizeof(Elf64_Shdr) * sect_count);
00361 }
00362
00363 memcpy((void *)p_shdr, p64_shdr, sizeof(Elf64_Shdr) * sect_count);
00364 }
00365
00366 return(p_shdr);
00367 }
00368
00369
00370 int
00371 is_elf_file(char *raw_bits, char *fname)
00372 {
00373 Elf32_Ehdr *p_ehdr;
00374 int ret = 0;
00375
00376 p_ehdr = (Elf32_Ehdr *)raw_bits;
00377 if (p_ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
00378 p_ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
00379 p_ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
00380 p_ehdr->e_ident[EI_MAG3] != ELFMAG3) {
00381 return(FALSE);
00382 }
00383
00384 if (p_ehdr->e_type == ET_REL)
00385 sysfatal( "%s not an executable", fname);
00386
00387 targ32_flag = (p_ehdr->e_ident[EI_CLASS] == ELFCLASS32);
00388
00389 return FILE_EXECUTABLE;
00390 }
00391
00392
00393 unsigned
00394 find_section(char *raw_bits, char *name, unsigned type, unsigned type_only)
00395 {
00396 Elf64_Shdr *p_shdr, *p_section;
00397 char *string_tab, *string;
00398 unsigned offset;
00399 unsigned i;
00400
00401
00402
00403
00404 p_section = &p_sect_header[p_elf_header->e_shstrndx];
00405 string_tab = (char *)(raw_bits+p_section->sh_offset);
00406
00407 for (i = 0; i < p_elf_header->e_shnum; i++) {
00408 if (p_sect_header[i].sh_type == type) {
00409
00410 if (type_only)
00411 return(i);
00412
00413 if (strcmp(string_tab+p_sect_header[i].sh_name, name) == 0) {
00414 return(i);
00415 }
00416 }
00417 }
00418
00419 return 0;
00420 }
00421
00422
00423 int
00424 verify_counts_file(char *bits, char *fname)
00425 {
00426 Counts_hdr *p;
00427
00428 p = (Counts_hdr *)bits;
00429
00430 if (p->c_ident[0] != COUNTSMAG0 ||
00431 p->c_ident[1] != COUNTSMAG1 ||
00432 p->c_ident[2] != COUNTSMAG2 ||
00433 p->c_ident[3] != COUNTSMAG3 ||
00434 p->c_ident[4] != COUNTSMAG4 ||
00435 p->c_ident[5] != COUNTSMAG5 ||
00436 p->c_ident[6] != COUNTSMAG6 ||
00437 p->c_ident[7] != COUNTSMAG7)
00438 sysfatal("Not a counts-file:%s\n",fname);
00439
00440 if (p->c_version != C_VERSION)
00441 sysfatal("Counts-file version %d not supported\n",p->c_version);
00442
00443 return p->c_entry;
00444 }
00445
00446
00447 void
00448 close_counts_file(char *fname)
00449 {
00450 close(fd_counts);
00451 }
00452
00453
00454 counts_entry *
00455 open_counts_file(char *fname, long *num_entry, char **count_str)
00456 {
00457 char *counts_bits;
00458
00459 ASSERT(fname, "openning file with null string");
00460
00461 fd_counts = open(fname, 0, 0755);
00462
00463 if (fd_counts < 0)
00464 sysfatal("Cannot open counts-file: %s\n",fname);
00465
00466 if (fstat(fd_counts, &statb) != 0)
00467 sysfatal("Cannot fstat counts-file: %s\n",fname);
00468
00469 if ((void *)(counts_bits =
00470 (caddr_t)mmap( 0,
00471 statb.st_size,
00472 PROT_WRITE,
00473 MAP_SHARED,
00474 fd_counts,
00475 0)) == (void *)-1) {
00476 counts_bits = (char *)MALLOC (statb.st_size);
00477 if (!counts_bits)
00478 sysfatal("Cannot malloc counts-file size: %x\n",statb.st_size);
00479
00480 if (read(fd_counts, counts_bits, statb.st_size) != statb.st_size)
00481 sysfatal("Cannot read counts-file: %s\n",fname);
00482
00483 }
00484 *num_entry = verify_counts_file(counts_bits, fname);
00485 *count_str = (char *)counts_bits + sizeof(Counts_hdr) + (*num_entry * sizeof(counts_entry));
00486
00487 return (counts_entry *)((char *)counts_bits+sizeof(Counts_hdr));
00488 }
00489
00490
00491 char *
00492 find_and_get_str(ADDR addr, Elf64_Sym *symtab, int symcount, int start, char *strtab)
00493 {
00494 unsigned int ilow, ihigh, ihalf;
00495
00496 ilow = start;
00497 ihigh = symcount-1;
00498 ihalf = (ilow + ihigh) / 2;
00499
00500 while (ilow < ihigh) {
00501 if (addr < symtab[ihalf].st_value)
00502 ihigh = ihalf;
00503 else if (addr > symtab[ihalf].st_value) {
00504 ilow = ihalf;
00505 if (ilow == ihigh - 1) {
00506 if (addr == symtab[ihigh].st_value)
00507 return (char *)(strtab + symtab[ihigh].st_name);
00508 break;
00509 }
00510 }
00511 else {
00512 return (char *)(strtab + symtab[ihalf].st_name);
00513 }
00514 ihalf = (ilow + ihigh) / 2;
00515 }
00516 warn("address %x has no symbol", addr);
00517 return 0;
00518 }
00519
00520
00521 char *make_name(ADDR addr)
00522 {
00523 char *tmp = MALLOC(12);
00524
00525 ASSERT(tmp, "Cannot malloc string to manufacture name");
00526
00527 sprintf(tmp, "_0x%x", addr);
00528 return tmp;
00529 }
00530
00531
00532 char *
00533 get_name(ADDR mem, int idx, Elf64_Sym *symtab, int symcount, int symstart, char *strtab, char *count_strtab)
00534 {
00535 char *name1;
00536
00537 if (idx == 0) {
00538 if ((name1 = find_and_get_str(mem, symtab, symcount, symstart, strtab)) == 0) {
00539
00540 name1 = make_name(mem);
00541 }
00542 }
00543 else
00544 name1 = count_strtab + idx;
00545 return name1;
00546 }
00547
00548
00549 void
00550 put_rec(counts_entry *pc, int idx)
00551 {
00552
00553 ASSERT(carray, "carray never initialized");
00554 carray[idx].count = pc->count;
00555 carray[idx].caller = pc->caller;
00556 carray[idx].callee = pc->callee;
00557 carray[idx].caller_name_idx = pc->caller_name_idx;
00558 carray[idx].callee_name_idx = pc->callee_name_idx;
00559 }
00560
00561
00562 int c_cmp(counts_entry *p1, counts_entry *p2)
00563 {
00564 if (p1->count > p2->count)
00565 return -1;
00566 if (p1->count == p2->count)
00567 return 0;
00568 return 1;
00569 }
00570
00571 typedef struct {
00572 char *name;
00573 ADDR a;
00574 VINDEX idx;
00575 } unique_name;
00576
00577 typedef struct {
00578 int caller;
00579 int callee;
00580 EINDEX edge_idx;
00581 } map2unique;
00582
00583 static unique_name *pun;
00584 static map2unique *c;
00585
00586
00587
00588
00589 int
00590 add_unique_name(char *name, ADDR a, unique_name *pun, int size)
00591 {
00592 int i;
00593 char *p;
00594
00595 for (i = 0; i < size; i++) {
00596 if (strcmp(pun[i].name, name) == 0) {
00597 if (pun[i].a == a)
00598 return i;
00599 }
00600 }
00601
00602 p = MALLOC(strlen(name) + 1);
00603 ASSERT(p, "cannot malloc string for unique name");
00604 strcpy(p, name);
00605
00606 pun[size].a = a;
00607 pun[size].name = p;
00608 return NOT_FOUND;
00609 }
00610
00611
00612 int
00613 pr_dyn_count(EINDEX idx, long num_entry)
00614 {
00615 long i, j;
00616
00617 for (i=0; i < num_entry; i++) {
00618 if (c[i].edge_idx == idx) {
00619 ADDR caller, callee;
00620
00621 caller = pun[c[i].caller].a;
00622 callee = pun[c[i].callee].a;
00623
00624 for (j = 0; j < num_entry; j++) {
00625 if (carray[j].caller == caller && carray[j].callee == callee)
00626 return j;
00627 }
00628 }
00629 }
00630 ASSERT(0, "edge_index not found");
00631 return 0;
00632 }
00633
00634
00635 extern ADDR get_proc_size();
00636 static char ptmp[] = " (???)";
00637
00638 void
00639 pr_vertex_name(int idx)
00640 {
00641 ADDR s;
00642
00643 printf("%s", pun[idx].name);
00644
00645 if (verbose_flag) {
00646 s = get_proc_size(pun[idx].name);
00647 if (s) {
00648 printf(" (0x%x)", s);
00649 }
00650 else {
00651 printf(ptmp);
00652 }
00653 }
00654 }
00655
00656
00657 void
00658 pr_count(long *p)
00659 {
00660 printf("%d",*p);
00661 }
00662
00663
00664 void
00665 build_call_graph(counts_entry *pc, long num_entry, Elf64_Sym *symtab, int symcount, int symstart, char *strtab, char *count_strtab)
00666 {
00667 int i, count, j;
00668 long k;
00669 char *name;
00670 GRAPH *graph;
00671
00672 count = 0;
00673
00674 pun = MALLOC(num_entry * sizeof(unique_name));
00675 ASSERT(pun, "cannot malloc unique struct");
00676
00677 c = MALLOC(num_entry * sizeof(map2unique));
00678 ASSERT(c, "cannot malloc map2unique array");
00679
00680 for (i = 0; i < num_entry; i++) {
00681 name = get_name(pc[i].caller, pc[i].caller_name_idx, symtab, symcount, symstart, strtab, count_strtab);
00682 j = add_unique_name(name, pc[i].caller, pun, count);
00683 if (j == NOT_FOUND) {
00684 c[i].caller = count;
00685 count++;
00686 }
00687 else
00688 c[i].caller = j;
00689
00690 name = get_name(pc[i].callee, pc[i].callee_name_idx, symtab, symcount, symstart, strtab, count_strtab);
00691 j = add_unique_name(name, pc[i].callee, pun, count);
00692 if (j == NOT_FOUND) {
00693 c[i].callee = count;
00694 count++;
00695 }
00696 else
00697 c[i].callee = j;
00698 }
00699
00700 graph = build_graph_u(DEF_VERTEX_SIZE, DEF_EDGE_SIZE, dummy);
00701 for (i = 0; i < count; i++) {
00702 VINDEX idx;
00703
00704 idx = add_vertex(graph, (void *)&pun[i]);
00705 #ifdef _DEBUG
00706 printf("add_vertex: %s (%d)\n",pun[i].name, idx);
00707 #endif
00708 pun[i].idx = idx;
00709 }
00710
00711 for (i = 0; i < num_entry; i++) {
00712 c[i].edge_idx = add_edge(graph, pun[c[i].caller].idx, pun[c[i].callee].idx, &pun[i]);
00713 #ifdef _DEBUG
00714 printf("add_edge: %s, --> %s (%d)\n",pun[c[i].caller].name, pun[c[i].callee].name, c[i].edge_idx);
00715 #endif
00716
00717 k = pr_dyn_count(c[i].edge_idx, num_entry);
00718 set_edge_u(graph, c[i].edge_idx, &carray[k].count);
00719
00720 if (GRAPH_root(graph) == INVALID_VINDEX )
00721 if (strcmp(pun[c[i].caller].name, "main") == 0)
00722 GRAPH_root(graph) = pun[c[i].caller].idx;
00723 }
00724
00725 {
00726 DFN *d;
00727 d = Depth_First_Ordering(graph, dummy);
00728 Print_DFN(d, graph, (void (*)())pr_vertex_name, pr_count);
00729 }
00730
00731 }
00732
00733
00734 void
00735 process_counts(char *fname, Elf64_Sym *symtab, int symcount, int symstart, char *strtab)
00736 {
00737 long num_entry;
00738 counts_entry *pc;
00739 long i, id1, id2;
00740 char *name1, *name2;
00741 char *count_strtab;
00742
00743 pc = open_counts_file(fname, &num_entry, &count_strtab);
00744
00745 if (!dump_flag) {
00746 if (carray == 0) {
00747 if ((carray = (counts_entry *)calloc(num_entry, sizeof(counts_entry))) == 0) {
00748 ASSERT(0, "Cannot allocate temporary array");
00749 }
00750 }
00751 }
00752
00753 for (i = 0; i < num_entry; i++) {
00754 if (dump_flag) {
00755 name1 = get_name(pc[i].caller, pc[i].caller_name_idx, symtab, symcount, symstart, strtab, count_strtab);
00756 name2 = get_name(pc[i].callee, pc[i].callee_name_idx, symtab, symcount, symstart, strtab, count_strtab);
00757 printf("%s\t%s\t%d\n", name1, name2, pc[i].count);
00758 }
00759 else
00760 put_rec(&pc[i], i);
00761 }
00762
00763 if (sort_flag) {
00764 char *v;
00765
00766 #define NOT_VISITED 1
00767
00768 v = MALLOC(num_entry);
00769 ASSERT(v, "fail to malloc visited array of carray");
00770 memset(v, NOT_VISITED, num_entry);
00771
00772 qsort(carray, num_entry, sizeof(counts_entry), (int (*) ()) c_cmp);
00773
00774 for (i = 0; i < num_entry; i++) {
00775
00776 if (v[i]) {
00777 name1 = get_name(carray[i].caller, carray[i].caller_name_idx, symtab, symcount, symstart, strtab, count_strtab);
00778 name2 = get_name(carray[i].callee, carray[i].callee_name_idx, symtab, symcount, symstart, strtab, count_strtab);
00779 printf("%s\t%s\t%d\n",name1, name2, carray[i].count);
00780
00781 if (verbose_flag) {
00782 int j, k;
00783 long total;
00784
00785 total = 0;
00786 for (j = i+1; j < num_entry; j++) {
00787 if (carray[i].caller == carray[j].caller) {
00788 if (total == 0) {
00789 for (k = 0; k < strlen(name1); k++) {
00790 printf(" ");
00791 }
00792 printf("\t ");
00793 }
00794
00795 name2 = get_name(carray[j].callee, carray[j].callee_name_idx, symtab, symcount, symstart, strtab, count_strtab);
00796 printf(" %s/%d", name2, carray[j].count);
00797
00798 total += carray[j].count;
00799 v[j] = !NOT_VISITED;
00800 }
00801 }
00802 if (total != 0)
00803 printf(" total - %d\n", total + carray[i].count);
00804 }
00805 }
00806 }
00807 }
00808
00809 if (callgraph_flag) {
00810 build_call_graph(pc, num_entry, symtab, symcount, symstart, strtab, count_strtab);
00811 }
00812 }
00813
00814
00815 Elf64_Sym *
00816 make_symtab64(char *orig, int count)
00817 {
00818 Elf64_Sym *new;
00819 int i;
00820
00821 if (ELF_TARG_32()) {
00822 Elf32_Sym *porig = (Elf32_Sym *)orig;
00823
00824 new = MALLOC(count * sizeof (Elf64_Sym));
00825 ASSERT(new, "cannot malloc symtab64");
00826
00827 for (i = 0; i < count; i++) {
00828 new[i].st_name = (Elf64_Word)porig[i].st_name;
00829 new[i].st_info = (Elf64_Byte)porig[i].st_info;
00830 new[i].st_other = (Elf64_Byte)porig[i].st_other;
00831 new[i].st_shndx = (Elf64_Section)porig[i].st_shndx;
00832 new[i].st_value = (Elf64_Addr)porig[i].st_value;
00833 new[i].st_size = (Elf64_Xword)porig[i].st_size;
00834 }
00835 return new;
00836 }
00837 else
00838 return (Elf64_Sym *)orig;
00839 }
00840
00841
00842 void
00843 get_dynamic_rec(int index, char *dynamic, Elf64_Dyn *dyn)
00844 {
00845 Elf64_Dyn *p = (Elf64_Dyn *)dynamic;
00846 if (ELF_TARG_32()) {
00847 Elf32_Dyn *p32 = (Elf32_Dyn *)dynamic;
00848 dyn->d_tag = p32[index].d_tag;
00849 dyn->d_un.d_val = p32[index].d_un.d_val;
00850 }
00851 else {
00852 dyn->d_tag = p[index].d_tag;
00853 dyn->d_un.d_val = p[index].d_un.d_val;
00854 return;
00855 }
00856 }
00857
00858
00859 ADDR
00860 get_proc_size(char *name)
00861 {
00862 int i;
00863
00864 if (parray == 0)
00865 return 0;
00866
00867 for (i = 0; i < num_proc; i++) {
00868 if (strcmp(name, parray[i].name) == 0)
00869 return (parray[i].size);
00870 }
00871 return 0;
00872 }
00873
00874
00875
00876 void
00877 put_proc_name(char *sect_name, ADDR size)
00878 {
00879 char *name;
00880
00881 if (sect_name == 0 || *sect_name == '\0')
00882 return;
00883
00884 if (strncmp(sect_name, ".text", 5) == 0) {
00885 if (strlen(sect_name) == 5)
00886 return;
00887
00888 parray[num_proc].size = size;
00889 parray[num_proc].name = sect_name + 5;
00890 num_proc++;
00891 }
00892 return;
00893 }
00894
00895
00896 main(int argc, char **argv)
00897 {
00898 unsigned index;
00899 int type;
00900 int i, sym_count, got_index;
00901 int start;
00902 Elf64_Sym *sym_tab;
00903 char *str_tab, *shstr_tab;
00904 char *raw_bits;
00905 int symindex;
00906 int strindex, dynindex, shstrindex;
00907 char *orig_tab, *dynamic;
00908 Elf64_Dyn e64_dyn;
00909 Elf32_Ehdr *p_ehdr;
00910
00911
00912 tool_name = argv[0];
00913
00914 if (argc < 3) {
00915 usage();
00916 exit(1);
00917 }
00918
00919 if (num_argc > 2) {
00920 sysfatal("Will only handle 1 counts-file for now");
00921 }
00922
00923 command_line(argc, argv);
00924 if (infile) {
00925 if ((raw_bits = open_file(infile)) == 0)
00926 sysfatal("Cannot open file %s ", infile);
00927
00928 if ((type = is_elf_file(raw_bits, infile)) == FILE_OTHER)
00929 sysfatal("%s not an elf file", infile);
00930
00931
00932 p_elf_header = make_elfheader(raw_bits);
00933 p_sect_header = make_sectheader(raw_bits);
00934
00935 symindex = find_section(raw_bits, ".dynsym", SHT_DYNSYM, FALSE);
00936 orig_tab = (char *)(raw_bits+p_sect_header[symindex].sh_offset);
00937 sym_count = p_sect_header[symindex].sh_size/p_sect_header[symindex].sh_entsize;
00938
00939 sym_tab = make_symtab64(orig_tab, sym_count);
00940
00941 strindex = find_section(raw_bits, ".dynstr", SHT_STRTAB, FALSE);
00942 str_tab = (char *)(raw_bits+p_sect_header[strindex].sh_offset);
00943
00944 dynindex = find_section(raw_bits, ".dynamic", SHT_DYNAMIC, FALSE);
00945 dynamic = (char *)(raw_bits+p_sect_header[dynindex].sh_offset);
00946
00947 i = 0;
00948 do {
00949 get_dynamic_rec(i++, dynamic, &e64_dyn);
00950 if (e64_dyn.d_tag == DT_MIPS_GOTSYM) {
00951 got_index = e64_dyn.d_un.d_val;
00952 break;
00953 }
00954 } while (e64_dyn.d_tag != DT_NULL);
00955
00956 if (got_index == 0)
00957 sysfatal("Got index of executable is 0");
00958 }
00959 else
00960 sysfatal("No executable specified");
00961
00962 if (verbose_flag) {
00963 int i, j;
00964 Elf64_Shdr *p_section = &p_sect_header[p_elf_header->e_shstrndx];
00965
00966 parray = MALLOC(sizeof(proc_info) * p_elf_header->e_shnum);
00967 ASSERT(parray, "cannot malloc proc array");
00968
00969 for (i = 0; i < p_elf_header->e_shnum; i++) {
00970 if (p_sect_header[i].sh_type == SHT_PROGBITS)
00971 put_proc_name((char *)(raw_bits+p_section->sh_offset + p_sect_header[i].sh_name), p_sect_header[i].sh_size);
00972 }
00973 }
00974
00975 for (i = 1; i < argc; i++) {
00976 if (argv[i][0] == '-')
00977 continue;
00978 process_counts(argv[i], sym_tab, sym_count, got_index, str_tab);
00979 close_counts_file(argv[i]);
00980 }
00981 }
00982