New test to expose erroneous negative sign on logb(1) (bug 887).
[glibc.git] / elf / sprof.c
blob2097d31195222b8c2bdf656e09a09a7911a05431
1 /* Read and display shared object profiling data.
2 Copyright (C) 1997-2011, 2012 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, see
18 <http://www.gnu.org/licenses/>. */
20 #include <argp.h>
21 #include <dlfcn.h>
22 #include <elf.h>
23 #include <error.h>
24 #include <fcntl.h>
25 #include <inttypes.h>
26 #include <libintl.h>
27 #include <locale.h>
28 #include <obstack.h>
29 #include <search.h>
30 #include <stdbool.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <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>
42 /* Get libc version number. */
43 #include "../version.h"
45 #define PACKAGE _libc_intl_domainname
48 #include <endian.h>
49 #if BYTE_ORDER == BIG_ENDIAN
50 # define byteorder ELFDATA2MSB
51 # define byteorder_name "big-endian"
52 #elif BYTE_ORDER == LITTLE_ENDIAN
53 # define byteorder ELFDATA2LSB
54 # define byteorder_name "little-endian"
55 #else
56 # error "Unknown BYTE_ORDER " BYTE_ORDER
57 # define byteorder ELFDATANONE
58 #endif
60 #ifndef PATH_MAX
61 # define PATH_MAX 1024
62 #endif
65 extern int __profile_frequency (void);
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;
71 #define OPT_TEST 1
73 /* Definitions of arguments for argp functions. */
74 static const struct argp_option options[] =
76 { NULL, 0, NULL, 0, N_("Output selection:") },
77 { "call-pairs", 'c', NULL, 0,
78 N_("print list of count paths and their number of use") },
79 { "flat-profile", 'p', NULL, 0,
80 N_("generate flat profile with counts and ticks") },
81 { "graph", 'q', NULL, 0, N_("generate call graph") },
83 { "test", OPT_TEST, NULL, OPTION_HIDDEN, NULL },
84 { NULL, 0, NULL, 0, NULL }
87 /* Short description of program. */
88 static const char doc[] = N_("Read and display shared object profiling data.");
89 //For bug reporting instructions, please see:\n
90 //<http://www.gnu.org/software/libc/bugs.html>.\n");
92 /* Strings for arguments in help texts. */
93 static const char args_doc[] = N_("SHOBJ [PROFDATA]");
95 /* Prototype for option handler. */
96 static error_t parse_opt (int key, char *arg, struct argp_state *state);
98 /* Function to print some extra text in the help message. */
99 static char *more_help (int key, const char *text, void *input);
101 /* Data structure to communicate with argp functions. */
102 static struct argp argp =
104 options, parse_opt, args_doc, doc, NULL, more_help
108 /* Operation modes. */
109 static enum
111 NONE = 0,
112 FLAT_MODE = 1 << 0,
113 CALL_GRAPH_MODE = 1 << 1,
114 CALL_PAIRS = 1 << 2,
116 DEFAULT_MODE = FLAT_MODE | CALL_GRAPH_MODE
117 } mode;
119 /* Nozero for testing. */
120 static int do_test;
122 /* Strcuture describing calls. */
123 struct here_fromstruct
125 struct here_cg_arc_record volatile *here;
126 uint16_t link;
129 /* We define a special type to address the elements of the arc table.
130 This is basically the `gmon_cg_arc_record' format but it includes
131 the room for the tag and it uses real types. */
132 struct here_cg_arc_record
134 uintptr_t from_pc;
135 uintptr_t self_pc;
136 uint32_t count;
137 } __attribute__ ((packed));
140 struct known_symbol;
141 struct arc_list
143 size_t idx;
144 uintmax_t count;
146 struct arc_list *next;
149 static struct obstack ob_list;
152 struct known_symbol
154 const char *name;
155 uintptr_t addr;
156 size_t size;
157 bool weak;
158 bool hidden;
160 uintmax_t ticks;
161 uintmax_t calls;
163 struct arc_list *froms;
164 struct arc_list *tos;
168 struct shobj
170 const char *name; /* User-provided name. */
172 struct link_map *map;
173 const char *dynstrtab; /* Dynamic string table of shared object. */
174 const char *soname; /* Soname of shared object. */
176 uintptr_t lowpc;
177 uintptr_t highpc;
178 unsigned long int kcountsize;
179 size_t expected_size; /* Expected size of profiling file. */
180 size_t tossize;
181 size_t fromssize;
182 size_t fromlimit;
183 unsigned int hashfraction;
184 int s_scale;
186 void *symbol_map;
187 size_t symbol_mapsize;
188 const ElfW(Sym) *symtab;
189 size_t symtab_size;
190 const char *strtab;
192 struct obstack ob_str;
193 struct obstack ob_sym;
197 struct real_gmon_hist_hdr
199 char *low_pc;
200 char *high_pc;
201 int32_t hist_size;
202 int32_t prof_rate;
203 char dimen[15];
204 char dimen_abbrev;
208 struct profdata
210 void *addr;
211 off_t size;
213 char *hist;
214 struct real_gmon_hist_hdr *hist_hdr;
215 uint16_t *kcount;
216 uint32_t narcs; /* Number of arcs in toset. */
217 struct here_cg_arc_record *data;
218 uint16_t *tos;
219 struct here_fromstruct *froms;
222 /* Search tree for symbols. */
223 static void *symroot;
224 static struct known_symbol **sortsym;
225 static size_t symidx;
226 static uintmax_t total_ticks;
228 /* Prototypes for local functions. */
229 static struct shobj *load_shobj (const char *name);
230 static void unload_shobj (struct shobj *shobj);
231 static struct profdata *load_profdata (const char *name, struct shobj *shobj);
232 static void unload_profdata (struct profdata *profdata);
233 static void count_total_ticks (struct shobj *shobj, struct profdata *profdata);
234 static void count_calls (struct shobj *shobj, struct profdata *profdata);
235 static void read_symbols (struct shobj *shobj);
236 static void add_arcs (struct profdata *profdata);
237 static void generate_flat_profile (struct profdata *profdata);
238 static void generate_call_graph (struct profdata *profdata);
239 static void generate_call_pair_list (struct profdata *profdata);
243 main (int argc, char *argv[])
245 const char *shobj;
246 const char *profdata;
247 struct shobj *shobj_handle;
248 struct profdata *profdata_handle;
249 int remaining;
251 setlocale (LC_ALL, "");
253 /* Initialize the message catalog. */
254 textdomain (_libc_intl_domainname);
256 /* Parse and process arguments. */
257 argp_parse (&argp, argc, argv, 0, &remaining, NULL);
259 if (argc - remaining == 0 || argc - remaining > 2)
261 /* We need exactly two non-option parameter. */
262 argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
263 program_invocation_short_name);
264 exit (1);
267 /* Get parameters. */
268 shobj = argv[remaining];
269 if (argc - remaining == 2)
270 profdata = argv[remaining + 1];
271 else
272 /* No filename for the profiling data given. We will determine it
273 from the soname of the shobj, later. */
274 profdata = NULL;
276 /* First see whether we can load the shared object. */
277 shobj_handle = load_shobj (shobj);
278 if (shobj_handle == NULL)
279 exit (1);
281 /* We can now determine the filename for the profiling data, if
282 nececessary. */
283 if (profdata == NULL)
285 char *newp;
286 const char *soname;
287 size_t soname_len;
289 soname = shobj_handle->soname ?: basename (shobj);
290 soname_len = strlen (soname);
291 newp = (char *) alloca (soname_len + sizeof ".profile");
292 stpcpy (mempcpy (newp, soname, soname_len), ".profile");
293 profdata = newp;
296 /* Now see whether the profiling data file matches the given object. */
297 profdata_handle = load_profdata (profdata, shobj_handle);
298 if (profdata_handle == NULL)
300 unload_shobj (shobj_handle);
302 exit (1);
305 read_symbols (shobj_handle);
307 /* Count the ticks. */
308 count_total_ticks (shobj_handle, profdata_handle);
310 /* Count the calls. */
311 count_calls (shobj_handle, profdata_handle);
313 /* Add the arc information. */
314 add_arcs (profdata_handle);
316 /* If no mode is specified fall back to the default mode. */
317 if (mode == NONE)
318 mode = DEFAULT_MODE;
320 /* Do some work. */
321 if (mode & FLAT_MODE)
322 generate_flat_profile (profdata_handle);
324 if (mode & CALL_GRAPH_MODE)
325 generate_call_graph (profdata_handle);
327 if (mode & CALL_PAIRS)
328 generate_call_pair_list (profdata_handle);
330 /* Free the resources. */
331 unload_shobj (shobj_handle);
332 unload_profdata (profdata_handle);
334 return 0;
338 /* Handle program arguments. */
339 static error_t
340 parse_opt (int key, char *arg, struct argp_state *state)
342 switch (key)
344 case 'c':
345 mode |= CALL_PAIRS;
346 break;
347 case 'p':
348 mode |= FLAT_MODE;
349 break;
350 case 'q':
351 mode |= CALL_GRAPH_MODE;
352 break;
353 case OPT_TEST:
354 do_test = 1;
355 break;
356 default:
357 return ARGP_ERR_UNKNOWN;
359 return 0;
363 static char *
364 more_help (int key, const char *text, void *input)
366 switch (key)
368 case ARGP_KEY_HELP_EXTRA:
369 /* We print some extra information. */
370 return strdup (gettext ("\
371 For bug reporting instructions, please see:\n\
372 <http://www.gnu.org/software/libc/bugs.html>.\n"));
373 default:
374 break;
376 return (char *) text;
380 /* Print the version information. */
381 static void
382 print_version (FILE *stream, struct argp_state *state)
384 fprintf (stream, "sprof (GNU %s) %s\n", PACKAGE, VERSION);
385 fprintf (stream, gettext ("\
386 Copyright (C) %s Free Software Foundation, Inc.\n\
387 This is free software; see the source for copying conditions. There is NO\n\
388 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
390 "2012");
391 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
395 /* Note that we must not use `dlopen' etc. The shobj object must not
396 be loaded for use. */
397 static struct shobj *
398 load_shobj (const char *name)
400 struct link_map *map = NULL;
401 struct shobj *result;
402 ElfW(Addr) mapstart = ~((ElfW(Addr)) 0);
403 ElfW(Addr) mapend = 0;
404 const ElfW(Phdr) *ph;
405 size_t textsize;
406 ElfW(Ehdr) *ehdr;
407 int fd;
408 ElfW(Shdr) *shdr;
409 size_t pagesize = getpagesize ();
411 /* Since we use dlopen() we must be prepared to work around the sometimes
412 strange lookup rules for the shared objects. If we have a file foo.so
413 in the current directory and the user specfies foo.so on the command
414 line (without specifying a directory) we should load the file in the
415 current directory even if a normal dlopen() call would read the other
416 file. We do this by adding a directory portion to the name. */
417 if (strchr (name, '/') == NULL)
419 char *load_name = (char *) alloca (strlen (name) + 3);
420 stpcpy (stpcpy (load_name, "./"), name);
422 map = (struct link_map *) dlopen (load_name, RTLD_LAZY | __RTLD_SPROF);
424 if (map == NULL)
426 map = (struct link_map *) dlopen (name, RTLD_LAZY | __RTLD_SPROF);
427 if (map == NULL)
429 error (0, errno, _("failed to load shared object `%s'"), name);
430 return NULL;
434 /* Prepare the result. */
435 result = (struct shobj *) calloc (1, sizeof (struct shobj));
436 if (result == NULL)
438 error (0, errno, _("cannot create internal descriptors"));
439 dlclose (map);
440 return NULL;
442 result->name = name;
443 result->map = map;
445 /* Compute the size of the sections which contain program code.
446 This must match the code in dl-profile.c (_dl_start_profile). */
447 for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
448 if (ph->p_type == PT_LOAD && (ph->p_flags & PF_X))
450 ElfW(Addr) start = (ph->p_vaddr & ~(pagesize - 1));
451 ElfW(Addr) end = ((ph->p_vaddr + ph->p_memsz + pagesize - 1)
452 & ~(pagesize - 1));
454 if (start < mapstart)
455 mapstart = start;
456 if (end > mapend)
457 mapend = end;
460 result->lowpc = ROUNDDOWN ((uintptr_t) (mapstart + map->l_addr),
461 HISTFRACTION * sizeof (HISTCOUNTER));
462 result->highpc = ROUNDUP ((uintptr_t) (mapend + map->l_addr),
463 HISTFRACTION * sizeof (HISTCOUNTER));
464 if (do_test)
465 printf ("load addr: %0#*" PRIxPTR "\n"
466 "lower bound PC: %0#*" PRIxPTR "\n"
467 "upper bound PC: %0#*" PRIxPTR "\n",
468 __ELF_NATIVE_CLASS == 32 ? 10 : 18, map->l_addr,
469 __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->lowpc,
470 __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->highpc);
472 textsize = result->highpc - result->lowpc;
473 result->kcountsize = textsize / HISTFRACTION;
474 result->hashfraction = HASHFRACTION;
475 if (do_test)
476 printf ("hashfraction = %d\ndivider = %Zu\n",
477 result->hashfraction,
478 result->hashfraction * sizeof (struct here_fromstruct));
479 result->tossize = textsize / HASHFRACTION;
480 result->fromlimit = textsize * ARCDENSITY / 100;
481 if (result->fromlimit < MINARCS)
482 result->fromlimit = MINARCS;
483 if (result->fromlimit > MAXARCS)
484 result->fromlimit = MAXARCS;
485 result->fromssize = result->fromlimit * sizeof (struct here_fromstruct);
487 result->expected_size = (sizeof (struct gmon_hdr)
488 + 4 + sizeof (struct gmon_hist_hdr)
489 + result->kcountsize
490 + 4 + 4
491 + (result->fromssize
492 * sizeof (struct here_cg_arc_record)));
494 if (do_test)
495 printf ("expected size: %Zd\n", result->expected_size);
497 #define SCALE_1_TO_1 0x10000L
499 if (result->kcountsize < result->highpc - result->lowpc)
501 size_t range = result->highpc - result->lowpc;
502 size_t quot = range / result->kcountsize;
504 if (quot >= SCALE_1_TO_1)
505 result->s_scale = 1;
506 else if (quot >= SCALE_1_TO_1 / 256)
507 result->s_scale = SCALE_1_TO_1 / quot;
508 else if (range > ULONG_MAX / 256)
509 result->s_scale = ((SCALE_1_TO_1 * 256)
510 / (range / (result->kcountsize / 256)));
511 else
512 result->s_scale = ((SCALE_1_TO_1 * 256)
513 / ((range * 256) / result->kcountsize));
515 else
516 result->s_scale = SCALE_1_TO_1;
518 if (do_test)
519 printf ("s_scale: %d\n", result->s_scale);
521 /* Determine the dynamic string table. */
522 if (map->l_info[DT_STRTAB] == NULL)
523 result->dynstrtab = NULL;
524 else
525 result->dynstrtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
526 if (do_test)
527 printf ("string table: %p\n", result->dynstrtab);
529 /* Determine the soname. */
530 if (map->l_info[DT_SONAME] == NULL)
531 result->soname = NULL;
532 else
533 result->soname = result->dynstrtab + map->l_info[DT_SONAME]->d_un.d_val;
534 if (do_test && result->soname != NULL)
535 printf ("soname: %s\n", result->soname);
537 /* Now we have to load the symbol table.
539 First load the section header table. */
540 ehdr = (ElfW(Ehdr) *) map->l_map_start;
542 /* Make sure we are on the right party. */
543 if (ehdr->e_shentsize != sizeof (ElfW(Shdr)))
544 abort ();
546 /* And we need the shared object file descriptor again. */
547 fd = open (map->l_name, O_RDONLY);
548 if (fd == -1)
549 /* Dooh, this really shouldn't happen. We know the file is available. */
550 error (EXIT_FAILURE, errno, _("Reopening shared object `%s' failed"),
551 map->l_name);
553 /* Map the section header. */
554 size_t size = ehdr->e_shnum * sizeof (ElfW(Shdr));
555 shdr = (ElfW(Shdr) *) alloca (size);
556 if (pread (fd, shdr, size, ehdr->e_shoff) != size)
557 error (EXIT_FAILURE, errno, _("reading of section headers failed"));
559 /* Get the section header string table. */
560 char *shstrtab = (char *) alloca (shdr[ehdr->e_shstrndx].sh_size);
561 if (pread (fd, shstrtab, shdr[ehdr->e_shstrndx].sh_size,
562 shdr[ehdr->e_shstrndx].sh_offset)
563 != shdr[ehdr->e_shstrndx].sh_size)
564 error (EXIT_FAILURE, errno,
565 _("reading of section header string table failed"));
567 /* Search for the ".symtab" section. */
568 ElfW(Shdr) *symtab_entry = NULL;
569 ElfW(Shdr) *debuglink_entry = NULL;
570 for (int idx = 0; idx < ehdr->e_shnum; ++idx)
571 if (shdr[idx].sh_type == SHT_SYMTAB
572 && strcmp (shstrtab + shdr[idx].sh_name, ".symtab") == 0)
574 symtab_entry = &shdr[idx];
575 break;
577 else if (shdr[idx].sh_type == SHT_PROGBITS
578 && strcmp (shstrtab + shdr[idx].sh_name, ".gnu_debuglink") == 0)
579 debuglink_entry = &shdr[idx];
581 /* Get the file name of the debuginfo file if necessary. */
582 int symfd = fd;
583 if (symtab_entry == NULL && debuglink_entry != NULL)
585 size_t size = debuglink_entry->sh_size;
586 char *debuginfo_fname = (char *) alloca (size + 1);
587 debuginfo_fname[size] = '\0';
588 if (pread (fd, debuginfo_fname, size, debuglink_entry->sh_offset)
589 != size)
591 fprintf (stderr, _("*** Cannot read debuginfo file name: %m\n"));
592 goto no_debuginfo;
595 static const char procpath[] = "/proc/self/fd/%d";
596 char origprocname[sizeof (procpath) + sizeof (int) * 3];
597 snprintf (origprocname, sizeof (origprocname), procpath, fd);
598 char *origlink = (char *) alloca (PATH_MAX);
599 ssize_t n = readlink (origprocname, origlink, PATH_MAX - 1);
600 if (n == -1)
601 goto no_debuginfo;
602 origlink[n] = '\0';
604 /* Try to find the actual file. There are three places:
605 1. the same directory the DSO is in
606 2. in a subdir named .debug of the directory the DSO is in
607 3. in /usr/lib/debug/PATH-OF-DSO
609 char *realname = canonicalize_file_name (origlink);
610 char *cp = NULL;
611 if (realname == NULL || (cp = strrchr (realname, '/')) == NULL)
612 error (EXIT_FAILURE, errno, _("cannot determine file name"));
614 /* Leave the last slash in place. */
615 *++cp = '\0';
617 /* First add the debuginfo file name only. */
618 static const char usrlibdebug[]= "/usr/lib/debug/";
619 char *workbuf = (char *) alloca (sizeof (usrlibdebug)
620 + (cp - realname)
621 + strlen (debuginfo_fname));
622 strcpy (stpcpy (workbuf, realname), debuginfo_fname);
624 int fd2 = open (workbuf, O_RDONLY);
625 if (fd2 == -1)
627 strcpy (stpcpy (stpcpy (workbuf, realname), ".debug/"),
628 debuginfo_fname);
629 fd2 = open (workbuf, O_RDONLY);
630 if (fd2 == -1)
632 strcpy (stpcpy (stpcpy (workbuf, usrlibdebug), realname),
633 debuginfo_fname);
634 fd2 = open (workbuf, O_RDONLY);
638 if (fd2 != -1)
640 ElfW(Ehdr) ehdr2;
642 /* Read the ELF header. */
643 if (pread (fd2, &ehdr2, sizeof (ehdr2), 0) != sizeof (ehdr2))
644 error (EXIT_FAILURE, errno,
645 _("reading of ELF header failed"));
647 /* Map the section header. */
648 size_t size = ehdr2.e_shnum * sizeof (ElfW(Shdr));
649 ElfW(Shdr) *shdr2 = (ElfW(Shdr) *) alloca (size);
650 if (pread (fd2, shdr2, size, ehdr2.e_shoff) != size)
651 error (EXIT_FAILURE, errno,
652 _("reading of section headers failed"));
654 /* Get the section header string table. */
655 shstrtab = (char *) alloca (shdr2[ehdr2.e_shstrndx].sh_size);
656 if (pread (fd2, shstrtab, shdr2[ehdr2.e_shstrndx].sh_size,
657 shdr2[ehdr2.e_shstrndx].sh_offset)
658 != shdr2[ehdr2.e_shstrndx].sh_size)
659 error (EXIT_FAILURE, errno,
660 _("reading of section header string table failed"));
662 /* Search for the ".symtab" section. */
663 for (int idx = 0; idx < ehdr2.e_shnum; ++idx)
664 if (shdr2[idx].sh_type == SHT_SYMTAB
665 && strcmp (shstrtab + shdr2[idx].sh_name, ".symtab") == 0)
667 symtab_entry = &shdr2[idx];
668 shdr = shdr2;
669 symfd = fd2;
670 break;
673 if (fd2 != symfd)
674 close (fd2);
678 no_debuginfo:
679 if (symtab_entry == NULL)
681 fprintf (stderr, _("\
682 *** The file `%s' is stripped: no detailed analysis possible\n"),
683 name);
684 result->symtab = NULL;
685 result->strtab = NULL;
687 else
689 ElfW(Off) min_offset, max_offset;
690 ElfW(Shdr) *strtab_entry;
692 strtab_entry = &shdr[symtab_entry->sh_link];
694 /* Find the minimum and maximum offsets that include both the symbol
695 table and the string table. */
696 if (symtab_entry->sh_offset < strtab_entry->sh_offset)
698 min_offset = symtab_entry->sh_offset & ~(pagesize - 1);
699 max_offset = strtab_entry->sh_offset + strtab_entry->sh_size;
701 else
703 min_offset = strtab_entry->sh_offset & ~(pagesize - 1);
704 max_offset = symtab_entry->sh_offset + symtab_entry->sh_size;
707 result->symbol_map = mmap (NULL, max_offset - min_offset,
708 PROT_READ, MAP_SHARED|MAP_FILE, symfd,
709 min_offset);
710 if (result->symbol_map == MAP_FAILED)
711 error (EXIT_FAILURE, errno, _("failed to load symbol data"));
713 result->symtab
714 = (const ElfW(Sym) *) ((const char *) result->symbol_map
715 + (symtab_entry->sh_offset - min_offset));
716 result->symtab_size = symtab_entry->sh_size;
717 result->strtab = ((const char *) result->symbol_map
718 + (strtab_entry->sh_offset - min_offset));
719 result->symbol_mapsize = max_offset - min_offset;
722 /* Free the descriptor for the shared object. */
723 close (fd);
724 if (symfd != fd)
725 close (symfd);
727 return result;
731 static void
732 unload_shobj (struct shobj *shobj)
734 munmap (shobj->symbol_map, shobj->symbol_mapsize);
735 dlclose (shobj->map);
739 static struct profdata *
740 load_profdata (const char *name, struct shobj *shobj)
742 struct profdata *result;
743 int fd;
744 struct stat st;
745 void *addr;
746 uint32_t *narcsp;
747 size_t fromlimit;
748 struct here_cg_arc_record *data;
749 struct here_fromstruct *froms;
750 uint16_t *tos;
751 size_t fromidx;
752 size_t idx;
754 fd = open (name, O_RDONLY);
755 if (fd == -1)
757 char *ext_name;
759 if (errno != ENOENT || strchr (name, '/') != NULL)
760 /* The file exists but we are not allowed to read it or the
761 file does not exist and the name includes a path
762 specification.. */
763 return NULL;
765 /* A file with the given name does not exist in the current
766 directory, try it in the default location where the profiling
767 files are created. */
768 ext_name = (char *) alloca (strlen (name) + sizeof "/var/tmp/");
769 stpcpy (stpcpy (ext_name, "/var/tmp/"), name);
770 name = ext_name;
772 fd = open (ext_name, O_RDONLY);
773 if (fd == -1)
775 /* Even this file does not exist. */
776 error (0, errno, _("cannot load profiling data"));
777 return NULL;
781 /* We have found the file, now make sure it is the right one for the
782 data file. */
783 if (fstat (fd, &st) < 0)
785 error (0, errno, _("while stat'ing profiling data file"));
786 close (fd);
787 return NULL;
790 if ((size_t) st.st_size != shobj->expected_size)
792 error (0, 0,
793 _("profiling data file `%s' does not match shared object `%s'"),
794 name, shobj->name);
795 close (fd);
796 return NULL;
799 /* The data file is most probably the right one for our shared
800 object. Map it now. */
801 addr = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0);
802 if (addr == MAP_FAILED)
804 error (0, errno, _("failed to mmap the profiling data file"));
805 close (fd);
806 return NULL;
809 /* We don't need the file desriptor anymore. */
810 if (close (fd) < 0)
812 error (0, errno, _("error while closing the profiling data file"));
813 munmap (addr, st.st_size);
814 return NULL;
817 /* Prepare the result. */
818 result = (struct profdata *) calloc (1, sizeof (struct profdata));
819 if (result == NULL)
821 error (0, errno, _("cannot create internal descriptor"));
822 munmap (addr, st.st_size);
823 return NULL;
826 /* Store the address and size so that we can later free the resources. */
827 result->addr = addr;
828 result->size = st.st_size;
830 /* Pointer to data after the header. */
831 result->hist = (char *) ((struct gmon_hdr *) addr + 1);
832 result->hist_hdr = (struct real_gmon_hist_hdr *) ((char *) result->hist
833 + sizeof (uint32_t));
834 result->kcount = (uint16_t *) ((char *) result->hist + sizeof (uint32_t)
835 + sizeof (struct real_gmon_hist_hdr));
837 /* Compute pointer to array of the arc information. */
838 narcsp = (uint32_t *) ((char *) result->kcount + shobj->kcountsize
839 + sizeof (uint32_t));
840 result->narcs = *narcsp;
841 result->data = (struct here_cg_arc_record *) ((char *) narcsp
842 + sizeof (uint32_t));
844 /* Create the gmon_hdr we expect or write. */
845 struct real_gmon_hdr
847 char cookie[4];
848 int32_t version;
849 char spare[3 * 4];
850 } gmon_hdr;
851 if (sizeof (gmon_hdr) != sizeof (struct gmon_hdr)
852 || (offsetof (struct real_gmon_hdr, cookie)
853 != offsetof (struct gmon_hdr, cookie))
854 || (offsetof (struct real_gmon_hdr, version)
855 != offsetof (struct gmon_hdr, version)))
856 abort ();
858 memcpy (&gmon_hdr.cookie[0], GMON_MAGIC, sizeof (gmon_hdr.cookie));
859 gmon_hdr.version = GMON_SHOBJ_VERSION;
860 memset (gmon_hdr.spare, '\0', sizeof (gmon_hdr.spare));
862 /* Create the hist_hdr we expect or write. */
863 struct real_gmon_hist_hdr hist_hdr;
864 if (sizeof (hist_hdr) != sizeof (struct gmon_hist_hdr)
865 || (offsetof (struct real_gmon_hist_hdr, low_pc)
866 != offsetof (struct gmon_hist_hdr, low_pc))
867 || (offsetof (struct real_gmon_hist_hdr, high_pc)
868 != offsetof (struct gmon_hist_hdr, high_pc))
869 || (offsetof (struct real_gmon_hist_hdr, hist_size)
870 != offsetof (struct gmon_hist_hdr, hist_size))
871 || (offsetof (struct real_gmon_hist_hdr, prof_rate)
872 != offsetof (struct gmon_hist_hdr, prof_rate))
873 || (offsetof (struct real_gmon_hist_hdr, dimen)
874 != offsetof (struct gmon_hist_hdr, dimen))
875 || (offsetof (struct real_gmon_hist_hdr, dimen_abbrev)
876 != offsetof (struct gmon_hist_hdr, dimen_abbrev)))
877 abort ();
879 hist_hdr.low_pc = (char *) shobj->lowpc - shobj->map->l_addr;
880 hist_hdr.high_pc = (char *) shobj->highpc - shobj->map->l_addr;
881 if (do_test)
882 printf ("low_pc = %p\nhigh_pc = %p\n", hist_hdr.low_pc, hist_hdr.high_pc);
883 hist_hdr.hist_size = shobj->kcountsize / sizeof (HISTCOUNTER);
884 hist_hdr.prof_rate = __profile_frequency ();
885 strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen));
886 hist_hdr.dimen_abbrev = 's';
888 /* Test whether the header of the profiling data is ok. */
889 if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0
890 || *(uint32_t *) result->hist != GMON_TAG_TIME_HIST
891 || memcmp (result->hist_hdr, &hist_hdr,
892 sizeof (struct gmon_hist_hdr)) != 0
893 || narcsp[-1] != GMON_TAG_CG_ARC)
895 error (0, 0, _("`%s' is no correct profile data file for `%s'"),
896 name, shobj->name);
897 if (do_test)
899 if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0)
900 puts ("gmon_hdr differs");
901 if (*(uint32_t *) result->hist != GMON_TAG_TIME_HIST)
902 puts ("result->hist differs");
903 if (memcmp (result->hist_hdr, &hist_hdr,
904 sizeof (struct gmon_hist_hdr)) != 0)
905 puts ("hist_hdr differs");
906 if (narcsp[-1] != GMON_TAG_CG_ARC)
907 puts ("narcsp[-1] differs");
909 free (result);
910 munmap (addr, st.st_size);
911 return NULL;
914 /* We are pretty sure now that this is a correct input file. Set up
915 the remaining information in the result structure and return. */
916 result->tos = (uint16_t *) calloc (shobj->tossize + shobj->fromssize, 1);
917 if (result->tos == NULL)
919 error (0, errno, _("cannot create internal descriptor"));
920 munmap (addr, st.st_size);
921 free (result);
922 return NULL;
925 result->froms = (struct here_fromstruct *) ((char *) result->tos
926 + shobj->tossize);
927 fromidx = 0;
929 /* Now we have to process all the arc count entries. */
930 fromlimit = shobj->fromlimit;
931 data = result->data;
932 froms = result->froms;
933 tos = result->tos;
934 for (idx = 0; idx < MIN (*narcsp, fromlimit); ++idx)
936 size_t to_index;
937 size_t newfromidx;
938 to_index = (data[idx].self_pc / (shobj->hashfraction * sizeof (*tos)));
939 newfromidx = fromidx++;
940 froms[newfromidx].here = &data[idx];
941 froms[newfromidx].link = tos[to_index];
942 tos[to_index] = newfromidx;
945 return result;
949 static void
950 unload_profdata (struct profdata *profdata)
952 free (profdata->tos);
953 munmap (profdata->addr, profdata->size);
954 free (profdata);
958 static void
959 count_total_ticks (struct shobj *shobj, struct profdata *profdata)
961 volatile uint16_t *kcount = profdata->kcount;
962 size_t maxkidx = shobj->kcountsize;
963 size_t factor = 2 * (65536 / shobj->s_scale);
964 size_t kidx = 0;
965 size_t sidx = 0;
967 while (sidx < symidx)
969 uintptr_t start = sortsym[sidx]->addr;
970 uintptr_t end = start + sortsym[sidx]->size;
972 while (kidx < maxkidx && factor * kidx < start)
973 ++kidx;
974 if (kidx == maxkidx)
975 break;
977 while (kidx < maxkidx && factor * kidx < end)
978 sortsym[sidx]->ticks += kcount[kidx++];
979 if (kidx == maxkidx)
980 break;
982 total_ticks += sortsym[sidx++]->ticks;
987 static size_t
988 find_symbol (uintptr_t addr)
990 size_t sidx = 0;
992 while (sidx < symidx)
994 uintptr_t start = sortsym[sidx]->addr;
995 uintptr_t end = start + sortsym[sidx]->size;
997 if (addr >= start && addr < end)
998 return sidx;
1000 if (addr < start)
1001 break;
1003 ++sidx;
1006 return (size_t) -1l;
1010 static void
1011 count_calls (struct shobj *shobj, struct profdata *profdata)
1013 struct here_cg_arc_record *data = profdata->data;
1014 uint32_t narcs = profdata->narcs;
1015 uint32_t cnt;
1017 for (cnt = 0; cnt < narcs; ++cnt)
1019 uintptr_t here = data[cnt].self_pc;
1020 size_t symbol_idx;
1022 /* Find the symbol for this address. */
1023 symbol_idx = find_symbol (here);
1024 if (symbol_idx != (size_t) -1l)
1025 sortsym[symbol_idx]->calls += data[cnt].count;
1030 static int
1031 symorder (const void *o1, const void *o2)
1033 const struct known_symbol *p1 = (const struct known_symbol *) o1;
1034 const struct known_symbol *p2 = (const struct known_symbol *) o2;
1036 return p1->addr - p2->addr;
1040 static void
1041 printsym (const void *node, VISIT value, int level)
1043 if (value == leaf || value == postorder)
1044 sortsym[symidx++] = *(struct known_symbol **) node;
1048 static void
1049 read_symbols (struct shobj *shobj)
1051 int n = 0;
1053 /* Initialize the obstacks. */
1054 #define obstack_chunk_alloc malloc
1055 #define obstack_chunk_free free
1056 obstack_init (&shobj->ob_str);
1057 obstack_init (&shobj->ob_sym);
1058 obstack_init (&ob_list);
1060 /* Process the symbols. */
1061 if (shobj->symtab != NULL)
1063 const ElfW(Sym) *sym = shobj->symtab;
1064 const ElfW(Sym) *sym_end
1065 = (const ElfW(Sym) *) ((const char *) sym + shobj->symtab_size);
1066 for (; sym < sym_end; sym++)
1067 if ((ELFW(ST_TYPE) (sym->st_info) == STT_FUNC
1068 || ELFW(ST_TYPE) (sym->st_info) == STT_NOTYPE)
1069 && sym->st_size != 0)
1071 struct known_symbol **existp;
1072 struct known_symbol *newsym
1073 = (struct known_symbol *) obstack_alloc (&shobj->ob_sym,
1074 sizeof (*newsym));
1075 if (newsym == NULL)
1076 error (EXIT_FAILURE, errno, _("cannot allocate symbol data"));
1078 newsym->name = &shobj->strtab[sym->st_name];
1079 newsym->addr = sym->st_value;
1080 newsym->size = sym->st_size;
1081 newsym->weak = ELFW(ST_BIND) (sym->st_info) == STB_WEAK;
1082 newsym->hidden = (ELFW(ST_VISIBILITY) (sym->st_other)
1083 != STV_DEFAULT);
1084 newsym->ticks = 0;
1085 newsym->calls = 0;
1087 existp = tfind (newsym, &symroot, symorder);
1088 if (existp == NULL)
1090 /* New function. */
1091 tsearch (newsym, &symroot, symorder);
1092 ++n;
1094 else
1096 /* The function is already defined. See whether we have
1097 a better name here. */
1098 if (((*existp)->hidden && !newsym->hidden)
1099 || ((*existp)->name[0] == '_' && newsym->name[0] != '_')
1100 || ((*existp)->name[0] != '_' && newsym->name[0] != '_'
1101 && ((*existp)->weak && !newsym->weak)))
1102 *existp = newsym;
1103 else
1104 /* We don't need the allocated memory. */
1105 obstack_free (&shobj->ob_sym, newsym);
1109 else
1111 /* Blarg, the binary is stripped. We have to rely on the
1112 information contained in the dynamic section of the object. */
1113 const ElfW(Sym) *symtab = (ElfW(Sym) *) D_PTR (shobj->map,
1114 l_info[DT_SYMTAB]);
1115 const char *strtab = (const char *) D_PTR (shobj->map,
1116 l_info[DT_STRTAB]);
1118 /* We assume that the string table follows the symbol table,
1119 because there is no way in ELF to know the size of the
1120 dynamic symbol table without looking at the section headers. */
1121 while ((void *) symtab < (void *) strtab)
1123 if ((ELFW(ST_TYPE)(symtab->st_info) == STT_FUNC
1124 || ELFW(ST_TYPE)(symtab->st_info) == STT_NOTYPE)
1125 && symtab->st_size != 0)
1127 struct known_symbol *newsym;
1128 struct known_symbol **existp;
1130 newsym =
1131 (struct known_symbol *) obstack_alloc (&shobj->ob_sym,
1132 sizeof (*newsym));
1133 if (newsym == NULL)
1134 error (EXIT_FAILURE, errno, _("cannot allocate symbol data"));
1136 newsym->name = &strtab[symtab->st_name];
1137 newsym->addr = symtab->st_value;
1138 newsym->size = symtab->st_size;
1139 newsym->weak = ELFW(ST_BIND) (symtab->st_info) == STB_WEAK;
1140 newsym->hidden = (ELFW(ST_VISIBILITY) (symtab->st_other)
1141 != STV_DEFAULT);
1142 newsym->ticks = 0;
1143 newsym->froms = NULL;
1144 newsym->tos = NULL;
1146 existp = tfind (newsym, &symroot, symorder);
1147 if (existp == NULL)
1149 /* New function. */
1150 tsearch (newsym, &symroot, symorder);
1151 ++n;
1153 else
1155 /* The function is already defined. See whether we have
1156 a better name here. */
1157 if (((*existp)->hidden && !newsym->hidden)
1158 || ((*existp)->name[0] == '_' && newsym->name[0] != '_')
1159 || ((*existp)->name[0] != '_' && newsym->name[0] != '_'
1160 && ((*existp)->weak && !newsym->weak)))
1161 *existp = newsym;
1162 else
1163 /* We don't need the allocated memory. */
1164 obstack_free (&shobj->ob_sym, newsym);
1168 ++symtab;
1172 sortsym = malloc (n * sizeof (struct known_symbol *));
1173 if (sortsym == NULL)
1174 abort ();
1176 twalk (symroot, printsym);
1180 static void
1181 add_arcs (struct profdata *profdata)
1183 uint32_t narcs = profdata->narcs;
1184 struct here_cg_arc_record *data = profdata->data;
1185 uint32_t cnt;
1187 for (cnt = 0; cnt < narcs; ++cnt)
1189 /* First add the incoming arc. */
1190 size_t sym_idx = find_symbol (data[cnt].self_pc);
1192 if (sym_idx != (size_t) -1l)
1194 struct known_symbol *sym = sortsym[sym_idx];
1195 struct arc_list *runp = sym->froms;
1197 while (runp != NULL
1198 && ((data[cnt].from_pc == 0 && runp->idx != (size_t) -1l)
1199 || (data[cnt].from_pc != 0
1200 && (runp->idx == (size_t) -1l
1201 || data[cnt].from_pc < sortsym[runp->idx]->addr
1202 || (data[cnt].from_pc
1203 >= (sortsym[runp->idx]->addr
1204 + sortsym[runp->idx]->size))))))
1205 runp = runp->next;
1207 if (runp == NULL)
1209 /* We need a new entry. */
1210 struct arc_list *newp = (struct arc_list *)
1211 obstack_alloc (&ob_list, sizeof (struct arc_list));
1213 if (data[cnt].from_pc == 0)
1214 newp->idx = (size_t) -1l;
1215 else
1216 newp->idx = find_symbol (data[cnt].from_pc);
1217 newp->count = data[cnt].count;
1218 newp->next = sym->froms;
1219 sym->froms = newp;
1221 else
1222 /* Increment the counter for the found entry. */
1223 runp->count += data[cnt].count;
1226 /* Now add it to the appropriate outgoing list. */
1227 sym_idx = find_symbol (data[cnt].from_pc);
1228 if (sym_idx != (size_t) -1l)
1230 struct known_symbol *sym = sortsym[sym_idx];
1231 struct arc_list *runp = sym->tos;
1233 while (runp != NULL
1234 && (runp->idx == (size_t) -1l
1235 || data[cnt].self_pc < sortsym[runp->idx]->addr
1236 || data[cnt].self_pc >= (sortsym[runp->idx]->addr
1237 + sortsym[runp->idx]->size)))
1238 runp = runp->next;
1240 if (runp == NULL)
1242 /* We need a new entry. */
1243 struct arc_list *newp = (struct arc_list *)
1244 obstack_alloc (&ob_list, sizeof (struct arc_list));
1246 newp->idx = find_symbol (data[cnt].self_pc);
1247 newp->count = data[cnt].count;
1248 newp->next = sym->tos;
1249 sym->tos = newp;
1251 else
1252 /* Increment the counter for the found entry. */
1253 runp->count += data[cnt].count;
1259 static int
1260 countorder (const void *p1, const void *p2)
1262 struct known_symbol *s1 = (struct known_symbol *) p1;
1263 struct known_symbol *s2 = (struct known_symbol *) p2;
1265 if (s1->ticks != s2->ticks)
1266 return (int) (s2->ticks - s1->ticks);
1268 if (s1->calls != s2->calls)
1269 return (int) (s2->calls - s1->calls);
1271 return strcmp (s1->name, s2->name);
1275 static double tick_unit;
1276 static uintmax_t cumu_ticks;
1278 static void
1279 printflat (const void *node, VISIT value, int level)
1281 if (value == leaf || value == postorder)
1283 struct known_symbol *s = *(struct known_symbol **) node;
1285 cumu_ticks += s->ticks;
1287 printf ("%6.2f%10.2f%9.2f%9" PRIdMAX "%9.2f %s\n",
1288 total_ticks ? (100.0 * s->ticks) / total_ticks : 0.0,
1289 tick_unit * cumu_ticks,
1290 tick_unit * s->ticks,
1291 s->calls,
1292 s->calls ? (s->ticks * 1000000) * tick_unit / s->calls : 0,
1293 /* FIXME: don't know about called functions. */
1294 s->name);
1299 /* ARGUSED */
1300 static void
1301 freenoop (void *p)
1306 static void
1307 generate_flat_profile (struct profdata *profdata)
1309 size_t n;
1310 void *data = NULL;
1312 tick_unit = 1.0 / profdata->hist_hdr->prof_rate;
1314 printf ("Flat profile:\n\n"
1315 "Each sample counts as %g %s.\n",
1316 tick_unit, profdata->hist_hdr->dimen);
1317 fputs (" % cumulative self self total\n"
1318 " time seconds seconds calls us/call us/call name\n",
1319 stdout);
1321 for (n = 0; n < symidx; ++n)
1322 if (sortsym[n]->calls != 0 || sortsym[n]->ticks != 0)
1323 tsearch (sortsym[n], &data, countorder);
1325 twalk (data, printflat);
1327 tdestroy (data, freenoop);
1331 static void
1332 generate_call_graph (struct profdata *profdata)
1334 size_t cnt;
1336 puts ("\nindex % time self children called name\n");
1338 for (cnt = 0; cnt < symidx; ++cnt)
1339 if (sortsym[cnt]->froms != NULL || sortsym[cnt]->tos != NULL)
1341 struct arc_list *runp;
1342 size_t n;
1344 /* First print the from-information. */
1345 runp = sortsym[cnt]->froms;
1346 while (runp != NULL)
1348 printf (" %8.2f%8.2f%9" PRIdMAX "/%-9" PRIdMAX " %s",
1349 (runp->idx != (size_t) -1l
1350 ? sortsym[runp->idx]->ticks * tick_unit : 0.0),
1351 0.0, /* FIXME: what's time for the children, recursive */
1352 runp->count, sortsym[cnt]->calls,
1353 (runp->idx != (size_t) -1l ?
1354 sortsym[runp->idx]->name : "<UNKNOWN>"));
1356 if (runp->idx != (size_t) -1l)
1357 printf (" [%Zd]", runp->idx);
1358 putchar_unlocked ('\n');
1360 runp = runp->next;
1363 /* Info abount the function itself. */
1364 n = printf ("[%Zu]", cnt);
1365 printf ("%*s%5.1f%8.2f%8.2f%9" PRIdMAX " %s [%Zd]\n",
1366 (int) (7 - n), " ",
1367 total_ticks ? (100.0 * sortsym[cnt]->ticks) / total_ticks : 0,
1368 sortsym[cnt]->ticks * tick_unit,
1369 0.0, /* FIXME: what's time for the children, recursive */
1370 sortsym[cnt]->calls,
1371 sortsym[cnt]->name, cnt);
1373 /* Info about the functions this function calls. */
1374 runp = sortsym[cnt]->tos;
1375 while (runp != NULL)
1377 printf (" %8.2f%8.2f%9" PRIdMAX "/",
1378 (runp->idx != (size_t) -1l
1379 ? sortsym[runp->idx]->ticks * tick_unit : 0.0),
1380 0.0, /* FIXME: what's time for the children, recursive */
1381 runp->count);
1383 if (runp->idx != (size_t) -1l)
1384 printf ("%-9" PRIdMAX " %s [%Zd]\n",
1385 sortsym[runp->idx]->calls,
1386 sortsym[runp->idx]->name,
1387 runp->idx);
1388 else
1389 fputs ("??? <UNKNOWN>\n\n", stdout);
1391 runp = runp->next;
1394 fputs ("-----------------------------------------------\n", stdout);
1399 static void
1400 generate_call_pair_list (struct profdata *profdata)
1402 size_t cnt;
1404 for (cnt = 0; cnt < symidx; ++cnt)
1405 if (sortsym[cnt]->froms != NULL || sortsym[cnt]->tos != NULL)
1407 struct arc_list *runp;
1409 /* First print the incoming arcs. */
1410 runp = sortsym[cnt]->froms;
1411 while (runp != NULL)
1413 if (runp->idx == (size_t) -1l)
1414 printf ("\
1415 <UNKNOWN> %-34s %9" PRIdMAX "\n",
1416 sortsym[cnt]->name, runp->count);
1417 runp = runp->next;
1420 /* Next the outgoing arcs. */
1421 runp = sortsym[cnt]->tos;
1422 while (runp != NULL)
1424 printf ("%-34s %-34s %9" PRIdMAX "\n",
1425 sortsym[cnt]->name,
1426 (runp->idx != (size_t) -1l
1427 ? sortsym[runp->idx]->name : "<UNKNOWN>"),
1428 runp->count);
1429 runp = runp->next;