Fix grouping and reuse other locales in various locales
[glibc.git] / elf / sprof.c
blobc90c22c26556ecd4a778869503c73e7a219290cf
1 /* Read and display shared object profiling data.
2 Copyright (C) 1997-2008, 2009, 2010, 2011 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
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 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
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 <stdbool.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <ldsodefs.h>
37 #include <sys/gmon.h>
38 #include <sys/gmon_out.h>
39 #include <sys/mman.h>
40 #include <sys/param.h>
41 #include <sys/stat.h>
43 /* Get libc version number. */
44 #include "../version.h"
46 #define PACKAGE _libc_intl_domainname
49 #include <endian.h>
50 #if BYTE_ORDER == BIG_ENDIAN
51 # define byteorder ELFDATA2MSB
52 # define byteorder_name "big-endian"
53 #elif BYTE_ORDER == LITTLE_ENDIAN
54 # define byteorder ELFDATA2LSB
55 # define byteorder_name "little-endian"
56 #else
57 # error "Unknown BYTE_ORDER " BYTE_ORDER
58 # define byteorder ELFDATANONE
59 #endif
61 #ifndef PATH_MAX
62 # define PATH_MAX 1024
63 #endif
66 extern int __profile_frequency (void);
68 /* Name and version of program. */
69 static void print_version (FILE *stream, struct argp_state *state);
70 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
72 #define OPT_TEST 1
74 /* Definitions of arguments for argp functions. */
75 static const struct argp_option options[] =
77 { NULL, 0, NULL, 0, N_("Output selection:") },
78 { "call-pairs", 'c', NULL, 0,
79 N_("print list of count paths and their number of use") },
80 { "flat-profile", 'p', NULL, 0,
81 N_("generate flat profile with counts and ticks") },
82 { "graph", 'q', NULL, 0, N_("generate call graph") },
84 { "test", OPT_TEST, NULL, OPTION_HIDDEN, NULL },
85 { NULL, 0, NULL, 0, NULL }
88 /* Short description of program. */
89 static const char doc[] = N_("Read and display shared object profiling data.");
90 //For bug reporting instructions, please see:\n
91 //<http://www.gnu.org/software/libc/bugs.html>.\n");
93 /* Strings for arguments in help texts. */
94 static const char args_doc[] = N_("SHOBJ [PROFDATA]");
96 /* Prototype for option handler. */
97 static error_t parse_opt (int key, char *arg, struct argp_state *state);
99 /* Function to print some extra text in the help message. */
100 static char *more_help (int key, const char *text, void *input);
102 /* Data structure to communicate with argp functions. */
103 static struct argp argp =
105 options, parse_opt, args_doc, doc, NULL, more_help
109 /* Operation modes. */
110 static enum
112 NONE = 0,
113 FLAT_MODE = 1 << 0,
114 CALL_GRAPH_MODE = 1 << 1,
115 CALL_PAIRS = 1 << 2,
117 DEFAULT_MODE = FLAT_MODE | CALL_GRAPH_MODE
118 } mode;
120 /* Nozero for testing. */
121 static int do_test;
123 /* Strcuture describing calls. */
124 struct here_fromstruct
126 struct here_cg_arc_record volatile *here;
127 uint16_t link;
130 /* We define a special type to address the elements of the arc table.
131 This is basically the `gmon_cg_arc_record' format but it includes
132 the room for the tag and it uses real types. */
133 struct here_cg_arc_record
135 uintptr_t from_pc;
136 uintptr_t self_pc;
137 uint32_t count;
138 } __attribute__ ((packed));
141 struct known_symbol;
142 struct arc_list
144 size_t idx;
145 uintmax_t count;
147 struct arc_list *next;
150 static struct obstack ob_list;
153 struct known_symbol
155 const char *name;
156 uintptr_t addr;
157 size_t size;
158 bool weak;
159 bool hidden;
161 uintmax_t ticks;
162 uintmax_t calls;
164 struct arc_list *froms;
165 struct arc_list *tos;
169 struct shobj
171 const char *name; /* User-provided name. */
173 struct link_map *map;
174 const char *dynstrtab; /* Dynamic string table of shared object. */
175 const char *soname; /* Soname of shared object. */
177 uintptr_t lowpc;
178 uintptr_t highpc;
179 unsigned long int kcountsize;
180 size_t expected_size; /* Expected size of profiling file. */
181 size_t tossize;
182 size_t fromssize;
183 size_t fromlimit;
184 unsigned int hashfraction;
185 int s_scale;
187 void *symbol_map;
188 size_t symbol_mapsize;
189 const ElfW(Sym) *symtab;
190 size_t symtab_size;
191 const char *strtab;
193 struct obstack ob_str;
194 struct obstack ob_sym;
198 struct real_gmon_hist_hdr
200 char *low_pc;
201 char *high_pc;
202 int32_t hist_size;
203 int32_t prof_rate;
204 char dimen[15];
205 char dimen_abbrev;
209 struct profdata
211 void *addr;
212 off_t size;
214 char *hist;
215 struct real_gmon_hist_hdr *hist_hdr;
216 uint16_t *kcount;
217 uint32_t narcs; /* Number of arcs in toset. */
218 struct here_cg_arc_record *data;
219 uint16_t *tos;
220 struct here_fromstruct *froms;
223 /* Search tree for symbols. */
224 static void *symroot;
225 static struct known_symbol **sortsym;
226 static size_t symidx;
227 static uintmax_t total_ticks;
229 /* Prototypes for local functions. */
230 static struct shobj *load_shobj (const char *name);
231 static void unload_shobj (struct shobj *shobj);
232 static struct profdata *load_profdata (const char *name, struct shobj *shobj);
233 static void unload_profdata (struct profdata *profdata);
234 static void count_total_ticks (struct shobj *shobj, struct profdata *profdata);
235 static void count_calls (struct shobj *shobj, struct profdata *profdata);
236 static void read_symbols (struct shobj *shobj);
237 static void add_arcs (struct profdata *profdata);
238 static void generate_flat_profile (struct profdata *profdata);
239 static void generate_call_graph (struct profdata *profdata);
240 static void generate_call_pair_list (struct profdata *profdata);
244 main (int argc, char *argv[])
246 const char *shobj;
247 const char *profdata;
248 struct shobj *shobj_handle;
249 struct profdata *profdata_handle;
250 int remaining;
252 setlocale (LC_ALL, "");
254 /* Initialize the message catalog. */
255 textdomain (_libc_intl_domainname);
257 /* Parse and process arguments. */
258 argp_parse (&argp, argc, argv, 0, &remaining, NULL);
260 if (argc - remaining == 0 || argc - remaining > 2)
262 /* We need exactly two non-option parameter. */
263 argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
264 program_invocation_short_name);
265 exit (1);
268 /* Get parameters. */
269 shobj = argv[remaining];
270 if (argc - remaining == 2)
271 profdata = argv[remaining + 1];
272 else
273 /* No filename for the profiling data given. We will determine it
274 from the soname of the shobj, later. */
275 profdata = NULL;
277 /* First see whether we can load the shared object. */
278 shobj_handle = load_shobj (shobj);
279 if (shobj_handle == NULL)
280 exit (1);
282 /* We can now determine the filename for the profiling data, if
283 nececessary. */
284 if (profdata == NULL)
286 char *newp;
287 const char *soname;
288 size_t soname_len;
290 soname = shobj_handle->soname ?: basename (shobj);
291 soname_len = strlen (soname);
292 newp = (char *) alloca (soname_len + sizeof ".profile");
293 stpcpy (mempcpy (newp, soname, soname_len), ".profile");
294 profdata = newp;
297 /* Now see whether the profiling data file matches the given object. */
298 profdata_handle = load_profdata (profdata, shobj_handle);
299 if (profdata_handle == NULL)
301 unload_shobj (shobj_handle);
303 exit (1);
306 read_symbols (shobj_handle);
308 /* Count the ticks. */
309 count_total_ticks (shobj_handle, profdata_handle);
311 /* Count the calls. */
312 count_calls (shobj_handle, profdata_handle);
314 /* Add the arc information. */
315 add_arcs (profdata_handle);
317 /* If no mode is specified fall back to the default mode. */
318 if (mode == NONE)
319 mode = DEFAULT_MODE;
321 /* Do some work. */
322 if (mode & FLAT_MODE)
323 generate_flat_profile (profdata_handle);
325 if (mode & CALL_GRAPH_MODE)
326 generate_call_graph (profdata_handle);
328 if (mode & CALL_PAIRS)
329 generate_call_pair_list (profdata_handle);
331 /* Free the resources. */
332 unload_shobj (shobj_handle);
333 unload_profdata (profdata_handle);
335 return 0;
339 /* Handle program arguments. */
340 static error_t
341 parse_opt (int key, char *arg, struct argp_state *state)
343 switch (key)
345 case 'c':
346 mode |= CALL_PAIRS;
347 break;
348 case 'p':
349 mode |= FLAT_MODE;
350 break;
351 case 'q':
352 mode |= CALL_GRAPH_MODE;
353 break;
354 case OPT_TEST:
355 do_test = 1;
356 break;
357 default:
358 return ARGP_ERR_UNKNOWN;
360 return 0;
364 static char *
365 more_help (int key, const char *text, void *input)
367 switch (key)
369 case ARGP_KEY_HELP_EXTRA:
370 /* We print some extra information. */
371 return strdup (gettext ("\
372 For bug reporting instructions, please see:\n\
373 <http://www.gnu.org/software/libc/bugs.html>.\n"));
374 default:
375 break;
377 return (char *) text;
381 /* Print the version information. */
382 static void
383 print_version (FILE *stream, struct argp_state *state)
385 fprintf (stream, "sprof (GNU %s) %s\n", PACKAGE, VERSION);
386 fprintf (stream, gettext ("\
387 Copyright (C) %s Free Software Foundation, Inc.\n\
388 This is free software; see the source for copying conditions. There is NO\n\
389 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
391 "2011");
392 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
396 /* Note that we must not use `dlopen' etc. The shobj object must not
397 be loaded for use. */
398 static struct shobj *
399 load_shobj (const char *name)
401 struct link_map *map = NULL;
402 struct shobj *result;
403 ElfW(Addr) mapstart = ~((ElfW(Addr)) 0);
404 ElfW(Addr) mapend = 0;
405 const ElfW(Phdr) *ph;
406 size_t textsize;
407 ElfW(Ehdr) *ehdr;
408 int fd;
409 ElfW(Shdr) *shdr;
410 size_t pagesize = getpagesize ();
412 /* Since we use dlopen() we must be prepared to work around the sometimes
413 strange lookup rules for the shared objects. If we have a file foo.so
414 in the current directory and the user specfies foo.so on the command
415 line (without specifying a directory) we should load the file in the
416 current directory even if a normal dlopen() call would read the other
417 file. We do this by adding a directory portion to the name. */
418 if (strchr (name, '/') == NULL)
420 char *load_name = (char *) alloca (strlen (name) + 3);
421 stpcpy (stpcpy (load_name, "./"), name);
423 map = (struct link_map *) dlopen (load_name, RTLD_LAZY | __RTLD_SPROF);
425 if (map == NULL)
427 map = (struct link_map *) dlopen (name, RTLD_LAZY | __RTLD_SPROF);
428 if (map == NULL)
430 error (0, errno, _("failed to load shared object `%s'"), name);
431 return NULL;
435 /* Prepare the result. */
436 result = (struct shobj *) calloc (1, sizeof (struct shobj));
437 if (result == NULL)
439 error (0, errno, _("cannot create internal descriptors"));
440 dlclose (map);
441 return NULL;
443 result->name = name;
444 result->map = map;
446 /* Compute the size of the sections which contain program code.
447 This must match the code in dl-profile.c (_dl_start_profile). */
448 for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
449 if (ph->p_type == PT_LOAD && (ph->p_flags & PF_X))
451 ElfW(Addr) start = (ph->p_vaddr & ~(pagesize - 1));
452 ElfW(Addr) end = ((ph->p_vaddr + ph->p_memsz + pagesize - 1)
453 & ~(pagesize - 1));
455 if (start < mapstart)
456 mapstart = start;
457 if (end > mapend)
458 mapend = end;
461 result->lowpc = ROUNDDOWN ((uintptr_t) (mapstart + map->l_addr),
462 HISTFRACTION * sizeof (HISTCOUNTER));
463 result->highpc = ROUNDUP ((uintptr_t) (mapend + map->l_addr),
464 HISTFRACTION * sizeof (HISTCOUNTER));
465 if (do_test)
466 printf ("load addr: %0#*" PRIxPTR "\n"
467 "lower bound PC: %0#*" PRIxPTR "\n"
468 "upper bound PC: %0#*" PRIxPTR "\n",
469 __ELF_NATIVE_CLASS == 32 ? 10 : 18, map->l_addr,
470 __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->lowpc,
471 __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->highpc);
473 textsize = result->highpc - result->lowpc;
474 result->kcountsize = textsize / HISTFRACTION;
475 result->hashfraction = HASHFRACTION;
476 if (do_test)
477 printf ("hashfraction = %d\ndivider = %Zu\n",
478 result->hashfraction,
479 result->hashfraction * sizeof (struct here_fromstruct));
480 result->tossize = textsize / HASHFRACTION;
481 result->fromlimit = textsize * ARCDENSITY / 100;
482 if (result->fromlimit < MINARCS)
483 result->fromlimit = MINARCS;
484 if (result->fromlimit > MAXARCS)
485 result->fromlimit = MAXARCS;
486 result->fromssize = result->fromlimit * sizeof (struct here_fromstruct);
488 result->expected_size = (sizeof (struct gmon_hdr)
489 + 4 + sizeof (struct gmon_hist_hdr)
490 + result->kcountsize
491 + 4 + 4
492 + (result->fromssize
493 * sizeof (struct here_cg_arc_record)));
495 if (do_test)
496 printf ("expected size: %Zd\n", result->expected_size);
498 #define SCALE_1_TO_1 0x10000L
500 if (result->kcountsize < result->highpc - result->lowpc)
502 size_t range = result->highpc - result->lowpc;
503 size_t quot = range / result->kcountsize;
505 if (quot >= SCALE_1_TO_1)
506 result->s_scale = 1;
507 else if (quot >= SCALE_1_TO_1 / 256)
508 result->s_scale = SCALE_1_TO_1 / quot;
509 else if (range > ULONG_MAX / 256)
510 result->s_scale = ((SCALE_1_TO_1 * 256)
511 / (range / (result->kcountsize / 256)));
512 else
513 result->s_scale = ((SCALE_1_TO_1 * 256)
514 / ((range * 256) / result->kcountsize));
516 else
517 result->s_scale = SCALE_1_TO_1;
519 if (do_test)
520 printf ("s_scale: %d\n", result->s_scale);
522 /* Determine the dynamic string table. */
523 if (map->l_info[DT_STRTAB] == NULL)
524 result->dynstrtab = NULL;
525 else
526 result->dynstrtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
527 if (do_test)
528 printf ("string table: %p\n", result->dynstrtab);
530 /* Determine the soname. */
531 if (map->l_info[DT_SONAME] == NULL)
532 result->soname = NULL;
533 else
534 result->soname = result->dynstrtab + map->l_info[DT_SONAME]->d_un.d_val;
535 if (do_test && result->soname != NULL)
536 printf ("soname: %s\n", result->soname);
538 /* Now we have to load the symbol table.
540 First load the section header table. */
541 ehdr = (ElfW(Ehdr) *) map->l_map_start;
543 /* Make sure we are on the right party. */
544 if (ehdr->e_shentsize != sizeof (ElfW(Shdr)))
545 abort ();
547 /* And we need the shared object file descriptor again. */
548 fd = open (map->l_name, O_RDONLY);
549 if (fd == -1)
550 /* Dooh, this really shouldn't happen. We know the file is available. */
551 error (EXIT_FAILURE, errno, _("Reopening shared object `%s' failed"),
552 map->l_name);
554 /* Map the section header. */
555 size_t size = ehdr->e_shnum * sizeof (ElfW(Shdr));
556 shdr = (ElfW(Shdr) *) alloca (size);
557 if (pread (fd, shdr, size, ehdr->e_shoff) != size)
558 error (EXIT_FAILURE, errno, _("reading of section headers failed"));
560 /* Get the section header string table. */
561 char *shstrtab = (char *) alloca (shdr[ehdr->e_shstrndx].sh_size);
562 if (pread (fd, shstrtab, shdr[ehdr->e_shstrndx].sh_size,
563 shdr[ehdr->e_shstrndx].sh_offset)
564 != shdr[ehdr->e_shstrndx].sh_size)
565 error (EXIT_FAILURE, errno,
566 _("reading of section header string table failed"));
568 /* Search for the ".symtab" section. */
569 ElfW(Shdr) *symtab_entry = NULL;
570 ElfW(Shdr) *debuglink_entry = NULL;
571 for (int idx = 0; idx < ehdr->e_shnum; ++idx)
572 if (shdr[idx].sh_type == SHT_SYMTAB
573 && strcmp (shstrtab + shdr[idx].sh_name, ".symtab") == 0)
575 symtab_entry = &shdr[idx];
576 break;
578 else if (shdr[idx].sh_type == SHT_PROGBITS
579 && strcmp (shstrtab + shdr[idx].sh_name, ".gnu_debuglink") == 0)
580 debuglink_entry = &shdr[idx];
582 /* Get the file name of the debuginfo file if necessary. */
583 int symfd = fd;
584 if (symtab_entry == NULL && debuglink_entry != NULL)
586 size_t size = debuglink_entry->sh_size;
587 char *debuginfo_fname = (char *) alloca (size + 1);
588 debuginfo_fname[size] = '\0';
589 if (pread (fd, debuginfo_fname, size, debuglink_entry->sh_offset)
590 != size)
592 fprintf (stderr, _("*** Cannot read debuginfo file name: %m\n"));
593 goto no_debuginfo;
596 static const char procpath[] = "/proc/self/fd/%d";
597 char origprocname[sizeof (procpath) + sizeof (int) * 3];
598 snprintf (origprocname, sizeof (origprocname), procpath, fd);
599 char *origlink = (char *) alloca (PATH_MAX);
600 ssize_t n = readlink (origprocname, origlink, PATH_MAX - 1);
601 if (n == -1)
602 goto no_debuginfo;
603 origlink[n] = '\0';
605 /* Try to find the actual file. There are three places:
606 1. the same directory the DSO is in
607 2. in a subdir named .debug of the directory the DSO is in
608 3. in /usr/lib/debug/PATH-OF-DSO
610 char *realname = canonicalize_file_name (origlink);
611 char *cp = NULL;
612 if (realname == NULL || (cp = strrchr (realname, '/')) == NULL)
613 error (EXIT_FAILURE, errno, _("cannot determine file name"));
615 /* Leave the last slash in place. */
616 *++cp = '\0';
618 /* First add the debuginfo file name only. */
619 static const char usrlibdebug[]= "/usr/lib/debug/";
620 char *workbuf = (char *) alloca (sizeof (usrlibdebug)
621 + (cp - realname)
622 + strlen (debuginfo_fname));
623 strcpy (stpcpy (workbuf, realname), debuginfo_fname);
625 int fd2 = open (workbuf, O_RDONLY);
626 if (fd2 == -1)
628 strcpy (stpcpy (stpcpy (workbuf, realname), ".debug/"),
629 debuginfo_fname);
630 fd2 = open (workbuf, O_RDONLY);
631 if (fd2 == -1)
633 strcpy (stpcpy (stpcpy (workbuf, usrlibdebug), realname),
634 debuginfo_fname);
635 fd2 = open (workbuf, O_RDONLY);
639 if (fd2 != -1)
641 ElfW(Ehdr) ehdr2;
643 /* Read the ELF header. */
644 if (pread (fd2, &ehdr2, sizeof (ehdr2), 0) != sizeof (ehdr2))
645 error (EXIT_FAILURE, errno,
646 _("reading of ELF header failed"));
648 /* Map the section header. */
649 size_t size = ehdr2.e_shnum * sizeof (ElfW(Shdr));
650 ElfW(Shdr) *shdr2 = (ElfW(Shdr) *) alloca (size);
651 if (pread (fd2, shdr2, size, ehdr2.e_shoff) != size)
652 error (EXIT_FAILURE, errno,
653 _("reading of section headers failed"));
655 /* Get the section header string table. */
656 shstrtab = (char *) alloca (shdr2[ehdr2.e_shstrndx].sh_size);
657 if (pread (fd2, shstrtab, shdr2[ehdr2.e_shstrndx].sh_size,
658 shdr2[ehdr2.e_shstrndx].sh_offset)
659 != shdr2[ehdr2.e_shstrndx].sh_size)
660 error (EXIT_FAILURE, errno,
661 _("reading of section header string table failed"));
663 /* Search for the ".symtab" section. */
664 for (int idx = 0; idx < ehdr2.e_shnum; ++idx)
665 if (shdr2[idx].sh_type == SHT_SYMTAB
666 && strcmp (shstrtab + shdr2[idx].sh_name, ".symtab") == 0)
668 symtab_entry = &shdr2[idx];
669 shdr = shdr2;
670 symfd = fd2;
671 break;
674 if (fd2 != symfd)
675 close (fd2);
679 no_debuginfo:
680 if (symtab_entry == NULL)
682 fprintf (stderr, _("\
683 *** The file `%s' is stripped: no detailed analysis possible\n"),
684 name);
685 result->symtab = NULL;
686 result->strtab = NULL;
688 else
690 ElfW(Off) min_offset, max_offset;
691 ElfW(Shdr) *strtab_entry;
693 strtab_entry = &shdr[symtab_entry->sh_link];
695 /* Find the minimum and maximum offsets that include both the symbol
696 table and the string table. */
697 if (symtab_entry->sh_offset < strtab_entry->sh_offset)
699 min_offset = symtab_entry->sh_offset & ~(pagesize - 1);
700 max_offset = strtab_entry->sh_offset + strtab_entry->sh_size;
702 else
704 min_offset = strtab_entry->sh_offset & ~(pagesize - 1);
705 max_offset = symtab_entry->sh_offset + symtab_entry->sh_size;
708 result->symbol_map = mmap (NULL, max_offset - min_offset,
709 PROT_READ, MAP_SHARED|MAP_FILE, symfd,
710 min_offset);
711 if (result->symbol_map == MAP_FAILED)
712 error (EXIT_FAILURE, errno, _("failed to load symbol data"));
714 result->symtab
715 = (const ElfW(Sym) *) ((const char *) result->symbol_map
716 + (symtab_entry->sh_offset - min_offset));
717 result->symtab_size = symtab_entry->sh_size;
718 result->strtab = ((const char *) result->symbol_map
719 + (strtab_entry->sh_offset - min_offset));
720 result->symbol_mapsize = max_offset - min_offset;
723 /* Free the descriptor for the shared object. */
724 close (fd);
725 if (symfd != fd)
726 close (symfd);
728 return result;
732 static void
733 unload_shobj (struct shobj *shobj)
735 munmap (shobj->symbol_map, shobj->symbol_mapsize);
736 dlclose (shobj->map);
740 static struct profdata *
741 load_profdata (const char *name, struct shobj *shobj)
743 struct profdata *result;
744 int fd;
745 struct stat st;
746 void *addr;
747 uint32_t *narcsp;
748 size_t fromlimit;
749 struct here_cg_arc_record *data;
750 struct here_fromstruct *froms;
751 uint16_t *tos;
752 size_t fromidx;
753 size_t idx;
755 fd = open (name, O_RDONLY);
756 if (fd == -1)
758 char *ext_name;
760 if (errno != ENOENT || strchr (name, '/') != NULL)
761 /* The file exists but we are not allowed to read it or the
762 file does not exist and the name includes a path
763 specification.. */
764 return NULL;
766 /* A file with the given name does not exist in the current
767 directory, try it in the default location where the profiling
768 files are created. */
769 ext_name = (char *) alloca (strlen (name) + sizeof "/var/tmp/");
770 stpcpy (stpcpy (ext_name, "/var/tmp/"), name);
771 name = ext_name;
773 fd = open (ext_name, O_RDONLY);
774 if (fd == -1)
776 /* Even this file does not exist. */
777 error (0, errno, _("cannot load profiling data"));
778 return NULL;
782 /* We have found the file, now make sure it is the right one for the
783 data file. */
784 if (fstat (fd, &st) < 0)
786 error (0, errno, _("while stat'ing profiling data file"));
787 close (fd);
788 return NULL;
791 if ((size_t) st.st_size != shobj->expected_size)
793 error (0, 0,
794 _("profiling data file `%s' does not match shared object `%s'"),
795 name, shobj->name);
796 close (fd);
797 return NULL;
800 /* The data file is most probably the right one for our shared
801 object. Map it now. */
802 addr = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0);
803 if (addr == MAP_FAILED)
805 error (0, errno, _("failed to mmap the profiling data file"));
806 close (fd);
807 return NULL;
810 /* We don't need the file desriptor anymore. */
811 if (close (fd) < 0)
813 error (0, errno, _("error while closing the profiling data file"));
814 munmap (addr, st.st_size);
815 return NULL;
818 /* Prepare the result. */
819 result = (struct profdata *) calloc (1, sizeof (struct profdata));
820 if (result == NULL)
822 error (0, errno, _("cannot create internal descriptor"));
823 munmap (addr, st.st_size);
824 return NULL;
827 /* Store the address and size so that we can later free the resources. */
828 result->addr = addr;
829 result->size = st.st_size;
831 /* Pointer to data after the header. */
832 result->hist = (char *) ((struct gmon_hdr *) addr + 1);
833 result->hist_hdr = (struct real_gmon_hist_hdr *) ((char *) result->hist
834 + sizeof (uint32_t));
835 result->kcount = (uint16_t *) ((char *) result->hist + sizeof (uint32_t)
836 + sizeof (struct real_gmon_hist_hdr));
838 /* Compute pointer to array of the arc information. */
839 narcsp = (uint32_t *) ((char *) result->kcount + shobj->kcountsize
840 + sizeof (uint32_t));
841 result->narcs = *narcsp;
842 result->data = (struct here_cg_arc_record *) ((char *) narcsp
843 + sizeof (uint32_t));
845 /* Create the gmon_hdr we expect or write. */
846 struct real_gmon_hdr
848 char cookie[4];
849 int32_t version;
850 char spare[3 * 4];
851 } gmon_hdr;
852 if (sizeof (gmon_hdr) != sizeof (struct gmon_hdr)
853 || (offsetof (struct real_gmon_hdr, cookie)
854 != offsetof (struct gmon_hdr, cookie))
855 || (offsetof (struct real_gmon_hdr, version)
856 != offsetof (struct gmon_hdr, version)))
857 abort ();
859 memcpy (&gmon_hdr.cookie[0], GMON_MAGIC, sizeof (gmon_hdr.cookie));
860 gmon_hdr.version = GMON_SHOBJ_VERSION;
861 memset (gmon_hdr.spare, '\0', sizeof (gmon_hdr.spare));
863 /* Create the hist_hdr we expect or write. */
864 struct real_gmon_hist_hdr hist_hdr;
865 if (sizeof (hist_hdr) != sizeof (struct gmon_hist_hdr)
866 || (offsetof (struct real_gmon_hist_hdr, low_pc)
867 != offsetof (struct gmon_hist_hdr, low_pc))
868 || (offsetof (struct real_gmon_hist_hdr, high_pc)
869 != offsetof (struct gmon_hist_hdr, high_pc))
870 || (offsetof (struct real_gmon_hist_hdr, hist_size)
871 != offsetof (struct gmon_hist_hdr, hist_size))
872 || (offsetof (struct real_gmon_hist_hdr, prof_rate)
873 != offsetof (struct gmon_hist_hdr, prof_rate))
874 || (offsetof (struct real_gmon_hist_hdr, dimen)
875 != offsetof (struct gmon_hist_hdr, dimen))
876 || (offsetof (struct real_gmon_hist_hdr, dimen_abbrev)
877 != offsetof (struct gmon_hist_hdr, dimen_abbrev)))
878 abort ();
880 hist_hdr.low_pc = (char *) shobj->lowpc - shobj->map->l_addr;
881 hist_hdr.high_pc = (char *) shobj->highpc - shobj->map->l_addr;
882 if (do_test)
883 printf ("low_pc = %p\nhigh_pc = %p\n", hist_hdr.low_pc, hist_hdr.high_pc);
884 hist_hdr.hist_size = shobj->kcountsize / sizeof (HISTCOUNTER);
885 hist_hdr.prof_rate = __profile_frequency ();
886 strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen));
887 hist_hdr.dimen_abbrev = 's';
889 /* Test whether the header of the profiling data is ok. */
890 if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0
891 || *(uint32_t *) result->hist != GMON_TAG_TIME_HIST
892 || memcmp (result->hist_hdr, &hist_hdr,
893 sizeof (struct gmon_hist_hdr)) != 0
894 || narcsp[-1] != GMON_TAG_CG_ARC)
896 error (0, 0, _("`%s' is no correct profile data file for `%s'"),
897 name, shobj->name);
898 if (do_test)
900 if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0)
901 puts ("gmon_hdr differs");
902 if (*(uint32_t *) result->hist != GMON_TAG_TIME_HIST)
903 puts ("result->hist differs");
904 if (memcmp (result->hist_hdr, &hist_hdr,
905 sizeof (struct gmon_hist_hdr)) != 0)
906 puts ("hist_hdr differs");
907 if (narcsp[-1] != GMON_TAG_CG_ARC)
908 puts ("narcsp[-1] differs");
910 free (result);
911 munmap (addr, st.st_size);
912 return NULL;
915 /* We are pretty sure now that this is a correct input file. Set up
916 the remaining information in the result structure and return. */
917 result->tos = (uint16_t *) calloc (shobj->tossize + shobj->fromssize, 1);
918 if (result->tos == NULL)
920 error (0, errno, _("cannot create internal descriptor"));
921 munmap (addr, st.st_size);
922 free (result);
923 return NULL;
926 result->froms = (struct here_fromstruct *) ((char *) result->tos
927 + shobj->tossize);
928 fromidx = 0;
930 /* Now we have to process all the arc count entries. */
931 fromlimit = shobj->fromlimit;
932 data = result->data;
933 froms = result->froms;
934 tos = result->tos;
935 for (idx = 0; idx < MIN (*narcsp, fromlimit); ++idx)
937 size_t to_index;
938 size_t newfromidx;
939 to_index = (data[idx].self_pc / (shobj->hashfraction * sizeof (*tos)));
940 newfromidx = fromidx++;
941 froms[newfromidx].here = &data[idx];
942 froms[newfromidx].link = tos[to_index];
943 tos[to_index] = newfromidx;
946 return result;
950 static void
951 unload_profdata (struct profdata *profdata)
953 free (profdata->tos);
954 munmap (profdata->addr, profdata->size);
955 free (profdata);
959 static void
960 count_total_ticks (struct shobj *shobj, struct profdata *profdata)
962 volatile uint16_t *kcount = profdata->kcount;
963 size_t maxkidx = shobj->kcountsize;
964 size_t factor = 2 * (65536 / shobj->s_scale);
965 size_t kidx = 0;
966 size_t sidx = 0;
968 while (sidx < symidx)
970 uintptr_t start = sortsym[sidx]->addr;
971 uintptr_t end = start + sortsym[sidx]->size;
973 while (kidx < maxkidx && factor * kidx < start)
974 ++kidx;
975 if (kidx == maxkidx)
976 break;
978 while (kidx < maxkidx && factor * kidx < end)
979 sortsym[sidx]->ticks += kcount[kidx++];
980 if (kidx == maxkidx)
981 break;
983 total_ticks += sortsym[sidx++]->ticks;
988 static size_t
989 find_symbol (uintptr_t addr)
991 size_t sidx = 0;
993 while (sidx < symidx)
995 uintptr_t start = sortsym[sidx]->addr;
996 uintptr_t end = start + sortsym[sidx]->size;
998 if (addr >= start && addr < end)
999 return sidx;
1001 if (addr < start)
1002 break;
1004 ++sidx;
1007 return (size_t) -1l;
1011 static void
1012 count_calls (struct shobj *shobj, struct profdata *profdata)
1014 struct here_cg_arc_record *data = profdata->data;
1015 uint32_t narcs = profdata->narcs;
1016 uint32_t cnt;
1018 for (cnt = 0; cnt < narcs; ++cnt)
1020 uintptr_t here = data[cnt].self_pc;
1021 size_t symbol_idx;
1023 /* Find the symbol for this address. */
1024 symbol_idx = find_symbol (here);
1025 if (symbol_idx != (size_t) -1l)
1026 sortsym[symbol_idx]->calls += data[cnt].count;
1031 static int
1032 symorder (const void *o1, const void *o2)
1034 const struct known_symbol *p1 = (const struct known_symbol *) o1;
1035 const struct known_symbol *p2 = (const struct known_symbol *) o2;
1037 return p1->addr - p2->addr;
1041 static void
1042 printsym (const void *node, VISIT value, int level)
1044 if (value == leaf || value == postorder)
1045 sortsym[symidx++] = *(struct known_symbol **) node;
1049 static void
1050 read_symbols (struct shobj *shobj)
1052 int n = 0;
1054 /* Initialize the obstacks. */
1055 #define obstack_chunk_alloc malloc
1056 #define obstack_chunk_free free
1057 obstack_init (&shobj->ob_str);
1058 obstack_init (&shobj->ob_sym);
1059 obstack_init (&ob_list);
1061 /* Process the symbols. */
1062 if (shobj->symtab != NULL)
1064 const ElfW(Sym) *sym = shobj->symtab;
1065 const ElfW(Sym) *sym_end
1066 = (const ElfW(Sym) *) ((const char *) sym + shobj->symtab_size);
1067 for (; sym < sym_end; sym++)
1068 if ((ELFW(ST_TYPE) (sym->st_info) == STT_FUNC
1069 || ELFW(ST_TYPE) (sym->st_info) == STT_NOTYPE)
1070 && sym->st_size != 0)
1072 struct known_symbol **existp;
1073 struct known_symbol *newsym
1074 = (struct known_symbol *) obstack_alloc (&shobj->ob_sym,
1075 sizeof (*newsym));
1076 if (newsym == NULL)
1077 error (EXIT_FAILURE, errno, _("cannot allocate symbol data"));
1079 newsym->name = &shobj->strtab[sym->st_name];
1080 newsym->addr = sym->st_value;
1081 newsym->size = sym->st_size;
1082 newsym->weak = ELFW(ST_BIND) (sym->st_info) == STB_WEAK;
1083 newsym->hidden = (ELFW(ST_VISIBILITY) (sym->st_other)
1084 != STV_DEFAULT);
1085 newsym->ticks = 0;
1086 newsym->calls = 0;
1088 existp = tfind (newsym, &symroot, symorder);
1089 if (existp == NULL)
1091 /* New function. */
1092 tsearch (newsym, &symroot, symorder);
1093 ++n;
1095 else
1097 /* The function is already defined. See whether we have
1098 a better name here. */
1099 if (((*existp)->hidden && !newsym->hidden)
1100 || ((*existp)->name[0] == '_' && newsym->name[0] != '_')
1101 || ((*existp)->name[0] != '_' && newsym->name[0] != '_'
1102 && ((*existp)->weak && !newsym->weak)))
1103 *existp = newsym;
1104 else
1105 /* We don't need the allocated memory. */
1106 obstack_free (&shobj->ob_sym, newsym);
1110 else
1112 /* Blarg, the binary is stripped. We have to rely on the
1113 information contained in the dynamic section of the object. */
1114 const ElfW(Sym) *symtab = (ElfW(Sym) *) D_PTR (shobj->map,
1115 l_info[DT_SYMTAB]);
1116 const char *strtab = (const char *) D_PTR (shobj->map,
1117 l_info[DT_STRTAB]);
1119 /* We assume that the string table follows the symbol table,
1120 because there is no way in ELF to know the size of the
1121 dynamic symbol table without looking at the section headers. */
1122 while ((void *) symtab < (void *) strtab)
1124 if ((ELFW(ST_TYPE)(symtab->st_info) == STT_FUNC
1125 || ELFW(ST_TYPE)(symtab->st_info) == STT_NOTYPE)
1126 && symtab->st_size != 0)
1128 struct known_symbol *newsym;
1129 struct known_symbol **existp;
1131 newsym =
1132 (struct known_symbol *) obstack_alloc (&shobj->ob_sym,
1133 sizeof (*newsym));
1134 if (newsym == NULL)
1135 error (EXIT_FAILURE, errno, _("cannot allocate symbol data"));
1137 newsym->name = &strtab[symtab->st_name];
1138 newsym->addr = symtab->st_value;
1139 newsym->size = symtab->st_size;
1140 newsym->weak = ELFW(ST_BIND) (symtab->st_info) == STB_WEAK;
1141 newsym->hidden = (ELFW(ST_VISIBILITY) (symtab->st_other)
1142 != STV_DEFAULT);
1143 newsym->ticks = 0;
1144 newsym->froms = NULL;
1145 newsym->tos = NULL;
1147 existp = tfind (newsym, &symroot, symorder);
1148 if (existp == NULL)
1150 /* New function. */
1151 tsearch (newsym, &symroot, symorder);
1152 ++n;
1154 else
1156 /* The function is already defined. See whether we have
1157 a better name here. */
1158 if (((*existp)->hidden && !newsym->hidden)
1159 || ((*existp)->name[0] == '_' && newsym->name[0] != '_')
1160 || ((*existp)->name[0] != '_' && newsym->name[0] != '_'
1161 && ((*existp)->weak && !newsym->weak)))
1162 *existp = newsym;
1163 else
1164 /* We don't need the allocated memory. */
1165 obstack_free (&shobj->ob_sym, newsym);
1169 ++symtab;
1173 sortsym = malloc (n * sizeof (struct known_symbol *));
1174 if (sortsym == NULL)
1175 abort ();
1177 twalk (symroot, printsym);
1181 static void
1182 add_arcs (struct profdata *profdata)
1184 uint32_t narcs = profdata->narcs;
1185 struct here_cg_arc_record *data = profdata->data;
1186 uint32_t cnt;
1188 for (cnt = 0; cnt < narcs; ++cnt)
1190 /* First add the incoming arc. */
1191 size_t sym_idx = find_symbol (data[cnt].self_pc);
1193 if (sym_idx != (size_t) -1l)
1195 struct known_symbol *sym = sortsym[sym_idx];
1196 struct arc_list *runp = sym->froms;
1198 while (runp != NULL
1199 && ((data[cnt].from_pc == 0 && runp->idx != (size_t) -1l)
1200 || (data[cnt].from_pc != 0
1201 && (runp->idx == (size_t) -1l
1202 || data[cnt].from_pc < sortsym[runp->idx]->addr
1203 || (data[cnt].from_pc
1204 >= (sortsym[runp->idx]->addr
1205 + sortsym[runp->idx]->size))))))
1206 runp = runp->next;
1208 if (runp == NULL)
1210 /* We need a new entry. */
1211 struct arc_list *newp = (struct arc_list *)
1212 obstack_alloc (&ob_list, sizeof (struct arc_list));
1214 if (data[cnt].from_pc == 0)
1215 newp->idx = (size_t) -1l;
1216 else
1217 newp->idx = find_symbol (data[cnt].from_pc);
1218 newp->count = data[cnt].count;
1219 newp->next = sym->froms;
1220 sym->froms = newp;
1222 else
1223 /* Increment the counter for the found entry. */
1224 runp->count += data[cnt].count;
1227 /* Now add it to the appropriate outgoing list. */
1228 sym_idx = find_symbol (data[cnt].from_pc);
1229 if (sym_idx != (size_t) -1l)
1231 struct known_symbol *sym = sortsym[sym_idx];
1232 struct arc_list *runp = sym->tos;
1234 while (runp != NULL
1235 && (runp->idx == (size_t) -1l
1236 || data[cnt].self_pc < sortsym[runp->idx]->addr
1237 || data[cnt].self_pc >= (sortsym[runp->idx]->addr
1238 + sortsym[runp->idx]->size)))
1239 runp = runp->next;
1241 if (runp == NULL)
1243 /* We need a new entry. */
1244 struct arc_list *newp = (struct arc_list *)
1245 obstack_alloc (&ob_list, sizeof (struct arc_list));
1247 newp->idx = find_symbol (data[cnt].self_pc);
1248 newp->count = data[cnt].count;
1249 newp->next = sym->tos;
1250 sym->tos = newp;
1252 else
1253 /* Increment the counter for the found entry. */
1254 runp->count += data[cnt].count;
1260 static int
1261 countorder (const void *p1, const void *p2)
1263 struct known_symbol *s1 = (struct known_symbol *) p1;
1264 struct known_symbol *s2 = (struct known_symbol *) p2;
1266 if (s1->ticks != s2->ticks)
1267 return (int) (s2->ticks - s1->ticks);
1269 if (s1->calls != s2->calls)
1270 return (int) (s2->calls - s1->calls);
1272 return strcmp (s1->name, s2->name);
1276 static double tick_unit;
1277 static uintmax_t cumu_ticks;
1279 static void
1280 printflat (const void *node, VISIT value, int level)
1282 if (value == leaf || value == postorder)
1284 struct known_symbol *s = *(struct known_symbol **) node;
1286 cumu_ticks += s->ticks;
1288 printf ("%6.2f%10.2f%9.2f%9" PRIdMAX "%9.2f %s\n",
1289 total_ticks ? (100.0 * s->ticks) / total_ticks : 0.0,
1290 tick_unit * cumu_ticks,
1291 tick_unit * s->ticks,
1292 s->calls,
1293 s->calls ? (s->ticks * 1000000) * tick_unit / s->calls : 0,
1294 /* FIXME: don't know about called functions. */
1295 s->name);
1300 /* ARGUSED */
1301 static void
1302 freenoop (void *p)
1307 static void
1308 generate_flat_profile (struct profdata *profdata)
1310 size_t n;
1311 void *data = NULL;
1313 tick_unit = 1.0 / profdata->hist_hdr->prof_rate;
1315 printf ("Flat profile:\n\n"
1316 "Each sample counts as %g %s.\n",
1317 tick_unit, profdata->hist_hdr->dimen);
1318 fputs (" % cumulative self self total\n"
1319 " time seconds seconds calls us/call us/call name\n",
1320 stdout);
1322 for (n = 0; n < symidx; ++n)
1323 if (sortsym[n]->calls != 0 || sortsym[n]->ticks != 0)
1324 tsearch (sortsym[n], &data, countorder);
1326 twalk (data, printflat);
1328 tdestroy (data, freenoop);
1332 static void
1333 generate_call_graph (struct profdata *profdata)
1335 size_t cnt;
1337 puts ("\nindex % time self children called name\n");
1339 for (cnt = 0; cnt < symidx; ++cnt)
1340 if (sortsym[cnt]->froms != NULL || sortsym[cnt]->tos != NULL)
1342 struct arc_list *runp;
1343 size_t n;
1345 /* First print the from-information. */
1346 runp = sortsym[cnt]->froms;
1347 while (runp != NULL)
1349 printf (" %8.2f%8.2f%9" PRIdMAX "/%-9" PRIdMAX " %s",
1350 (runp->idx != (size_t) -1l
1351 ? sortsym[runp->idx]->ticks * tick_unit : 0.0),
1352 0.0, /* FIXME: what's time for the children, recursive */
1353 runp->count, sortsym[cnt]->calls,
1354 (runp->idx != (size_t) -1l ?
1355 sortsym[runp->idx]->name : "<UNKNOWN>"));
1357 if (runp->idx != (size_t) -1l)
1358 printf (" [%Zd]", runp->idx);
1359 putchar_unlocked ('\n');
1361 runp = runp->next;
1364 /* Info abount the function itself. */
1365 n = printf ("[%Zu]", cnt);
1366 printf ("%*s%5.1f%8.2f%8.2f%9" PRIdMAX " %s [%Zd]\n",
1367 (int) (7 - n), " ",
1368 total_ticks ? (100.0 * sortsym[cnt]->ticks) / total_ticks : 0,
1369 sortsym[cnt]->ticks * tick_unit,
1370 0.0, /* FIXME: what's time for the children, recursive */
1371 sortsym[cnt]->calls,
1372 sortsym[cnt]->name, cnt);
1374 /* Info about the functions this function calls. */
1375 runp = sortsym[cnt]->tos;
1376 while (runp != NULL)
1378 printf (" %8.2f%8.2f%9" PRIdMAX "/",
1379 (runp->idx != (size_t) -1l
1380 ? sortsym[runp->idx]->ticks * tick_unit : 0.0),
1381 0.0, /* FIXME: what's time for the children, recursive */
1382 runp->count);
1384 if (runp->idx != (size_t) -1l)
1385 printf ("%-9" PRIdMAX " %s [%Zd]\n",
1386 sortsym[runp->idx]->calls,
1387 sortsym[runp->idx]->name,
1388 runp->idx);
1389 else
1390 fputs ("??? <UNKNOWN>\n\n", stdout);
1392 runp = runp->next;
1395 fputs ("-----------------------------------------------\n", stdout);
1400 static void
1401 generate_call_pair_list (struct profdata *profdata)
1403 size_t cnt;
1405 for (cnt = 0; cnt < symidx; ++cnt)
1406 if (sortsym[cnt]->froms != NULL || sortsym[cnt]->tos != NULL)
1408 struct arc_list *runp;
1410 /* First print the incoming arcs. */
1411 runp = sortsym[cnt]->froms;
1412 while (runp != NULL)
1414 if (runp->idx == (size_t) -1l)
1415 printf ("\
1416 <UNKNOWN> %-34s %9" PRIdMAX "\n",
1417 sortsym[cnt]->name, runp->count);
1418 runp = runp->next;
1421 /* Next the outgoing arcs. */
1422 runp = sortsym[cnt]->tos;
1423 while (runp != NULL)
1425 printf ("%-34s %-34s %9" PRIdMAX "\n",
1426 sortsym[cnt]->name,
1427 (runp->idx != (size_t) -1l
1428 ? sortsym[runp->idx]->name : "<UNKNOWN>"),
1429 runp->count);
1430 runp = runp->next;