Update.
[platform/upstream/glibc.git] / elf / sprof.c
1 /* Read and display shared object profiling data.
2    Copyright (C) 1997, 1998 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15
16    You should have received a copy of the GNU Library General Public
17    License along with the GNU C Library; see the file COPYING.LIB.  If not,
18    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 #include <argp.h>
22 #include <dlfcn.h>
23 #include <elf.h>
24 #include <endian.h>
25 #include <error.h>
26 #include <fcntl.h>
27 #include <inttypes.h>
28 #include <libintl.h>
29 #include <link.h>
30 #include <locale.h>
31 #include <obstack.h>
32 #include <search.h>
33 #include <stab.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38 #include <sys/gmon.h>
39 #include <sys/gmon_out.h>
40 #include <sys/mman.h>
41 #include <sys/param.h>
42 #include <sys/stat.h>
43
44 /* Undefine the following line line in the production version.  */
45 /* #define _NDEBUG 1 */
46 #include <assert.h>
47
48 /* Get libc version number.  */
49 #include "../version.h"
50
51 #define PACKAGE _libc_intl_domainname
52
53
54 #include <endian.h>
55 #if BYTE_ORDER == BIG_ENDIAN
56 #define byteorder ELFDATA2MSB
57 #define byteorder_name "big-endian"
58 #elif BYTE_ORDER == LITTLE_ENDIAN
59 #define byteorder ELFDATA2LSB
60 #define byteorder_name "little-endian"
61 #else
62 #error "Unknown BYTE_ORDER " BYTE_ORDER
63 #define byteorder ELFDATANONE
64 #endif
65
66
67 extern int __profile_frequency __P ((void));
68
69 /* Name and version of program.  */
70 static void print_version (FILE *stream, struct argp_state *state);
71 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
72
73 #define OPT_COUNT_TOTAL 1
74 #define OPT_TEST 2
75
76 /* Definitions of arguments for argp functions.  */
77 static const struct argp_option options[] =
78 {
79   { NULL, 0, NULL, 0, N_("Output selection:") },
80   { "count-total", OPT_COUNT_TOTAL, NULL, 0,
81     N_("print number of invocations for each function") },
82   { "test", OPT_TEST, NULL, OPTION_HIDDEN, NULL },
83   { NULL, 0, NULL, 0, NULL }
84 };
85
86 /* Short description of program.  */
87 static const char doc[] = N_("Read and display shared object profiling data");
88
89 /* Strings for arguments in help texts.  */
90 static const char args_doc[] = N_("SHOBJ [PROFDATA]");
91
92 /* Prototype for option handler.  */
93 static error_t parse_opt (int key, char *arg, struct argp_state *state);
94
95 /* Data structure to communicate with argp functions.  */
96 static struct argp argp =
97 {
98   options, parse_opt, args_doc, doc, NULL, NULL
99 };
100
101
102 /* Operation modes.  */
103 static enum
104 {
105   NONE = 0,
106   COUNT_TOTAL
107 } mode;
108
109 /* If nonzero the total number of invocations of a function is emitted.  */
110 int count_total;
111
112 /* Nozero for testing.  */
113 int do_test;
114
115 /* Strcuture describing calls.  */
116 struct here_fromstruct
117   {
118     struct here_cg_arc_record volatile *here;
119     uint16_t link;
120   };
121
122 /* We define a special type to address the elements of the arc table.
123    This is basically the `gmon_cg_arc_record' format but it includes
124    the room for the tag and it uses real types.  */
125 struct here_cg_arc_record
126   {
127     uintptr_t from_pc;
128     uintptr_t self_pc;
129     uint32_t count;
130   } __attribute__ ((packed));
131
132 /* Information about the stab debugging info.  This should be in a
133    head but it is not.  */
134 #define STRDXOFF (0)
135 #define TYPEOFF (4)
136 #define OTHEROFF (5)
137 #define DESCOFF (6)
138 #define VALOFF (8)
139 #define STABSIZE (12)
140
141
142 struct known_symbol
143 {
144   const char *name;
145   uintptr_t addr;
146   size_t size;
147
148   uintmax_t ticks;
149 };
150
151
152 struct shobj
153 {
154   const char *name;             /* User-provided name.  */
155
156   struct link_map *map;
157   const char *strtab;           /* String table of shared object.  */
158   const char *soname;           /* Soname of shared object.  */
159
160   uintptr_t lowpc;
161   uintptr_t highpc;
162   unsigned long int kcountsize;
163   size_t expected_size;         /* Expected size of profiling file.  */
164   size_t tossize;
165   size_t fromssize;
166   size_t fromlimit;
167   unsigned int hashfraction;
168   int s_scale;
169
170   void *stab_map;
171   size_t stab_mapsize;
172   const char *stab;
173   size_t stab_size;
174   const char *stabstr;
175   size_t stabstr_size;
176
177   struct obstack ob_str;
178   struct obstack ob_sym;
179 };
180
181
182 struct profdata
183 {
184   void *addr;
185   off_t size;
186
187   char *hist;
188   uint16_t *kcount;
189   uint32_t narcs;               /* Number of arcs in toset.  */
190   struct here_cg_arc_record *data;
191   uint16_t *tos;
192   struct here_fromstruct *froms;
193 };
194
195 /* Search tree for symbols.  */
196 void *symroot;
197 static struct known_symbol **sortsym;
198 static size_t symidx;
199 static uintmax_t total_ticks;
200
201 /* Prototypes for local functions.  */
202 static struct shobj *load_shobj (const char *name);
203 static void unload_shobj (struct shobj *shobj);
204 static struct profdata *load_profdata (const char *name, struct shobj *shobj);
205 static void unload_profdata (struct profdata *profdata);
206 static void count_total_ticks (struct shobj *shobj, struct profdata *profdata);
207 static void read_symbols (struct shobj *shobj);
208
209
210 int
211 main (int argc, char *argv[])
212 {
213   const char *shobj;
214   const char *profdata;
215   struct shobj *shobj_handle;
216   struct profdata *profdata_handle;
217   int remaining;
218
219   setlocale (LC_ALL, "");
220
221   /* Initialize the message catalog.  */
222   textdomain (_libc_intl_domainname);
223
224   /* Parse and process arguments.  */
225   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
226
227   if (argc - remaining == 0 || argc - remaining > 2)
228     {
229       /* We need exactly two non-option parameter.  */
230       argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
231                  program_invocation_short_name);
232       exit (1);
233     }
234
235   /* Get parameters.  */
236   shobj = argv[remaining];
237   if (argc - remaining == 2)
238     profdata = argv[remaining + 1];
239   else
240     /* No filename for the profiling data given.  We will determine it
241        from the soname of the shobj, later.  */
242     profdata = NULL;
243
244   /* First see whether we can load the shared object.  */
245   shobj_handle = load_shobj (shobj);
246   if (shobj_handle == NULL)
247     exit (1);
248
249   /* We can now determine the filename for the profiling data, if
250      nececessary.  */
251   if (profdata == NULL)
252     {
253       char *newp;
254
255       if (shobj_handle->soname == NULL)
256         {
257           unload_shobj (shobj_handle);
258
259           error (EXIT_FAILURE, 0, _("\
260 no filename for profiling data given and shared object `%s' has no soname"),
261                  shobj);
262         }
263
264       newp = (char *) alloca (strlen (shobj_handle->soname)
265                               + sizeof ".profile");
266       stpcpy (stpcpy (newp, shobj_handle->soname), ".profile");
267       profdata = newp;
268     }
269
270   /* Now see whether the profiling data file matches the given object.   */
271   profdata_handle = load_profdata (profdata, shobj_handle);
272   if (profdata_handle == NULL)
273     {
274       unload_shobj (shobj_handle);
275
276       exit (1);
277     }
278
279   read_symbols (shobj_handle);
280
281   /* Do some work.  */
282   switch (mode)
283     {
284     case COUNT_TOTAL:
285       count_total_ticks (shobj_handle, profdata_handle);
286       {
287         size_t n;
288         for (n = 0; n < symidx; ++n)
289           if (sortsym[n]->ticks != 0)
290             printf ("Name: %-30s, Ticks: %" PRIdMAX "\n", sortsym[n]->name,
291                     sortsym[n]->ticks);
292         printf ("Total ticks: %" PRIdMAX "\n", total_ticks);
293       }
294       break;
295     case NONE:
296       /* Do nothing.  */
297       break;
298     default:
299       assert (! "Internal error");
300     }
301
302   /* Free the resources.  */
303   unload_shobj (shobj_handle);
304   unload_profdata (profdata_handle);
305
306   return 0;
307 }
308
309
310 /* Handle program arguments.  */
311 static error_t
312 parse_opt (int key, char *arg, struct argp_state *state)
313 {
314   switch (key)
315     {
316     case OPT_COUNT_TOTAL:
317       mode = COUNT_TOTAL;
318       break;
319     case OPT_TEST:
320       do_test = 1;
321       break;
322     default:
323       return ARGP_ERR_UNKNOWN;
324     }
325   return 0;
326 }
327
328
329 /* Print the version information.  */
330 static void
331 print_version (FILE *stream, struct argp_state *state)
332 {
333   fprintf (stream, "sprof (GNU %s) %s\n", PACKAGE, VERSION);
334   fprintf (stream, gettext ("\
335 Copyright (C) %s Free Software Foundation, Inc.\n\
336 This is free software; see the source for copying conditions.  There is NO\n\
337 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
338 "),
339            "1997, 1998");
340   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
341 }
342
343
344 /* Note that we must not use `dlopen' etc.  The shobj object must not
345    be loaded for use.  */
346 static struct shobj *
347 load_shobj (const char *name)
348 {
349   struct link_map *map = NULL;
350   struct shobj *result;
351   ElfW(Addr) mapstart = ~((ElfW(Addr)) 0);
352   ElfW(Addr) mapend = 0;
353   const ElfW(Phdr) *ph;
354   size_t textsize;
355   unsigned int log_hashfraction;
356   ElfW(Ehdr) *ehdr;
357   int fd;
358   ElfW(Shdr) *shdr;
359   void *ptr;
360   size_t pagesize = getpagesize ();
361   const char *shstrtab;
362   int idx;
363   ElfW(Shdr) *stab_entry;
364   ElfW(Shdr) *stabstr_entry;
365
366   /* Since we use dlopen() we must be prepared to work around the sometimes
367      strange lookup rules for the shared objects.  If we have a file foo.so
368      in the current directory and the user specfies foo.so on the command
369      line (without specifying a directory) we should load the file in the
370      current directory even if a normal dlopen() call would read the other
371      file.  We do this by adding a directory portion to the name.  */
372   if (strchr (name, '/') == NULL)
373     {
374       char *load_name = (char *) alloca (strlen (name) + 3);
375       stpcpy (stpcpy (load_name, "./"), name);
376
377       map = (struct link_map *) dlopen (load_name, RTLD_LAZY);
378     }
379   if (map == NULL)
380     {
381       map = (struct link_map *) dlopen (name, RTLD_LAZY);
382       if (map == NULL)
383         {
384           error (0, errno, _("failed to load shared object `%s'"), name);
385           return NULL;
386         }
387     }
388
389   /* Prepare the result.  */
390   result = (struct shobj *) calloc (1, sizeof (struct shobj));
391   if (result == NULL)
392     {
393       error (0, errno, _("cannot create internal descriptors"));
394       dlclose (map);
395       return NULL;
396     }
397   result->name = name;
398   result->map = map;
399
400   /* Compute the size of the sections which contain program code.
401      This must match the code in dl-profile.c (_dl_start_profile).  */
402   for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
403     if (ph->p_type == PT_LOAD && (ph->p_flags & PF_X))
404       {
405         ElfW(Addr) start = (ph->p_vaddr & ~(_dl_pagesize - 1));
406         ElfW(Addr) end = ((ph->p_vaddr + ph->p_memsz + _dl_pagesize - 1)
407                           & ~(_dl_pagesize - 1));
408
409         if (start < mapstart)
410           mapstart = start;
411         if (end > mapend)
412           mapend = end;
413       }
414
415   result->lowpc = ROUNDDOWN ((uintptr_t) (mapstart + map->l_addr),
416                              HISTFRACTION * sizeof (HISTCOUNTER));
417   result->highpc = ROUNDUP ((uintptr_t) (mapend + map->l_addr),
418                             HISTFRACTION * sizeof (HISTCOUNTER));
419   if (do_test)
420     printf ("load addr: %0#*" PRIxPTR "\n"
421             "lower bound PC: %0#*" PRIxPTR "\n"
422             "upper bound PC: %0#*" PRIxPTR "\n",
423             __ELF_NATIVE_CLASS == 32 ? 10 : 18, map->l_addr,
424             __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->lowpc,
425             __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->highpc);
426
427   textsize = result->highpc - result->lowpc;
428   result->kcountsize = textsize / HISTFRACTION;
429   result->hashfraction = HASHFRACTION;
430   if ((HASHFRACTION & (HASHFRACTION - 1)) == 0)
431     /* If HASHFRACTION is a power of two, mcount can use shifting
432        instead of integer division.  Precompute shift amount.  */
433     log_hashfraction = __builtin_ffs (result->hashfraction
434                                       * sizeof (struct here_fromstruct)) - 1;
435   else
436     log_hashfraction = -1;
437   if (do_test)
438     printf ("hashfraction = %d\ndivider = %d\n",
439             result->hashfraction,
440             result->hashfraction * sizeof (struct here_fromstruct));
441   result->tossize = textsize / HASHFRACTION;
442   result->fromlimit = textsize * ARCDENSITY / 100;
443   if (result->fromlimit < MINARCS)
444     result->fromlimit = MINARCS;
445   if (result->fromlimit > MAXARCS)
446     result->fromlimit = MAXARCS;
447   result->fromssize = result->fromlimit * sizeof (struct here_fromstruct);
448
449   result->expected_size = (sizeof (struct gmon_hdr)
450                            + 4 + sizeof (struct gmon_hist_hdr)
451                            + result->kcountsize
452                            + 4 + 4
453                            + (result->fromssize
454                               * sizeof (struct here_cg_arc_record)));
455
456   if (do_test)
457     printf ("expected size: %Zd\n", result->expected_size);
458
459 #define SCALE_1_TO_1    0x10000L
460
461   if (result->kcountsize < result->highpc - result->lowpc)
462     {
463       size_t range = result->highpc - result->lowpc;
464       size_t quot = range / result->kcountsize;
465
466       if (quot >= SCALE_1_TO_1)
467         result->s_scale = 1;
468       else if (quot >= SCALE_1_TO_1 / 256)
469         result->s_scale = SCALE_1_TO_1 / quot;
470       else if (range > ULONG_MAX / 256)
471         result->s_scale = ((SCALE_1_TO_1 * 256)
472                            / (range / (result->kcountsize / 256)));
473       else
474         result->s_scale = ((SCALE_1_TO_1 * 256)
475                            / ((range * 256) / result->kcountsize));
476     }
477   else
478     result->s_scale = SCALE_1_TO_1;
479
480   if (do_test)
481     printf ("s_scale: %d\n", result->s_scale);
482
483   /* Determine the string table.  */
484   if (map->l_info[DT_STRTAB] == NULL)
485     result->strtab = NULL;
486   else
487     result->strtab = (const char *) (map->l_addr
488                                      + map->l_info[DT_STRTAB]->d_un.d_ptr);
489   if (do_test)
490     printf ("string table: %p\n", result->strtab);
491
492   /* Determine the soname.  */
493   if (map->l_info[DT_SONAME] == NULL)
494     result->soname = NULL;
495   else
496     result->soname = result->strtab + map->l_info[DT_SONAME]->d_un.d_val;
497   if (do_test)
498     printf ("soname: %s\n", result->soname);
499
500   /* Now the hard part, we have to load the debugging data.  For now
501      we support stabs only.
502
503      First load the section header table.  */
504   ehdr = (ElfW(Ehdr) *) map->l_addr;
505
506   /* Make sure we are on the right party.  */
507   if (ehdr->e_shentsize != sizeof (ElfW(Shdr)))
508     abort ();
509
510   /* And we need the shared object file descriptor again.  */
511   fd = open (map->l_name, O_RDONLY);
512   if (fd == -1)
513     /* Dooh, this really shouldn't happen.  We know the file is available.  */
514     error (EXIT_FAILURE, errno, _("Reopening shared object `%s' failed"));
515
516   /* Now map the section header.  */
517   ptr = mmap (NULL, (ehdr->e_phnum * sizeof (ElfW(Shdr))
518                      + (ehdr->e_shoff & (pagesize - 1))), PROT_READ,
519               MAP_SHARED|MAP_FILE, fd, ehdr->e_shoff & ~(pagesize - 1));
520   if (ptr == MAP_FAILED)
521     error (EXIT_FAILURE, errno, _("mapping of section headers failed"));
522   shdr = (ElfW(Shdr) *) ((char *) ptr + (ehdr->e_shoff & (pagesize - 1)));
523
524   /* Get the section header string table.  */
525   ptr = mmap (NULL, (shdr[ehdr->e_shstrndx].sh_size
526                      + (shdr[ehdr->e_shstrndx].sh_offset & (pagesize - 1))),
527               PROT_READ, MAP_SHARED|MAP_FILE, fd,
528               shdr[ehdr->e_shstrndx].sh_offset & ~(pagesize - 1));
529   if (ptr == MAP_FAILED)
530     error (EXIT_FAILURE, errno,
531            _("mapping of section header string table failed"));
532   shstrtab = ((const char *) ptr
533               + (shdr[ehdr->e_shstrndx].sh_offset & (pagesize - 1)));
534
535   /* Search for the ".stab" and ".stabstr" section (and ".rel.stab" ?).  */
536   stab_entry = NULL;
537   stabstr_entry = NULL;
538   for (idx = 0; idx < ehdr->e_shnum; ++idx)
539     /* We only have to look for sections which are not loaded.  */
540     if (shdr[idx].sh_addr == 0)
541       {
542         if (strcmp (shstrtab + shdr[idx].sh_name, ".stab") == 0)
543           stab_entry = &shdr[idx];
544         else if (strcmp (shstrtab + shdr[idx].sh_name, ".stabstr") == 0)
545           stabstr_entry = &shdr[idx];
546       }
547
548   /* We don't need the sectin header string table anymore.  */
549   munmap (ptr, (shdr[ehdr->e_shstrndx].sh_size
550                 + (shdr[ehdr->e_shstrndx].sh_offset & (pagesize - 1))));
551
552   if (stab_entry == NULL || stabstr_entry == NULL)
553     {
554       fprintf (stderr, _("\
555 *** The file `%s' is stripped: no detailed analysis possible\n"),
556               name);
557       result->stab = NULL;
558       result->stabstr = NULL;
559     }
560   else
561     {
562       if (stab_entry->sh_offset + stab_entry->sh_size
563           != stabstr_entry->sh_offset)
564         abort ();
565       if (stab_entry->sh_size % STABSIZE != 0)
566         abort ();
567
568       result->stab_map = mmap (NULL, (stab_entry->sh_size
569                                       + stabstr_entry->sh_size
570                                       + (stab_entry->sh_offset
571                                          & (pagesize - 1))),
572                                PROT_READ, MAP_SHARED|MAP_FILE, fd,
573                                stab_entry->sh_offset & ~(pagesize - 1));
574       if (result->stab_map == NULL)
575         error (EXIT_FAILURE, errno, _("failed to load stab data:"));
576
577       result->stab = ((const char *) result->stab_map
578                       + (stab_entry->sh_offset & (pagesize - 1)));
579       result->stab_size = stab_entry->sh_size;
580       result->stabstr = result->stab + stab_entry->sh_size;
581       result->stabstr_size = stabstr_entry->sh_size;
582       result->stab_mapsize = (stab_entry->sh_size + stabstr_entry->sh_size
583                               + (stab_entry->sh_offset & (pagesize - 1)));
584     }
585
586   /* Now we also don't need the sectio header table anymore.  */
587   munmap ((char *) shdr - (ehdr->e_shoff & (pagesize - 1)),
588           (ehdr->e_phnum * sizeof (ElfW(Shdr))
589            + (ehdr->e_shoff & (pagesize - 1))));
590
591   /* Free the descriptor for the shared object.  */
592   close (fd);
593
594   return result;
595 }
596
597
598 static void
599 unload_shobj (struct shobj *shobj)
600 {
601   munmap (shobj->stab_map, shobj->stab_mapsize);
602   dlclose (shobj->map);
603 }
604
605
606 static struct profdata *
607 load_profdata (const char *name, struct shobj *shobj)
608 {
609   struct profdata *result;
610   int fd;
611   struct stat st;
612   void *addr;
613   struct gmon_hdr gmon_hdr;
614   struct gmon_hist_hdr hist_hdr;
615   uint32_t *narcsp;
616   size_t fromlimit;
617   struct here_cg_arc_record *data;
618   struct here_fromstruct *froms;
619   uint16_t *tos;
620   size_t fromidx;
621   size_t idx;
622
623   fd = open (name, O_RDONLY);
624   if (fd == -1)
625     {
626       char *ext_name;
627
628       if (errno != ENOENT || strchr (name, '/') != NULL)
629         /* The file exists but we are not allowed to read it or the
630            file does not exist and the name includes a path
631            specification..  */
632         return NULL;
633
634       /* A file with the given name does not exist in the current
635          directory, try it in the default location where the profiling
636          files are created.  */
637       ext_name = (char *) alloca (strlen (name) + sizeof "/var/tmp/");
638       stpcpy (stpcpy (ext_name, "/var/tmp/"), name);
639       name = ext_name;
640
641       fd = open (ext_name, O_RDONLY);
642       if (fd == -1)
643         {
644           /* Even this file does not exist.  */
645           error (0, errno, _("cannot load profiling data"));
646           return NULL;
647         }
648     }
649
650   /* We have found the file, now make sure it is the right one for the
651      data file.  */
652   if (fstat (fd, &st) < 0)
653     {
654       error (0, errno, _("while stat'ing profiling data file"));
655       close (fd);
656       return NULL;
657     }
658
659   if (st.st_size != shobj->expected_size)
660     {
661       error (0, 0, _("profiling data file `%s' does match shared object `%s'"),
662              name, shobj->name);
663       close (fd);
664       return NULL;
665     }
666
667   /* The data file is most probably the right one for our shared
668      object.  Map it now.  */
669   addr = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0);
670   if (addr == MAP_FAILED)
671     {
672       error (0, errno, _("failed to mmap the profiling data file"));
673       close (fd);
674       return NULL;
675     }
676
677   /* We don't need the file desriptor anymore.  */
678   if (close (fd) < 0)
679     {
680       error (0, errno, _("error while closing the profiling data file"));
681       munmap (addr, st.st_size);
682       return NULL;
683     }
684
685   /* Prepare the result.  */
686   result = (struct profdata *) calloc (1, sizeof (struct profdata));
687   if (result == NULL)
688     {
689       error (0, errno, _("cannot create internal descriptor"));
690       munmap (addr, st.st_size);
691       return NULL;
692     }
693
694   /* Store the address and size so that we can later free the resources.  */
695   result->addr = addr;
696   result->size = st.st_size;
697
698   /* Pointer to data after the header.  */
699   result->hist = (char *) ((struct gmon_hdr *) addr + 1);
700   result->kcount = (uint16_t *) ((char *) result->hist + sizeof (uint32_t)
701                                  + sizeof (struct gmon_hist_hdr));
702
703   /* Compute pointer to array of the arc information.  */
704   narcsp = (uint32_t *) ((char *) result->kcount + shobj->kcountsize
705                          + sizeof (uint32_t));
706   result->narcs = *narcsp;
707   result->data = (struct here_cg_arc_record *) ((char *) narcsp
708                                                 + sizeof (uint32_t));
709
710   /* Create the gmon_hdr we expect or write.  */
711   memset (&gmon_hdr, '\0', sizeof (struct gmon_hdr));
712   memcpy (&gmon_hdr.cookie[0], GMON_MAGIC, sizeof (gmon_hdr.cookie));
713   *(int32_t *) gmon_hdr.version = GMON_SHOBJ_VERSION;
714
715   /* Create the hist_hdr we expect or write.  */
716   *(char **) hist_hdr.low_pc = (char *) shobj->lowpc - shobj->map->l_addr;
717   *(char **) hist_hdr.high_pc = (char *) shobj->highpc - shobj->map->l_addr;
718   if (do_test)
719     printf ("low_pc = %p\nhigh_pc = %p\n",
720             hist_hdr.low_pc, hist_hdr.high_pc);
721   *(int32_t *) hist_hdr.hist_size = shobj->kcountsize / sizeof (HISTCOUNTER);
722   *(int32_t *) hist_hdr.prof_rate = __profile_frequency ();
723   strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen));
724   hist_hdr.dimen_abbrev = 's';
725
726   /* Test whether the header of the profiling data is ok.  */
727   if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0
728       || *(uint32_t *) result->hist != GMON_TAG_TIME_HIST
729       || memcmp (result->hist + sizeof (uint32_t), &hist_hdr,
730                  sizeof (struct gmon_hist_hdr)) != 0
731       || narcsp[-1] != GMON_TAG_CG_ARC)
732     {
733       free (result);
734       error (0, 0, _("`%s' is no correct profile data file for `%s'"),
735              name, shobj->name);
736       munmap (addr, st.st_size);
737       return NULL;
738     }
739
740   /* We are pretty sure now that this is a correct input file.  Set up
741      the remaining information in the result structure and return.  */
742   result->tos = (uint16_t *) calloc (shobj->tossize + shobj->fromssize, 1);
743   if (result->tos == NULL)
744     {
745       error (0, errno, _("cannot create internal descriptor"));
746       munmap (addr, st.st_size);
747       free (result);
748       return NULL;
749     }
750
751   result->froms = (struct here_fromstruct *) ((char *) result->tos
752                                               + shobj->tossize);
753   fromidx = 0;
754
755   /* Now we have to process all the arc count entries.  */
756   fromlimit = shobj->fromlimit;
757   data = result->data;
758   froms = result->froms;
759   tos = result->tos;
760   for (idx = 0; idx < MIN (*narcsp, fromlimit); ++idx)
761     {
762       size_t to_index;
763       size_t newfromidx;
764       to_index = (data[idx].self_pc / (shobj->hashfraction * sizeof (*tos)));
765       newfromidx = fromidx++;
766       froms[newfromidx].here = &data[idx];
767       froms[newfromidx].link = tos[to_index];
768       tos[to_index] = newfromidx;
769     }
770
771   return result;
772 }
773
774
775 static void
776 unload_profdata (struct profdata *profdata)
777 {
778   free (profdata->tos);
779   munmap (profdata->addr, profdata->size);
780   free (profdata);
781 }
782
783
784 static void
785 count_total_ticks (struct shobj *shobj, struct profdata *profdata)
786 {
787   volatile uint16_t *kcount = profdata->kcount;
788   size_t maxkidx = shobj->kcountsize;
789   size_t factor = 2 * (65536 / shobj->s_scale);
790   size_t kidx = 0;
791   size_t sidx = 0;
792
793   while (sidx < symidx)
794     {
795       uintptr_t start = sortsym[sidx]->addr;
796       uintptr_t end = start + sortsym[sidx]->size;
797
798       while (kidx < maxkidx && factor * kidx < start)
799         ++kidx;
800       if (kidx == maxkidx)
801         break;
802
803       while (kidx < maxkidx && factor * kidx < end)
804         sortsym[sidx]->ticks += kcount[kidx++];
805       if (kidx == maxkidx)
806         break;
807
808       total_ticks += sortsym[sidx++]->ticks;
809     }
810 }
811
812
813 static int
814 symorder (const void *o1, const void *o2)
815 {
816   const struct known_symbol *p1 = (struct known_symbol *) o1;
817   const struct known_symbol *p2 = (struct known_symbol *) o2;
818
819   return p1->addr - p2->addr;
820 }
821
822
823 static void
824 printsym (const void *node, VISIT value, int level)
825 {
826   if (value == leaf || value == postorder)
827     sortsym[symidx++] = *(const struct known_symbol **) node;
828 }
829
830
831 static void
832 read_symbols (struct shobj *shobj)
833 {
834   void *load_addr = (void *) shobj->map->l_addr;
835   int n = 0;
836   int idx;
837   const char *last_name = NULL;
838   uintptr_t last_addr = 0;
839
840   /* Initialize the obstacks.  */
841 #define obstack_chunk_alloc malloc
842 #define obstack_chunk_free free
843   obstack_init (&shobj->ob_str);
844   obstack_init (&shobj->ob_sym);
845
846   /* Process the stabs.  */
847   for (idx = 0; idx < shobj->stab_size; idx += 12)
848     if (*(shobj->stab + idx + TYPEOFF) == N_FUN)
849       {
850         const char *str = (shobj->stabstr
851                            + *((uint32_t *) (shobj->stab + idx + STRDXOFF)));
852
853         if (*str != '\0')
854           {
855             last_name = str;
856             last_addr = *((uint32_t *) (shobj->stab + idx + VALOFF));
857           }
858         else
859           {
860             const char *endp;
861             char *name0;
862             struct known_symbol *newsym;
863
864             if (last_name == NULL)
865               abort ();
866
867             endp = strchr (last_name, ':');
868
869             name0 = (char *) obstack_copy0 (&shobj->ob_str, last_name,
870                                             endp - last_name);
871             if (name0 != NULL)
872               newsym =
873                 (struct known_symbol *) obstack_alloc (&shobj->ob_sym,
874                                                        sizeof (*newsym));
875             else
876               /* Keep the stupid compiler happy.  */
877               newsym = NULL;
878             if (name0 == NULL || newsym == NULL)
879               error (EXIT_FAILURE, errno, _("cannot allocate symbol data"));
880
881             newsym->name = name0;
882             newsym->addr = last_addr;
883             newsym->size = *((uint32_t *) (shobj->stab + idx + VALOFF));
884             newsym->ticks = 0;
885
886             tsearch (newsym, &symroot, symorder);
887             ++n;
888
889             last_name = NULL;
890             last_addr = 0;
891           }
892       }
893
894   if (shobj->stab == NULL)
895     {
896       /* Blarg, the binary is stripped.  We have to rely on the
897          information contained in the dynamic section of the object.  */
898       const ElfW(Sym) *symtab = (load_addr
899                                  + shobj->map->l_info[DT_SYMTAB]->d_un.d_ptr);
900       const char *strtab = (load_addr
901                             + shobj->map->l_info[DT_STRTAB]->d_un.d_ptr);
902
903       /* We assume that the string table follows the symbol table,
904          because there is no way in ELF to know the size of the
905          dynamic symbol table!!  */
906       while ((void *) symtab < (void *) strtab)
907         {
908           if (/*(ELFW(ST_TYPE)(symtab->st_info) == STT_FUNC
909                 || ELFW(ST_TYPE)(symtab->st_info) == STT_NOTYPE)
910                 &&*/ symtab->st_size != 0)
911             {
912               struct known_symbol *newsym;
913
914               newsym =
915                 (struct known_symbol *) obstack_alloc (&shobj->ob_sym,
916                                                        sizeof (*newsym));
917               if (newsym == NULL)
918                 error (EXIT_FAILURE, errno, _("cannot allocate symbol data"));
919
920               newsym->name = &strtab[symtab->st_name];
921               newsym->addr = symtab->st_value;
922               newsym->size = symtab->st_size;
923               newsym->ticks = 0;
924
925               tsearch (newsym, &symroot, symorder);
926               ++n;
927             }
928         }
929
930       ++symtab;
931     }
932
933   sortsym = malloc (n * sizeof (struct known_symbol *));
934   if (sortsym == NULL)
935     abort ();
936
937   twalk (symroot, printsym);
938 }