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