f54a61657fd83963be5cf63af269196b729b9c3a
[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 <error.h>
25 #include <fcntl.h>
26 #include <inttypes.h>
27 #include <libintl.h>
28 #include <locale.h>
29 #include <obstack.h>
30 #include <search.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <elf/ldsodefs.h>
36 #include <sys/gmon.h>
37 #include <sys/gmon_out.h>
38 #include <sys/mman.h>
39 #include <sys/param.h>
40 #include <sys/stat.h>
41
42 /* Undefine the following line line in the production version.  */
43 /* #define _NDEBUG 1 */
44 #include <assert.h>
45
46 /* Get libc version number.  */
47 #include "../version.h"
48
49 #define PACKAGE _libc_intl_domainname
50
51
52 #include <endian.h>
53 #if BYTE_ORDER == BIG_ENDIAN
54 #define byteorder ELFDATA2MSB
55 #define byteorder_name "big-endian"
56 #elif BYTE_ORDER == LITTLE_ENDIAN
57 #define byteorder ELFDATA2LSB
58 #define byteorder_name "little-endian"
59 #else
60 #error "Unknown BYTE_ORDER " BYTE_ORDER
61 #define byteorder ELFDATANONE
62 #endif
63
64
65 extern int __profile_frequency __P ((void));
66
67 /* Name and version of program.  */
68 static void print_version (FILE *stream, struct argp_state *state);
69 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
70
71 #define OPT_TEST        1
72
73 /* Definitions of arguments for argp functions.  */
74 static const struct argp_option options[] =
75 {
76   { NULL, 0, NULL, 0, N_("Output selection:") },
77   { "flat-profile", 'p', NULL, 0,
78     N_("generate flat profile with counts and ticks") },
79   { "graph", 'q', NULL, 0, N_("generate call graph") },
80
81   { "test", OPT_TEST, NULL, OPTION_HIDDEN, NULL },
82   { NULL, 0, NULL, 0, NULL }
83 };
84
85 /* Short description of program.  */
86 static const char doc[] = N_("Read and display shared object profiling data");
87
88 /* Strings for arguments in help texts.  */
89 static const char args_doc[] = N_("SHOBJ [PROFDATA]");
90
91 /* Prototype for option handler.  */
92 static error_t parse_opt (int key, char *arg, struct argp_state *state);
93
94 /* Data structure to communicate with argp functions.  */
95 static struct argp argp =
96 {
97   options, parse_opt, args_doc, doc, NULL, NULL
98 };
99
100
101 /* Operation modes.  */
102 static enum
103 {
104   NONE = 0,
105   FLAT_MODE = 1 << 0,
106   CALL_GRAPH_MODE = 1 << 1,
107
108   DEFAULT_MODE = FLAT_MODE | CALL_GRAPH_MODE
109 } mode;
110
111 /* If nonzero the total number of invocations of a function is emitted.  */
112 int count_total;
113
114 /* Nozero for testing.  */
115 int do_test;
116
117 /* Strcuture describing calls.  */
118 struct here_fromstruct
119 {
120   struct here_cg_arc_record volatile *here;
121   uint16_t link;
122 };
123
124 /* We define a special type to address the elements of the arc table.
125    This is basically the `gmon_cg_arc_record' format but it includes
126    the room for the tag and it uses real types.  */
127 struct here_cg_arc_record
128 {
129   uintptr_t from_pc;
130   uintptr_t self_pc;
131   uint32_t count;
132 } __attribute__ ((packed));
133
134
135 struct known_symbol;
136 struct arc_list
137 {
138   size_t idx;
139   uintmax_t count;
140
141   struct arc_list *next;
142 };
143
144 static struct obstack ob_list;
145
146
147 struct known_symbol
148 {
149   const char *name;
150   uintptr_t addr;
151   size_t size;
152
153   uintmax_t ticks;
154   uintmax_t calls;
155
156   struct arc_list *froms;
157   struct arc_list *tos;
158 };
159
160
161 struct shobj
162 {
163   const char *name;             /* User-provided name.  */
164
165   struct link_map *map;
166   const char *dynstrtab;        /* Dynamic string table of shared object.  */
167   const char *soname;           /* Soname of shared object.  */
168
169   uintptr_t lowpc;
170   uintptr_t highpc;
171   unsigned long int kcountsize;
172   size_t expected_size;         /* Expected size of profiling file.  */
173   size_t tossize;
174   size_t fromssize;
175   size_t fromlimit;
176   unsigned int hashfraction;
177   int s_scale;
178
179   void *symbol_map;
180   size_t symbol_mapsize;
181   const ElfW(Sym) *symtab;
182   size_t symtab_size;
183   const char *strtab;
184
185   struct obstack ob_str;
186   struct obstack ob_sym;
187 };
188
189
190 struct profdata
191 {
192   void *addr;
193   off_t size;
194
195   char *hist;
196   struct gmon_hist_hdr *hist_hdr;
197   uint16_t *kcount;
198   uint32_t narcs;               /* Number of arcs in toset.  */
199   struct here_cg_arc_record *data;
200   uint16_t *tos;
201   struct here_fromstruct *froms;
202 };
203
204 /* Search tree for symbols.  */
205 void *symroot;
206 static struct known_symbol **sortsym;
207 static size_t symidx;
208 static uintmax_t total_ticks;
209
210 /* Prototypes for local functions.  */
211 static struct shobj *load_shobj (const char *name);
212 static void unload_shobj (struct shobj *shobj);
213 static struct profdata *load_profdata (const char *name, struct shobj *shobj);
214 static void unload_profdata (struct profdata *profdata);
215 static void count_total_ticks (struct shobj *shobj, struct profdata *profdata);
216 static void count_calls (struct shobj *shobj, struct profdata *profdata);
217 static void read_symbols (struct shobj *shobj);
218 static void add_arcs (struct profdata *profdata);
219 static void generate_flat_profile (struct profdata *profdata);
220 static void generate_call_graph (struct profdata *profdata);
221
222
223 int
224 main (int argc, char *argv[])
225 {
226   const char *shobj;
227   const char *profdata;
228   struct shobj *shobj_handle;
229   struct profdata *profdata_handle;
230   int remaining;
231
232   setlocale (LC_ALL, "");
233
234   /* Initialize the message catalog.  */
235   textdomain (_libc_intl_domainname);
236
237   /* Parse and process arguments.  */
238   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
239
240   if (argc - remaining == 0 || argc - remaining > 2)
241     {
242       /* We need exactly two non-option parameter.  */
243       argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
244                  program_invocation_short_name);
245       exit (1);
246     }
247
248   /* Get parameters.  */
249   shobj = argv[remaining];
250   if (argc - remaining == 2)
251     profdata = argv[remaining + 1];
252   else
253     /* No filename for the profiling data given.  We will determine it
254        from the soname of the shobj, later.  */
255     profdata = NULL;
256
257   /* First see whether we can load the shared object.  */
258   shobj_handle = load_shobj (shobj);
259   if (shobj_handle == NULL)
260     exit (1);
261
262   /* We can now determine the filename for the profiling data, if
263      nececessary.  */
264   if (profdata == NULL)
265     {
266       char *newp;
267
268       if (shobj_handle->soname == NULL)
269         {
270           unload_shobj (shobj_handle);
271
272           error (EXIT_FAILURE, 0, _("\
273 no filename for profiling data given and shared object `%s' has no soname"),
274                  shobj);
275         }
276
277       newp = (char *) alloca (strlen (shobj_handle->soname)
278                               + sizeof ".profile");
279       stpcpy (stpcpy (newp, shobj_handle->soname), ".profile");
280       profdata = newp;
281     }
282
283   /* Now see whether the profiling data file matches the given object.   */
284   profdata_handle = load_profdata (profdata, shobj_handle);
285   if (profdata_handle == NULL)
286     {
287       unload_shobj (shobj_handle);
288
289       exit (1);
290     }
291
292   read_symbols (shobj_handle);
293
294   /* Count the ticks.  */
295   count_total_ticks (shobj_handle, profdata_handle);
296
297   /* Count the calls.  */
298   count_calls (shobj_handle, profdata_handle);
299
300   /* Add the arc information.  */
301   add_arcs (profdata_handle);
302
303   /* If no mode is specified fall back to the default mode.  */
304   if (mode == NONE)
305     mode = DEFAULT_MODE;
306
307   /* Do some work.  */
308   if (mode & FLAT_MODE)
309     generate_flat_profile (profdata_handle);
310
311   if (mode & CALL_GRAPH_MODE)
312     generate_call_graph (profdata_handle);
313
314   /* Free the resources.  */
315   unload_shobj (shobj_handle);
316   unload_profdata (profdata_handle);
317
318   return 0;
319 }
320
321
322 /* Handle program arguments.  */
323 static error_t
324 parse_opt (int key, char *arg, struct argp_state *state)
325 {
326   switch (key)
327     {
328     case 'p':
329       mode |= FLAT_MODE;
330       break;
331     case 'q':
332       mode |= CALL_GRAPH_MODE;
333       break;
334     case OPT_TEST:
335       do_test = 1;
336       break;
337     default:
338       return ARGP_ERR_UNKNOWN;
339     }
340   return 0;
341 }
342
343
344 /* Print the version information.  */
345 static void
346 print_version (FILE *stream, struct argp_state *state)
347 {
348   fprintf (stream, "sprof (GNU %s) %s\n", PACKAGE, VERSION);
349   fprintf (stream, gettext ("\
350 Copyright (C) %s Free Software Foundation, Inc.\n\
351 This is free software; see the source for copying conditions.  There is NO\n\
352 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
353 "),
354            "1997, 1998");
355   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
356 }
357
358
359 /* Note that we must not use `dlopen' etc.  The shobj object must not
360    be loaded for use.  */
361 static struct shobj *
362 load_shobj (const char *name)
363 {
364   struct link_map *map = NULL;
365   struct shobj *result;
366   ElfW(Addr) mapstart = ~((ElfW(Addr)) 0);
367   ElfW(Addr) mapend = 0;
368   const ElfW(Phdr) *ph;
369   size_t textsize;
370   unsigned int log_hashfraction;
371   ElfW(Ehdr) *ehdr;
372   int fd;
373   ElfW(Shdr) *shdr;
374   void *ptr;
375   size_t pagesize = getpagesize ();
376   const char *shstrtab;
377   int idx;
378   ElfW(Shdr) *symtab_entry;
379
380   /* Since we use dlopen() we must be prepared to work around the sometimes
381      strange lookup rules for the shared objects.  If we have a file foo.so
382      in the current directory and the user specfies foo.so on the command
383      line (without specifying a directory) we should load the file in the
384      current directory even if a normal dlopen() call would read the other
385      file.  We do this by adding a directory portion to the name.  */
386   if (strchr (name, '/') == NULL)
387     {
388       char *load_name = (char *) alloca (strlen (name) + 3);
389       stpcpy (stpcpy (load_name, "./"), name);
390
391       map = (struct link_map *) dlopen (load_name, RTLD_LAZY);
392     }
393   if (map == NULL)
394     {
395       map = (struct link_map *) dlopen (name, RTLD_LAZY);
396       if (map == NULL)
397         {
398           error (0, errno, _("failed to load shared object `%s'"), name);
399           return NULL;
400         }
401     }
402
403   /* Prepare the result.  */
404   result = (struct shobj *) calloc (1, sizeof (struct shobj));
405   if (result == NULL)
406     {
407       error (0, errno, _("cannot create internal descriptors"));
408       dlclose (map);
409       return NULL;
410     }
411   result->name = name;
412   result->map = map;
413
414   /* Compute the size of the sections which contain program code.
415      This must match the code in dl-profile.c (_dl_start_profile).  */
416   for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
417     if (ph->p_type == PT_LOAD && (ph->p_flags & PF_X))
418       {
419         ElfW(Addr) start = (ph->p_vaddr & ~(pagesize - 1));
420         ElfW(Addr) end = ((ph->p_vaddr + ph->p_memsz + pagesize - 1)
421                           & ~(pagesize - 1));
422
423         if (start < mapstart)
424           mapstart = start;
425         if (end > mapend)
426           mapend = end;
427       }
428
429   result->lowpc = ROUNDDOWN ((uintptr_t) (mapstart + map->l_addr),
430                              HISTFRACTION * sizeof (HISTCOUNTER));
431   result->highpc = ROUNDUP ((uintptr_t) (mapend + map->l_addr),
432                             HISTFRACTION * sizeof (HISTCOUNTER));
433   if (do_test)
434     printf ("load addr: %0#*" PRIxPTR "\n"
435             "lower bound PC: %0#*" PRIxPTR "\n"
436             "upper bound PC: %0#*" PRIxPTR "\n",
437             __ELF_NATIVE_CLASS == 32 ? 10 : 18, map->l_addr,
438             __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->lowpc,
439             __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->highpc);
440
441   textsize = result->highpc - result->lowpc;
442   result->kcountsize = textsize / HISTFRACTION;
443   result->hashfraction = HASHFRACTION;
444   if ((HASHFRACTION & (HASHFRACTION - 1)) == 0)
445     /* If HASHFRACTION is a power of two, mcount can use shifting
446        instead of integer division.  Precompute shift amount.  */
447     log_hashfraction = __builtin_ffs (result->hashfraction
448                                       * sizeof (struct here_fromstruct)) - 1;
449   else
450     log_hashfraction = -1;
451   if (do_test)
452     printf ("hashfraction = %d\ndivider = %d\n",
453             result->hashfraction,
454             result->hashfraction * sizeof (struct here_fromstruct));
455   result->tossize = textsize / HASHFRACTION;
456   result->fromlimit = textsize * ARCDENSITY / 100;
457   if (result->fromlimit < MINARCS)
458     result->fromlimit = MINARCS;
459   if (result->fromlimit > MAXARCS)
460     result->fromlimit = MAXARCS;
461   result->fromssize = result->fromlimit * sizeof (struct here_fromstruct);
462
463   result->expected_size = (sizeof (struct gmon_hdr)
464                            + 4 + sizeof (struct gmon_hist_hdr)
465                            + result->kcountsize
466                            + 4 + 4
467                            + (result->fromssize
468                               * sizeof (struct here_cg_arc_record)));
469
470   if (do_test)
471     printf ("expected size: %Zd\n", result->expected_size);
472
473 #define SCALE_1_TO_1    0x10000L
474
475   if (result->kcountsize < result->highpc - result->lowpc)
476     {
477       size_t range = result->highpc - result->lowpc;
478       size_t quot = range / result->kcountsize;
479
480       if (quot >= SCALE_1_TO_1)
481         result->s_scale = 1;
482       else if (quot >= SCALE_1_TO_1 / 256)
483         result->s_scale = SCALE_1_TO_1 / quot;
484       else if (range > ULONG_MAX / 256)
485         result->s_scale = ((SCALE_1_TO_1 * 256)
486                            / (range / (result->kcountsize / 256)));
487       else
488         result->s_scale = ((SCALE_1_TO_1 * 256)
489                            / ((range * 256) / result->kcountsize));
490     }
491   else
492     result->s_scale = SCALE_1_TO_1;
493
494   if (do_test)
495     printf ("s_scale: %d\n", result->s_scale);
496
497   /* Determine the dynamic string table.  */
498   if (map->l_info[DT_STRTAB] == NULL)
499     result->dynstrtab = NULL;
500   else
501     result->dynstrtab = (const char *) (map->l_addr
502                                         + map->l_info[DT_STRTAB]->d_un.d_ptr);
503   if (do_test)
504     printf ("string table: %p\n", result->dynstrtab);
505
506   /* Determine the soname.  */
507   if (map->l_info[DT_SONAME] == NULL)
508     result->soname = NULL;
509   else
510     result->soname = result->dynstrtab + map->l_info[DT_SONAME]->d_un.d_val;
511   if (do_test)
512     printf ("soname: %s\n", result->soname);
513
514   /* Now we have to load the symbol table.
515
516      First load the section header table.  */
517   ehdr = (ElfW(Ehdr) *) map->l_addr;
518
519   /* Make sure we are on the right party.  */
520   if (ehdr->e_shentsize != sizeof (ElfW(Shdr)))
521     abort ();
522
523   /* And we need the shared object file descriptor again.  */
524   fd = open (map->l_name, O_RDONLY);
525   if (fd == -1)
526     /* Dooh, this really shouldn't happen.  We know the file is available.  */
527     error (EXIT_FAILURE, errno, _("Reopening shared object `%s' failed"));
528
529   /* Now map the section header.  */
530   ptr = mmap (NULL, (ehdr->e_shnum * sizeof (ElfW(Shdr))
531                      + (ehdr->e_shoff & (pagesize - 1))), PROT_READ,
532               MAP_SHARED|MAP_FILE, fd, ehdr->e_shoff & ~(pagesize - 1));
533   if (ptr == MAP_FAILED)
534     error (EXIT_FAILURE, errno, _("mapping of section headers failed"));
535   shdr = (ElfW(Shdr) *) ((char *) ptr + (ehdr->e_shoff & (pagesize - 1)));
536
537   /* Get the section header string table.  */
538   ptr = mmap (NULL, (shdr[ehdr->e_shstrndx].sh_size
539                      + (shdr[ehdr->e_shstrndx].sh_offset & (pagesize - 1))),
540               PROT_READ, MAP_SHARED|MAP_FILE, fd,
541               shdr[ehdr->e_shstrndx].sh_offset & ~(pagesize - 1));
542   if (ptr == MAP_FAILED)
543     error (EXIT_FAILURE, errno,
544            _("mapping of section header string table failed"));
545   shstrtab = ((const char *) ptr
546               + (shdr[ehdr->e_shstrndx].sh_offset & (pagesize - 1)));
547
548   /* Search for the ".symtab" section.  */
549   symtab_entry = NULL;
550   for (idx = 0; idx < ehdr->e_shnum; ++idx)
551     if (shdr[idx].sh_type == SHT_SYMTAB
552         && strcmp (shstrtab + shdr[idx].sh_name, ".symtab") == 0)
553       {
554         symtab_entry = &shdr[idx];
555         break;
556       }
557
558   /* We don't need the section header string table anymore.  */
559   munmap (ptr, (shdr[ehdr->e_shstrndx].sh_size
560                 + (shdr[ehdr->e_shstrndx].sh_offset & (pagesize - 1))));
561
562   if (symtab_entry == NULL)
563     {
564       fprintf (stderr, _("\
565 *** The file `%s' is stripped: no detailed analysis possible\n"),
566               name);
567       result->symtab = NULL;
568       result->strtab = NULL;
569     }
570   else
571     {
572       ElfW(Off) min_offset, max_offset;
573       ElfW(Shdr) *strtab_entry;
574
575       strtab_entry = &shdr[symtab_entry->sh_link];
576
577       /* Find the minimum and maximum offsets that include both the symbol
578          table and the string table.  */
579       if (symtab_entry->sh_offset < strtab_entry->sh_offset)
580         {
581           min_offset = symtab_entry->sh_offset & ~(pagesize - 1);
582           max_offset = strtab_entry->sh_offset + strtab_entry->sh_size;
583         }
584       else
585         {
586           min_offset = strtab_entry->sh_offset & ~(pagesize - 1);
587           max_offset = symtab_entry->sh_offset + symtab_entry->sh_size;
588         }
589
590       result->symbol_map = mmap (NULL, max_offset - min_offset,
591                                  PROT_READ, MAP_SHARED|MAP_FILE, fd,
592                                  min_offset);
593       if (result->symbol_map == NULL)
594         error (EXIT_FAILURE, errno, _("failed to load symbol data"));
595
596       result->symtab
597         = (const ElfW(Sym) *) ((const char *) result->symbol_map
598                                + (symtab_entry->sh_offset - min_offset));
599       result->symtab_size = symtab_entry->sh_size;
600       result->strtab = ((const char *) result->symbol_map
601                         + (strtab_entry->sh_offset - min_offset));
602       result->symbol_mapsize = max_offset - min_offset;
603     }
604
605   /* Now we also don't need the section header table anymore.  */
606   munmap ((char *) shdr - (ehdr->e_shoff & (pagesize - 1)),
607           (ehdr->e_phnum * sizeof (ElfW(Shdr))
608            + (ehdr->e_shoff & (pagesize - 1))));
609
610   /* Free the descriptor for the shared object.  */
611   close (fd);
612
613   return result;
614 }
615
616
617 static void
618 unload_shobj (struct shobj *shobj)
619 {
620   munmap (shobj->symbol_map, shobj->symbol_mapsize);
621   dlclose (shobj->map);
622 }
623
624
625 static struct profdata *
626 load_profdata (const char *name, struct shobj *shobj)
627 {
628   struct profdata *result;
629   int fd;
630   struct stat st;
631   void *addr;
632   struct gmon_hdr gmon_hdr;
633   struct gmon_hist_hdr hist_hdr;
634   uint32_t *narcsp;
635   size_t fromlimit;
636   struct here_cg_arc_record *data;
637   struct here_fromstruct *froms;
638   uint16_t *tos;
639   size_t fromidx;
640   size_t idx;
641
642   fd = open (name, O_RDONLY);
643   if (fd == -1)
644     {
645       char *ext_name;
646
647       if (errno != ENOENT || strchr (name, '/') != NULL)
648         /* The file exists but we are not allowed to read it or the
649            file does not exist and the name includes a path
650            specification..  */
651         return NULL;
652
653       /* A file with the given name does not exist in the current
654          directory, try it in the default location where the profiling
655          files are created.  */
656       ext_name = (char *) alloca (strlen (name) + sizeof "/var/tmp/");
657       stpcpy (stpcpy (ext_name, "/var/tmp/"), name);
658       name = ext_name;
659
660       fd = open (ext_name, O_RDONLY);
661       if (fd == -1)
662         {
663           /* Even this file does not exist.  */
664           error (0, errno, _("cannot load profiling data"));
665           return NULL;
666         }
667     }
668
669   /* We have found the file, now make sure it is the right one for the
670      data file.  */
671   if (fstat (fd, &st) < 0)
672     {
673       error (0, errno, _("while stat'ing profiling data file"));
674       close (fd);
675       return NULL;
676     }
677
678   if (st.st_size != shobj->expected_size)
679     {
680       error (0, 0, _("profiling data file `%s' does match shared object `%s'"),
681              name, shobj->name);
682       close (fd);
683       return NULL;
684     }
685
686   /* The data file is most probably the right one for our shared
687      object.  Map it now.  */
688   addr = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0);
689   if (addr == MAP_FAILED)
690     {
691       error (0, errno, _("failed to mmap the profiling data file"));
692       close (fd);
693       return NULL;
694     }
695
696   /* We don't need the file desriptor anymore.  */
697   if (close (fd) < 0)
698     {
699       error (0, errno, _("error while closing the profiling data file"));
700       munmap (addr, st.st_size);
701       return NULL;
702     }
703
704   /* Prepare the result.  */
705   result = (struct profdata *) calloc (1, sizeof (struct profdata));
706   if (result == NULL)
707     {
708       error (0, errno, _("cannot create internal descriptor"));
709       munmap (addr, st.st_size);
710       return NULL;
711     }
712
713   /* Store the address and size so that we can later free the resources.  */
714   result->addr = addr;
715   result->size = st.st_size;
716
717   /* Pointer to data after the header.  */
718   result->hist = (char *) ((struct gmon_hdr *) addr + 1);
719   result->hist_hdr = (struct gmon_hist_hdr *) ((char *) result->hist
720                                                + sizeof (uint32_t));
721   result->kcount = (uint16_t *) ((char *) result->hist + sizeof (uint32_t)
722                                  + sizeof (struct gmon_hist_hdr));
723
724   /* Compute pointer to array of the arc information.  */
725   narcsp = (uint32_t *) ((char *) result->kcount + shobj->kcountsize
726                          + sizeof (uint32_t));
727   result->narcs = *narcsp;
728   result->data = (struct here_cg_arc_record *) ((char *) narcsp
729                                                 + sizeof (uint32_t));
730
731   /* Create the gmon_hdr we expect or write.  */
732   memset (&gmon_hdr, '\0', sizeof (struct gmon_hdr));
733   memcpy (&gmon_hdr.cookie[0], GMON_MAGIC, sizeof (gmon_hdr.cookie));
734   *(int32_t *) gmon_hdr.version = GMON_SHOBJ_VERSION;
735
736   /* Create the hist_hdr we expect or write.  */
737   *(char **) hist_hdr.low_pc = (char *) shobj->lowpc - shobj->map->l_addr;
738   *(char **) hist_hdr.high_pc = (char *) shobj->highpc - shobj->map->l_addr;
739   if (do_test)
740     printf ("low_pc = %p\nhigh_pc = %p\n",
741             *(char **) hist_hdr.low_pc, *(char **) hist_hdr.high_pc);
742   *(int32_t *) hist_hdr.hist_size = shobj->kcountsize / sizeof (HISTCOUNTER);
743   *(int32_t *) hist_hdr.prof_rate = __profile_frequency ();
744   strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen));
745   hist_hdr.dimen_abbrev = 's';
746
747   /* Test whether the header of the profiling data is ok.  */
748   if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0
749       || *(uint32_t *) result->hist != GMON_TAG_TIME_HIST
750       || memcmp (result->hist_hdr, &hist_hdr,
751                  sizeof (struct gmon_hist_hdr)) != 0
752       || narcsp[-1] != GMON_TAG_CG_ARC)
753     {
754       free (result);
755       error (0, 0, _("`%s' is no correct profile data file for `%s'"),
756              name, shobj->name);
757       munmap (addr, st.st_size);
758       return NULL;
759     }
760
761   /* We are pretty sure now that this is a correct input file.  Set up
762      the remaining information in the result structure and return.  */
763   result->tos = (uint16_t *) calloc (shobj->tossize + shobj->fromssize, 1);
764   if (result->tos == NULL)
765     {
766       error (0, errno, _("cannot create internal descriptor"));
767       munmap (addr, st.st_size);
768       free (result);
769       return NULL;
770     }
771
772   result->froms = (struct here_fromstruct *) ((char *) result->tos
773                                               + shobj->tossize);
774   fromidx = 0;
775
776   /* Now we have to process all the arc count entries.  */
777   fromlimit = shobj->fromlimit;
778   data = result->data;
779   froms = result->froms;
780   tos = result->tos;
781   for (idx = 0; idx < MIN (*narcsp, fromlimit); ++idx)
782     {
783       size_t to_index;
784       size_t newfromidx;
785       to_index = (data[idx].self_pc / (shobj->hashfraction * sizeof (*tos)));
786       newfromidx = fromidx++;
787       froms[newfromidx].here = &data[idx];
788       froms[newfromidx].link = tos[to_index];
789       tos[to_index] = newfromidx;
790     }
791
792   return result;
793 }
794
795
796 static void
797 unload_profdata (struct profdata *profdata)
798 {
799   free (profdata->tos);
800   munmap (profdata->addr, profdata->size);
801   free (profdata);
802 }
803
804
805 static void
806 count_total_ticks (struct shobj *shobj, struct profdata *profdata)
807 {
808   volatile uint16_t *kcount = profdata->kcount;
809   size_t maxkidx = shobj->kcountsize;
810   size_t factor = 2 * (65536 / shobj->s_scale);
811   size_t kidx = 0;
812   size_t sidx = 0;
813
814   while (sidx < symidx)
815     {
816       uintptr_t start = sortsym[sidx]->addr;
817       uintptr_t end = start + sortsym[sidx]->size;
818
819       while (kidx < maxkidx && factor * kidx < start)
820         ++kidx;
821       if (kidx == maxkidx)
822         break;
823
824       while (kidx < maxkidx && factor * kidx < end)
825         sortsym[sidx]->ticks += kcount[kidx++];
826       if (kidx == maxkidx)
827         break;
828
829       total_ticks += sortsym[sidx++]->ticks;
830     }
831 }
832
833
834 static size_t
835 find_symbol (uintptr_t addr)
836 {
837   size_t sidx = 0;
838
839   while (sidx < symidx)
840     {
841       uintptr_t start = sortsym[sidx]->addr;
842       uintptr_t end = start + sortsym[sidx]->size;
843
844       if (addr >= start && addr < end)
845         return sidx;
846
847       if (addr < start)
848         break;
849
850       ++sidx;
851     }
852
853   return (size_t) -1l;
854 }
855
856
857 static void
858 count_calls (struct shobj *shobj, struct profdata *profdata)
859 {
860   struct here_cg_arc_record *data = profdata->data;
861   uint32_t narcs = profdata->narcs;
862   uint32_t cnt;
863
864   for (cnt = 0; cnt < narcs; ++cnt)
865     {
866       uintptr_t here = data[cnt].self_pc;
867       size_t symbol_idx;
868
869       /* Find the symbol for this address.  */
870       symbol_idx = find_symbol (here);
871       if (symbol_idx != (size_t) -1l)
872         sortsym[symbol_idx]->calls += data[cnt].count;
873     }
874 }
875
876
877 static int
878 symorder (const void *o1, const void *o2)
879 {
880   const struct known_symbol *p1 = (const struct known_symbol *) o1;
881   const struct known_symbol *p2 = (const struct known_symbol *) o2;
882
883   return p1->addr - p2->addr;
884 }
885
886
887 static void
888 printsym (const void *node, VISIT value, int level)
889 {
890   if (value == leaf || value == postorder)
891     sortsym[symidx++] = *(struct known_symbol **) node;
892 }
893
894
895 static void
896 read_symbols (struct shobj *shobj)
897 {
898   void *load_addr = (void *) shobj->map->l_addr;
899   int n = 0;
900
901   /* Initialize the obstacks.  */
902 #define obstack_chunk_alloc malloc
903 #define obstack_chunk_free free
904   obstack_init (&shobj->ob_str);
905   obstack_init (&shobj->ob_sym);
906   obstack_init (&ob_list);
907
908   /* Process the symbols.  */
909   if (shobj->symtab)
910     {
911       const ElfW(Sym) *sym = shobj->symtab;
912       const ElfW(Sym) *sym_end
913         = (const ElfW(Sym) *) ((const char *) sym + shobj->symtab_size);
914       for (; sym < sym_end; sym++)
915         if ((ELFW(ST_TYPE) (sym->st_info) == STT_FUNC
916              || ELFW(ST_TYPE) (sym->st_info) == STT_NOTYPE)
917             && sym->st_size != 0)
918           {
919             struct known_symbol **existp;
920             struct known_symbol *newsym
921               = (struct known_symbol *) obstack_alloc (&shobj->ob_sym,
922                                                        sizeof (*newsym));
923             if (newsym == NULL)
924               error (EXIT_FAILURE, errno, _("cannot allocate symbol data"));
925
926             newsym->name = &shobj->strtab[sym->st_name];
927             newsym->addr = sym->st_value;
928             newsym->size = sym->st_size;
929             newsym->ticks = 0;
930             newsym->calls = 0;
931
932             existp = tfind (newsym, &symroot, symorder);
933             if (existp == NULL)
934               {
935                 /* New function.  */
936                 tsearch (newsym, &symroot, symorder);
937                 ++n;
938               }
939             else
940               {
941                 /* The function is already defined.  See whether we have
942                    a better name here.  */
943                 if ((*existp)->name[0] == '_' && newsym->name[0] != '_')
944                   *existp = newsym;
945                 else
946                   /* We don't need the allocated memory.  */
947                   obstack_free (&shobj->ob_sym, newsym);
948               }
949           }
950     }
951   else
952     {
953       /* Blarg, the binary is stripped.  We have to rely on the
954          information contained in the dynamic section of the object.  */
955       const ElfW(Sym) *symtab = (load_addr
956                                  + shobj->map->l_info[DT_SYMTAB]->d_un.d_ptr);
957       const char *strtab = (load_addr
958                             + shobj->map->l_info[DT_STRTAB]->d_un.d_ptr);
959
960       /* We assume that the string table follows the symbol table,
961          because there is no way in ELF to know the size of the
962          dynamic symbol table!!  */
963       while ((void *) symtab < (void *) strtab)
964         {
965           if ((ELFW(ST_TYPE)(symtab->st_info) == STT_FUNC
966                || ELFW(ST_TYPE)(symtab->st_info) == STT_NOTYPE)
967               && symtab->st_size != 0)
968             {
969               struct known_symbol *newsym;
970               struct known_symbol **existp;
971
972               newsym =
973                 (struct known_symbol *) obstack_alloc (&shobj->ob_sym,
974                                                        sizeof (*newsym));
975               if (newsym == NULL)
976                 error (EXIT_FAILURE, errno, _("cannot allocate symbol data"));
977
978               newsym->name = &strtab[symtab->st_name];
979               newsym->addr = symtab->st_value;
980               newsym->size = symtab->st_size;
981               newsym->ticks = 0;
982               newsym->froms = NULL;
983               newsym->tos = NULL;
984
985               existp = tfind (newsym, &symroot, symorder);
986               if (existp == NULL)
987                 {
988                   /* New function.  */
989                   tsearch (newsym, &symroot, symorder);
990                   ++n;
991                 }
992               else
993                 {
994                   /* The function is already defined.  See whether we have
995                      a better name here.  */
996                   if ((*existp)->name[0] == '_' && newsym->name[0] != '_')
997                     *existp = newsym;
998                   else
999                     /* We don't need the allocated memory.  */
1000                     obstack_free (&shobj->ob_sym, newsym);
1001                 }
1002             }
1003         }
1004
1005       ++symtab;
1006     }
1007
1008   sortsym = malloc (n * sizeof (struct known_symbol *));
1009   if (sortsym == NULL)
1010     abort ();
1011
1012   twalk (symroot, printsym);
1013 }
1014
1015
1016 static void
1017 add_arcs (struct profdata *profdata)
1018 {
1019   uint32_t narcs = profdata->narcs;
1020   struct here_cg_arc_record *data = profdata->data;
1021   uint32_t cnt;
1022
1023   for (cnt = 0; cnt < narcs; ++cnt)
1024     {
1025       /* First add the incoming arc.  */
1026       size_t sym_idx = find_symbol (data[cnt].self_pc);
1027
1028       if (sym_idx != (size_t) -1l)
1029         {
1030           struct known_symbol *sym = sortsym[sym_idx];
1031           struct arc_list *runp = sym->froms;
1032
1033           while (runp != NULL
1034                  && ((data[cnt].from_pc == 0 && runp->idx != (size_t) -1l)
1035                      || (data[cnt].from_pc != 0
1036                          && (runp->idx == (size_t) -1l
1037                              || data[cnt].from_pc < sortsym[runp->idx]->addr
1038                              || (data[cnt].from_pc
1039                                  >= (sortsym[runp->idx]->addr
1040                                      + sortsym[runp->idx]->size))))))
1041             runp = runp->next;
1042
1043           if (runp == NULL)
1044             {
1045               /* We need a new entry.  */
1046               struct arc_list *newp = (struct arc_list *)
1047                 obstack_alloc (&ob_list, sizeof (struct arc_list));
1048
1049               if (data[cnt].from_pc == 0)
1050                 newp->idx = (size_t) -1l;
1051               else
1052                 newp->idx = find_symbol (data[cnt].from_pc);
1053               newp->count = data[cnt].count;
1054               newp->next = sym->froms;
1055               sym->froms = newp;
1056             }
1057           else
1058             /* Increment the counter for the found entry.  */
1059             runp->count += data[cnt].count;
1060         }
1061
1062       /* Now add it to the appropriate outgoing list.  */
1063       sym_idx = find_symbol (data[cnt].from_pc);
1064       if (sym_idx != (size_t) -1l)
1065         {
1066           struct known_symbol *sym = sortsym[sym_idx];
1067           struct arc_list *runp = sym->tos;
1068
1069           while (runp != NULL
1070                  && (runp->idx == (size_t) -1l
1071                      || data[cnt].self_pc < sortsym[runp->idx]->addr
1072                      || data[cnt].self_pc >= (sortsym[runp->idx]->addr
1073                                               + sortsym[runp->idx]->size)))
1074             runp = runp->next;
1075
1076           if (runp == NULL)
1077             {
1078               /* We need a new entry.  */
1079               struct arc_list *newp = (struct arc_list *)
1080                 obstack_alloc (&ob_list, sizeof (struct arc_list));
1081
1082               newp->idx = find_symbol (data[cnt].self_pc);
1083               newp->count = data[cnt].count;
1084               newp->next = sym->tos;
1085               sym->tos = newp;
1086             }
1087           else
1088             /* Increment the counter for the found entry.  */
1089             runp->count += data[cnt].count;
1090         }
1091     }
1092 }
1093
1094
1095 static int
1096 countorder (const void *p1, const void *p2)
1097 {
1098   struct known_symbol *s1 = (struct known_symbol *) p1;
1099   struct known_symbol *s2 = (struct known_symbol *) p2;
1100
1101   if (s1->ticks != s2->ticks)
1102     return (int) (s2->ticks - s1->ticks);
1103
1104   if (s1->calls != s2->calls)
1105     return (int) (s2->calls - s1->calls);
1106
1107   return strcmp (s1->name, s2->name);
1108 }
1109
1110
1111 static double tick_unit;
1112 static uintmax_t cumu_ticks;
1113
1114 static void
1115 printflat (const void *node, VISIT value, int level)
1116 {
1117   if (value == leaf || value == postorder)
1118     {
1119       struct known_symbol *s = *(struct known_symbol **) node;
1120
1121       cumu_ticks += s->ticks;
1122
1123       printf ("%6.2f%10.2f%9.2f%9" PRIdMAX "%9.2f           %s\n",
1124               total_ticks ? (100.0 * s->ticks) / total_ticks : 0.0,
1125               tick_unit * cumu_ticks,
1126               tick_unit * s->ticks,
1127               s->calls,
1128               s->calls ? (s->ticks * 1000000) * tick_unit / s->calls : 0,
1129               /* FIXME: don't know about called functions.  */
1130               s->name);
1131     }
1132 }
1133
1134
1135 /* ARGUSED */
1136 static void
1137 freenoop (void *p)
1138 {
1139 }
1140
1141
1142 static void
1143 generate_flat_profile (struct profdata *profdata)
1144 {
1145   size_t n;
1146   void *data = NULL;
1147
1148   tick_unit = 1.0 / *(uint32_t *) profdata->hist_hdr->prof_rate;
1149
1150   printf ("Flat profile:\n\n"
1151           "Each sample counts as %g %s.\n",
1152           tick_unit, profdata->hist_hdr->dimen);
1153   fputs ("  %   cumulative   self              self     total\n"
1154          " time   seconds   seconds    calls  us/call  us/call  name\n",
1155          stdout);
1156
1157   for (n = 0; n < symidx; ++n)
1158     if (sortsym[n]->calls != 0 || sortsym[n]->ticks != 0)
1159       tsearch (sortsym[n], &data, countorder);
1160
1161   twalk (data, printflat);
1162
1163   tdestroy (data, freenoop);
1164 }
1165
1166
1167 static void
1168 generate_call_graph (struct profdata *profdata)
1169 {
1170   size_t cnt;
1171
1172   puts ("\nindex % time    self  children    called     name\n");
1173
1174   for (cnt = 0; cnt < symidx; ++cnt)
1175     if (sortsym[cnt]->froms != NULL || sortsym[cnt]->tos != NULL)
1176       {
1177         struct arc_list *runp;
1178         size_t n;
1179
1180         /* First print the from-information.  */
1181         runp = sortsym[cnt]->froms;
1182         while (runp != NULL)
1183           {
1184             printf ("            %8.2f%8.2f%9" PRIdMAX "/%-9" PRIdMAX "   %s",
1185                     (runp->idx != (size_t) -1l
1186                      ? sortsym[runp->idx]->ticks * tick_unit : 0.0),
1187                     0.0, /* FIXME: what's time for the childern, recursive */
1188                     runp->count, sortsym[cnt]->calls,
1189                     (runp->idx != (size_t) -1l ?
1190                      sortsym[runp->idx]->name : "<UNKNOWN>"));
1191
1192             if (runp->idx != (size_t) -1l)
1193               printf (" [%Zd]", runp->idx);
1194             putchar_unlocked ('\n');
1195
1196             runp = runp->next;
1197           }
1198
1199         /* Info abount the function itself.  */
1200         n = printf ("[%d]", cnt);
1201         printf ("%*s%5.1f%8.2f%8.2f%9" PRIdMAX "         %s [%Zd]\n",
1202                 7 - n, " ",
1203                 total_ticks ? (100.0 * sortsym[cnt]->ticks) / total_ticks : 0,
1204                 sortsym[cnt]->ticks * tick_unit,
1205                 0.0, /* FIXME: what's time for the childern, recursive */
1206                 sortsym[cnt]->calls,
1207                 sortsym[cnt]->name, cnt);
1208
1209         /* Info about the functions this function calls.  */
1210         runp = sortsym[cnt]->tos;
1211         while (runp != NULL)
1212           {
1213             printf ("            %8.2f%8.2f%9" PRIdMAX "/",
1214                     (runp->idx != (size_t) -1l
1215                      ? sortsym[runp->idx]->ticks * tick_unit : 0.0),
1216                     0.0, /* FIXME: what's time for the childern, recursive */
1217                     runp->count);
1218
1219             if (runp->idx != (size_t) -1l)
1220               printf ("%-9" PRIdMAX "   %s [%Zd]\n",
1221                       sortsym[runp->idx]->calls,
1222                       sortsym[runp->idx]->name,
1223                       runp->idx);
1224             else
1225               fputs ("???         <UNKNOWN>\n\n", stdout);
1226
1227             runp = runp->next;
1228           }
1229
1230         fputs ("-----------------------------------------------\n", stdout);
1231       }
1232 }