Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 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 } /* obj_open */ 00241 00242 00243 void close_file(char *raw_bits) 00244 { 00245 extern long *_end; 00246 unsigned long new_offset; 00247 00248 /* 00249 * Free malloc'd tables and sections. 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 * Get target address size 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 * Find the section. 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 /* manufacture a name */ 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; /* this gives the map from the counts array to the vertices in the graph */ 00576 /* 00577 this is really quick and dirty, I am doing a linear search 00578 from beginning and check for same name, same address 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 /* I assume that section names are made up of .text{proc name} */ 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 /* normalize the symbol table */ 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