Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
ir_prof_digest.c
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines