(rcmd_af): Make from a union of the various needed types to avoid warnings.
[glibc/history.git] / elf / sprof.c
blobfd4ffaeaba4773d85fa47480621f72871326c3dd
1 /* Read and display shared object profiling data.
2 Copyright (C) 1997-2008, 2009 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 profdata
200 void *addr;
201 off_t size;
203 char *hist;
204 struct gmon_hist_hdr *hist_hdr;
205 uint16_t *kcount;
206 uint32_t narcs; /* Number of arcs in toset. */
207 struct here_cg_arc_record *data;
208 uint16_t *tos;
209 struct here_fromstruct *froms;
212 /* Search tree for symbols. */
213 static void *symroot;
214 static struct known_symbol **sortsym;
215 static size_t symidx;
216 static uintmax_t total_ticks;
218 /* Prototypes for local functions. */
219 static struct shobj *load_shobj (const char *name);
220 static void unload_shobj (struct shobj *shobj);
221 static struct profdata *load_profdata (const char *name, struct shobj *shobj);
222 static void unload_profdata (struct profdata *profdata);
223 static void count_total_ticks (struct shobj *shobj, struct profdata *profdata);
224 static void count_calls (struct shobj *shobj, struct profdata *profdata);
225 static void read_symbols (struct shobj *shobj);
226 static void add_arcs (struct profdata *profdata);
227 static void generate_flat_profile (struct profdata *profdata);
228 static void generate_call_graph (struct profdata *profdata);
229 static void generate_call_pair_list (struct profdata *profdata);
233 main (int argc, char *argv[])
235 const char *shobj;
236 const char *profdata;
237 struct shobj *shobj_handle;
238 struct profdata *profdata_handle;
239 int remaining;
241 setlocale (LC_ALL, "");
243 /* Initialize the message catalog. */
244 textdomain (_libc_intl_domainname);
246 /* Parse and process arguments. */
247 argp_parse (&argp, argc, argv, 0, &remaining, NULL);
249 if (argc - remaining == 0 || argc - remaining > 2)
251 /* We need exactly two non-option parameter. */
252 argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
253 program_invocation_short_name);
254 exit (1);
257 /* Get parameters. */
258 shobj = argv[remaining];
259 if (argc - remaining == 2)
260 profdata = argv[remaining + 1];
261 else
262 /* No filename for the profiling data given. We will determine it
263 from the soname of the shobj, later. */
264 profdata = NULL;
266 /* First see whether we can load the shared object. */
267 shobj_handle = load_shobj (shobj);
268 if (shobj_handle == NULL)
269 exit (1);
271 /* We can now determine the filename for the profiling data, if
272 nececessary. */
273 if (profdata == NULL)
275 char *newp;
276 const char *soname;
277 size_t soname_len;
279 soname = shobj_handle->soname ?: basename (shobj);
280 soname_len = strlen (soname);
281 newp = (char *) alloca (soname_len + sizeof ".profile");
282 stpcpy (mempcpy (newp, soname, soname_len), ".profile");
283 profdata = newp;
286 /* Now see whether the profiling data file matches the given object. */
287 profdata_handle = load_profdata (profdata, shobj_handle);
288 if (profdata_handle == NULL)
290 unload_shobj (shobj_handle);
292 exit (1);
295 read_symbols (shobj_handle);
297 /* Count the ticks. */
298 count_total_ticks (shobj_handle, profdata_handle);
300 /* Count the calls. */
301 count_calls (shobj_handle, profdata_handle);
303 /* Add the arc information. */
304 add_arcs (profdata_handle);
306 /* If no mode is specified fall back to the default mode. */
307 if (mode == NONE)
308 mode = DEFAULT_MODE;
310 /* Do some work. */
311 if (mode & FLAT_MODE)
312 generate_flat_profile (profdata_handle);
314 if (mode & CALL_GRAPH_MODE)
315 generate_call_graph (profdata_handle);
317 if (mode & CALL_PAIRS)
318 generate_call_pair_list (profdata_handle);
320 /* Free the resources. */
321 unload_shobj (shobj_handle);
322 unload_profdata (profdata_handle);
324 return 0;
328 /* Handle program arguments. */
329 static error_t
330 parse_opt (int key, char *arg, struct argp_state *state)
332 switch (key)
334 case 'c':
335 mode |= CALL_PAIRS;
336 break;
337 case 'p':
338 mode |= FLAT_MODE;
339 break;
340 case 'q':
341 mode |= CALL_GRAPH_MODE;
342 break;
343 case OPT_TEST:
344 do_test = 1;
345 break;
346 default:
347 return ARGP_ERR_UNKNOWN;
349 return 0;
353 static char *
354 more_help (int key, const char *text, void *input)
356 switch (key)
358 case ARGP_KEY_HELP_EXTRA:
359 /* We print some extra information. */
360 return strdup (gettext ("\
361 For bug reporting instructions, please see:\n\
362 <http://www.gnu.org/software/libc/bugs.html>.\n"));
363 default:
364 break;
366 return (char *) text;
370 /* Print the version information. */
371 static void
372 print_version (FILE *stream, struct argp_state *state)
374 fprintf (stream, "sprof (GNU %s) %s\n", PACKAGE, VERSION);
375 fprintf (stream, gettext ("\
376 Copyright (C) %s Free Software Foundation, Inc.\n\
377 This is free software; see the source for copying conditions. There is NO\n\
378 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
380 "2009");
381 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
385 /* Note that we must not use `dlopen' etc. The shobj object must not
386 be loaded for use. */
387 static struct shobj *
388 load_shobj (const char *name)
390 struct link_map *map = NULL;
391 struct shobj *result;
392 ElfW(Addr) mapstart = ~((ElfW(Addr)) 0);
393 ElfW(Addr) mapend = 0;
394 const ElfW(Phdr) *ph;
395 size_t textsize;
396 unsigned int log_hashfraction;
397 ElfW(Ehdr) *ehdr;
398 int fd;
399 ElfW(Shdr) *shdr;
400 size_t pagesize = getpagesize ();
402 /* Since we use dlopen() we must be prepared to work around the sometimes
403 strange lookup rules for the shared objects. If we have a file foo.so
404 in the current directory and the user specfies foo.so on the command
405 line (without specifying a directory) we should load the file in the
406 current directory even if a normal dlopen() call would read the other
407 file. We do this by adding a directory portion to the name. */
408 if (strchr (name, '/') == NULL)
410 char *load_name = (char *) alloca (strlen (name) + 3);
411 stpcpy (stpcpy (load_name, "./"), name);
413 map = (struct link_map *) dlopen (load_name, RTLD_LAZY | __RTLD_SPROF);
415 if (map == NULL)
417 map = (struct link_map *) dlopen (name, RTLD_LAZY | __RTLD_SPROF);
418 if (map == NULL)
420 error (0, errno, _("failed to load shared object `%s'"), name);
421 return NULL;
425 /* Prepare the result. */
426 result = (struct shobj *) calloc (1, sizeof (struct shobj));
427 if (result == NULL)
429 error (0, errno, _("cannot create internal descriptors"));
430 dlclose (map);
431 return NULL;
433 result->name = name;
434 result->map = map;
436 /* Compute the size of the sections which contain program code.
437 This must match the code in dl-profile.c (_dl_start_profile). */
438 for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
439 if (ph->p_type == PT_LOAD && (ph->p_flags & PF_X))
441 ElfW(Addr) start = (ph->p_vaddr & ~(pagesize - 1));
442 ElfW(Addr) end = ((ph->p_vaddr + ph->p_memsz + pagesize - 1)
443 & ~(pagesize - 1));
445 if (start < mapstart)
446 mapstart = start;
447 if (end > mapend)
448 mapend = end;
451 result->lowpc = ROUNDDOWN ((uintptr_t) (mapstart + map->l_addr),
452 HISTFRACTION * sizeof (HISTCOUNTER));
453 result->highpc = ROUNDUP ((uintptr_t) (mapend + map->l_addr),
454 HISTFRACTION * sizeof (HISTCOUNTER));
455 if (do_test)
456 printf ("load addr: %0#*" PRIxPTR "\n"
457 "lower bound PC: %0#*" PRIxPTR "\n"
458 "upper bound PC: %0#*" PRIxPTR "\n",
459 __ELF_NATIVE_CLASS == 32 ? 10 : 18, map->l_addr,
460 __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->lowpc,
461 __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->highpc);
463 textsize = result->highpc - result->lowpc;
464 result->kcountsize = textsize / HISTFRACTION;
465 result->hashfraction = HASHFRACTION;
466 if ((HASHFRACTION & (HASHFRACTION - 1)) == 0)
467 /* If HASHFRACTION is a power of two, mcount can use shifting
468 instead of integer division. Precompute shift amount. */
469 log_hashfraction = __builtin_ffs (result->hashfraction
470 * sizeof (struct here_fromstruct)) - 1;
471 else
472 log_hashfraction = -1;
473 if (do_test)
474 printf ("hashfraction = %d\ndivider = %Zu\n",
475 result->hashfraction,
476 result->hashfraction * sizeof (struct here_fromstruct));
477 result->tossize = textsize / HASHFRACTION;
478 result->fromlimit = textsize * ARCDENSITY / 100;
479 if (result->fromlimit < MINARCS)
480 result->fromlimit = MINARCS;
481 if (result->fromlimit > MAXARCS)
482 result->fromlimit = MAXARCS;
483 result->fromssize = result->fromlimit * sizeof (struct here_fromstruct);
485 result->expected_size = (sizeof (struct gmon_hdr)
486 + 4 + sizeof (struct gmon_hist_hdr)
487 + result->kcountsize
488 + 4 + 4
489 + (result->fromssize
490 * sizeof (struct here_cg_arc_record)));
492 if (do_test)
493 printf ("expected size: %Zd\n", result->expected_size);
495 #define SCALE_1_TO_1 0x10000L
497 if (result->kcountsize < result->highpc - result->lowpc)
499 size_t range = result->highpc - result->lowpc;
500 size_t quot = range / result->kcountsize;
502 if (quot >= SCALE_1_TO_1)
503 result->s_scale = 1;
504 else if (quot >= SCALE_1_TO_1 / 256)
505 result->s_scale = SCALE_1_TO_1 / quot;
506 else if (range > ULONG_MAX / 256)
507 result->s_scale = ((SCALE_1_TO_1 * 256)
508 / (range / (result->kcountsize / 256)));
509 else
510 result->s_scale = ((SCALE_1_TO_1 * 256)
511 / ((range * 256) / result->kcountsize));
513 else
514 result->s_scale = SCALE_1_TO_1;
516 if (do_test)
517 printf ("s_scale: %d\n", result->s_scale);
519 /* Determine the dynamic string table. */
520 if (map->l_info[DT_STRTAB] == NULL)
521 result->dynstrtab = NULL;
522 else
523 result->dynstrtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
524 if (do_test)
525 printf ("string table: %p\n", result->dynstrtab);
527 /* Determine the soname. */
528 if (map->l_info[DT_SONAME] == NULL)
529 result->soname = NULL;
530 else
531 result->soname = result->dynstrtab + map->l_info[DT_SONAME]->d_un.d_val;
532 if (do_test && result->soname != NULL)
533 printf ("soname: %s\n", result->soname);
535 /* Now we have to load the symbol table.
537 First load the section header table. */
538 ehdr = (ElfW(Ehdr) *) map->l_map_start;
540 /* Make sure we are on the right party. */
541 if (ehdr->e_shentsize != sizeof (ElfW(Shdr)))
542 abort ();
544 /* And we need the shared object file descriptor again. */
545 fd = open (map->l_name, O_RDONLY);
546 if (fd == -1)
547 /* Dooh, this really shouldn't happen. We know the file is available. */
548 error (EXIT_FAILURE, errno, _("Reopening shared object `%s' failed"),
549 map->l_name);
551 /* Map the section header. */
552 size_t size = ehdr->e_shnum * sizeof (ElfW(Shdr));
553 shdr = (ElfW(Shdr) *) alloca (size);
554 if (pread (fd, shdr, size, ehdr->e_shoff) != size)
555 error (EXIT_FAILURE, errno, _("reading of section headers failed"));
557 /* Get the section header string table. */
558 char *shstrtab = (char *) alloca (shdr[ehdr->e_shstrndx].sh_size);
559 if (pread (fd, shstrtab, shdr[ehdr->e_shstrndx].sh_size,
560 shdr[ehdr->e_shstrndx].sh_offset)
561 != shdr[ehdr->e_shstrndx].sh_size)
562 error (EXIT_FAILURE, errno,
563 _("reading of section header string table failed"));
565 /* Search for the ".symtab" section. */
566 ElfW(Shdr) *symtab_entry = NULL;
567 ElfW(Shdr) *debuglink_entry = NULL;
568 for (int idx = 0; idx < ehdr->e_shnum; ++idx)
569 if (shdr[idx].sh_type == SHT_SYMTAB
570 && strcmp (shstrtab + shdr[idx].sh_name, ".symtab") == 0)
572 symtab_entry = &shdr[idx];
573 break;
575 else if (shdr[idx].sh_type == SHT_PROGBITS
576 && strcmp (shstrtab + shdr[idx].sh_name, ".gnu_debuglink") == 0)
577 debuglink_entry = &shdr[idx];
579 /* Get the file name of the debuginfo file if necessary. */
580 int symfd = fd;
581 if (symtab_entry == NULL && debuglink_entry != NULL)
583 size_t size = debuglink_entry->sh_size;
584 char *debuginfo_fname = (char *) alloca (size + 1);
585 debuginfo_fname[size] = '\0';
586 if (pread (fd, debuginfo_fname, size, debuglink_entry->sh_offset)
587 != size)
589 fprintf (stderr, _("*** Cannot read debuginfo file name: %m\n"));
590 goto no_debuginfo;
593 static const char procpath[] = "/proc/self/fd/%d";
594 char origprocname[sizeof (procpath) + sizeof (int) * 3];
595 snprintf (origprocname, sizeof (origprocname), procpath, fd);
596 char *origlink = (char *) alloca (PATH_MAX + 1);
597 origlink[PATH_MAX] = '\0';
598 if (readlink (origprocname, origlink, PATH_MAX) == -1)
599 goto no_debuginfo;
601 /* Try to find the actual file. There are three places:
602 1. the same directory the DSO is in
603 2. in a subdir named .debug of the directory the DSO is in
604 3. in /usr/lib/debug/PATH-OF-DSO
606 char *realname = canonicalize_file_name (origlink);
607 char *cp = NULL;
608 if (realname == NULL || (cp = strrchr (realname, '/')) == NULL)
609 error (EXIT_FAILURE, errno, _("cannot determine file name"));
611 /* Leave the last slash in place. */
612 *++cp = '\0';
614 /* First add the debuginfo file name only. */
615 static const char usrlibdebug[]= "/usr/lib/debug/";
616 char *workbuf = (char *) alloca (sizeof (usrlibdebug)
617 + (cp - realname)
618 + strlen (debuginfo_fname));
619 strcpy (stpcpy (workbuf, realname), debuginfo_fname);
621 int fd2 = open (workbuf, O_RDONLY);
622 if (fd2 == -1)
624 strcpy (stpcpy (stpcpy (workbuf, realname), ".debug/"),
625 debuginfo_fname);
626 fd2 = open (workbuf, O_RDONLY);
627 if (fd2 == -1)
629 strcpy (stpcpy (stpcpy (workbuf, usrlibdebug), realname),
630 debuginfo_fname);
631 fd2 = open (workbuf, O_RDONLY);
635 if (fd2 != -1)
637 ElfW(Ehdr) ehdr2;
639 /* Read the ELF header. */
640 if (pread (fd2, &ehdr2, sizeof (ehdr2), 0) != sizeof (ehdr2))
641 error (EXIT_FAILURE, errno,
642 _("reading of ELF header failed"));
644 /* Map the section header. */
645 size_t size = ehdr2.e_shnum * sizeof (ElfW(Shdr));
646 ElfW(Shdr) *shdr2 = (ElfW(Shdr) *) alloca (size);
647 if (pread (fd2, shdr2, size, ehdr2.e_shoff) != size)
648 error (EXIT_FAILURE, errno,
649 _("reading of section headers failed"));
651 /* Get the section header string table. */
652 shstrtab = (char *) alloca (shdr2[ehdr2.e_shstrndx].sh_size);
653 if (pread (fd2, shstrtab, shdr2[ehdr2.e_shstrndx].sh_size,
654 shdr2[ehdr2.e_shstrndx].sh_offset)
655 != shdr2[ehdr2.e_shstrndx].sh_size)
656 error (EXIT_FAILURE, errno,
657 _("reading of section header string table failed"));
659 /* Search for the ".symtab" section. */
660 for (int idx = 0; idx < ehdr2.e_shnum; ++idx)
661 if (shdr2[idx].sh_type == SHT_SYMTAB
662 && strcmp (shstrtab + shdr2[idx].sh_name, ".symtab") == 0)
664 symtab_entry = &shdr2[idx];
665 shdr = shdr2;
666 symfd = fd2;
667 break;
670 if (fd2 != symfd)
671 close (fd2);
675 no_debuginfo:
676 if (symtab_entry == NULL)
678 fprintf (stderr, _("\
679 *** The file `%s' is stripped: no detailed analysis possible\n"),
680 name);
681 result->symtab = NULL;
682 result->strtab = NULL;
684 else
686 ElfW(Off) min_offset, max_offset;
687 ElfW(Shdr) *strtab_entry;
689 strtab_entry = &shdr[symtab_entry->sh_link];
691 /* Find the minimum and maximum offsets that include both the symbol
692 table and the string table. */
693 if (symtab_entry->sh_offset < strtab_entry->sh_offset)
695 min_offset = symtab_entry->sh_offset & ~(pagesize - 1);
696 max_offset = strtab_entry->sh_offset + strtab_entry->sh_size;
698 else
700 min_offset = strtab_entry->sh_offset & ~(pagesize - 1);
701 max_offset = symtab_entry->sh_offset + symtab_entry->sh_size;
704 result->symbol_map = mmap (NULL, max_offset - min_offset,
705 PROT_READ, MAP_SHARED|MAP_FILE, symfd,
706 min_offset);
707 if (result->symbol_map == MAP_FAILED)
708 error (EXIT_FAILURE, errno, _("failed to load symbol data"));
710 result->symtab
711 = (const ElfW(Sym) *) ((const char *) result->symbol_map
712 + (symtab_entry->sh_offset - min_offset));
713 result->symtab_size = symtab_entry->sh_size;
714 result->strtab = ((const char *) result->symbol_map
715 + (strtab_entry->sh_offset - min_offset));
716 result->symbol_mapsize = max_offset - min_offset;
719 /* Free the descriptor for the shared object. */
720 close (fd);
721 if (symfd != fd)
722 close (symfd);
724 return result;
728 static void
729 unload_shobj (struct shobj *shobj)
731 munmap (shobj->symbol_map, shobj->symbol_mapsize);
732 dlclose (shobj->map);
736 static struct profdata *
737 load_profdata (const char *name, struct shobj *shobj)
739 struct profdata *result;
740 int fd;
741 struct stat st;
742 void *addr;
743 struct gmon_hdr gmon_hdr;
744 struct gmon_hist_hdr hist_hdr;
745 uint32_t *narcsp;
746 size_t fromlimit;
747 struct here_cg_arc_record *data;
748 struct here_fromstruct *froms;
749 uint16_t *tos;
750 size_t fromidx;
751 size_t idx;
753 fd = open (name, O_RDONLY);
754 if (fd == -1)
756 char *ext_name;
758 if (errno != ENOENT || strchr (name, '/') != NULL)
759 /* The file exists but we are not allowed to read it or the
760 file does not exist and the name includes a path
761 specification.. */
762 return NULL;
764 /* A file with the given name does not exist in the current
765 directory, try it in the default location where the profiling
766 files are created. */
767 ext_name = (char *) alloca (strlen (name) + sizeof "/var/tmp/");
768 stpcpy (stpcpy (ext_name, "/var/tmp/"), name);
769 name = ext_name;
771 fd = open (ext_name, O_RDONLY);
772 if (fd == -1)
774 /* Even this file does not exist. */
775 error (0, errno, _("cannot load profiling data"));
776 return NULL;
780 /* We have found the file, now make sure it is the right one for the
781 data file. */
782 if (fstat (fd, &st) < 0)
784 error (0, errno, _("while stat'ing profiling data file"));
785 close (fd);
786 return NULL;
789 if ((size_t) st.st_size != shobj->expected_size)
791 error (0, 0,
792 _("profiling data file `%s' does not match shared object `%s'"),
793 name, shobj->name);
794 close (fd);
795 return NULL;
798 /* The data file is most probably the right one for our shared
799 object. Map it now. */
800 addr = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0);
801 if (addr == MAP_FAILED)
803 error (0, errno, _("failed to mmap the profiling data file"));
804 close (fd);
805 return NULL;
808 /* We don't need the file desriptor anymore. */
809 if (close (fd) < 0)
811 error (0, errno, _("error while closing the profiling data file"));
812 munmap (addr, st.st_size);
813 return NULL;
816 /* Prepare the result. */
817 result = (struct profdata *) calloc (1, sizeof (struct profdata));
818 if (result == NULL)
820 error (0, errno, _("cannot create internal descriptor"));
821 munmap (addr, st.st_size);
822 return NULL;
825 /* Store the address and size so that we can later free the resources. */
826 result->addr = addr;
827 result->size = st.st_size;
829 /* Pointer to data after the header. */
830 result->hist = (char *) ((struct gmon_hdr *) addr + 1);
831 result->hist_hdr = (struct gmon_hist_hdr *) ((char *) result->hist
832 + sizeof (uint32_t));
833 result->kcount = (uint16_t *) ((char *) result->hist + sizeof (uint32_t)
834 + sizeof (struct gmon_hist_hdr));
836 /* Compute pointer to array of the arc information. */
837 narcsp = (uint32_t *) ((char *) result->kcount + shobj->kcountsize
838 + sizeof (uint32_t));
839 result->narcs = *narcsp;
840 result->data = (struct here_cg_arc_record *) ((char *) narcsp
841 + sizeof (uint32_t));
843 /* Create the gmon_hdr we expect or write. */
844 memset (&gmon_hdr, '\0', sizeof (struct gmon_hdr));
845 memcpy (&gmon_hdr.cookie[0], GMON_MAGIC, sizeof (gmon_hdr.cookie));
846 *(int32_t *) gmon_hdr.version = GMON_SHOBJ_VERSION;
848 /* Create the hist_hdr we expect or write. */
849 *(char **) hist_hdr.low_pc = (char *) shobj->lowpc - shobj->map->l_addr;
850 *(char **) hist_hdr.high_pc = (char *) shobj->highpc - shobj->map->l_addr;
851 if (do_test)
852 printf ("low_pc = %p\nhigh_pc = %p\n",
853 *(char **) hist_hdr.low_pc, *(char **) hist_hdr.high_pc);
854 *(int32_t *) hist_hdr.hist_size = shobj->kcountsize / sizeof (HISTCOUNTER);
855 *(int32_t *) hist_hdr.prof_rate = __profile_frequency ();
856 strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen));
857 hist_hdr.dimen_abbrev = 's';
859 /* Test whether the header of the profiling data is ok. */
860 if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0
861 || *(uint32_t *) result->hist != GMON_TAG_TIME_HIST
862 || memcmp (result->hist_hdr, &hist_hdr,
863 sizeof (struct gmon_hist_hdr)) != 0
864 || narcsp[-1] != GMON_TAG_CG_ARC)
866 error (0, 0, _("`%s' is no correct profile data file for `%s'"),
867 name, shobj->name);
868 if (do_test)
870 if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0)
871 puts ("gmon_hdr differs");
872 if (*(uint32_t *) result->hist != GMON_TAG_TIME_HIST)
873 puts ("result->hist differs");
874 if (memcmp (result->hist_hdr, &hist_hdr,
875 sizeof (struct gmon_hist_hdr)) != 0)
876 puts ("hist_hdr differs");
877 if (narcsp[-1] != GMON_TAG_CG_ARC)
878 puts ("narcsp[-1] differs");
880 free (result);
881 munmap (addr, st.st_size);
882 return NULL;
885 /* We are pretty sure now that this is a correct input file. Set up
886 the remaining information in the result structure and return. */
887 result->tos = (uint16_t *) calloc (shobj->tossize + shobj->fromssize, 1);
888 if (result->tos == NULL)
890 error (0, errno, _("cannot create internal descriptor"));
891 munmap (addr, st.st_size);
892 free (result);
893 return NULL;
896 result->froms = (struct here_fromstruct *) ((char *) result->tos
897 + shobj->tossize);
898 fromidx = 0;
900 /* Now we have to process all the arc count entries. */
901 fromlimit = shobj->fromlimit;
902 data = result->data;
903 froms = result->froms;
904 tos = result->tos;
905 for (idx = 0; idx < MIN (*narcsp, fromlimit); ++idx)
907 size_t to_index;
908 size_t newfromidx;
909 to_index = (data[idx].self_pc / (shobj->hashfraction * sizeof (*tos)));
910 newfromidx = fromidx++;
911 froms[newfromidx].here = &data[idx];
912 froms[newfromidx].link = tos[to_index];
913 tos[to_index] = newfromidx;
916 return result;
920 static void
921 unload_profdata (struct profdata *profdata)
923 free (profdata->tos);
924 munmap (profdata->addr, profdata->size);
925 free (profdata);
929 static void
930 count_total_ticks (struct shobj *shobj, struct profdata *profdata)
932 volatile uint16_t *kcount = profdata->kcount;
933 size_t maxkidx = shobj->kcountsize;
934 size_t factor = 2 * (65536 / shobj->s_scale);
935 size_t kidx = 0;
936 size_t sidx = 0;
938 while (sidx < symidx)
940 uintptr_t start = sortsym[sidx]->addr;
941 uintptr_t end = start + sortsym[sidx]->size;
943 while (kidx < maxkidx && factor * kidx < start)
944 ++kidx;
945 if (kidx == maxkidx)
946 break;
948 while (kidx < maxkidx && factor * kidx < end)
949 sortsym[sidx]->ticks += kcount[kidx++];
950 if (kidx == maxkidx)
951 break;
953 total_ticks += sortsym[sidx++]->ticks;
958 static size_t
959 find_symbol (uintptr_t addr)
961 size_t sidx = 0;
963 while (sidx < symidx)
965 uintptr_t start = sortsym[sidx]->addr;
966 uintptr_t end = start + sortsym[sidx]->size;
968 if (addr >= start && addr < end)
969 return sidx;
971 if (addr < start)
972 break;
974 ++sidx;
977 return (size_t) -1l;
981 static void
982 count_calls (struct shobj *shobj, struct profdata *profdata)
984 struct here_cg_arc_record *data = profdata->data;
985 uint32_t narcs = profdata->narcs;
986 uint32_t cnt;
988 for (cnt = 0; cnt < narcs; ++cnt)
990 uintptr_t here = data[cnt].self_pc;
991 size_t symbol_idx;
993 /* Find the symbol for this address. */
994 symbol_idx = find_symbol (here);
995 if (symbol_idx != (size_t) -1l)
996 sortsym[symbol_idx]->calls += data[cnt].count;
1001 static int
1002 symorder (const void *o1, const void *o2)
1004 const struct known_symbol *p1 = (const struct known_symbol *) o1;
1005 const struct known_symbol *p2 = (const struct known_symbol *) o2;
1007 return p1->addr - p2->addr;
1011 static void
1012 printsym (const void *node, VISIT value, int level)
1014 if (value == leaf || value == postorder)
1015 sortsym[symidx++] = *(struct known_symbol **) node;
1019 static void
1020 read_symbols (struct shobj *shobj)
1022 int n = 0;
1024 /* Initialize the obstacks. */
1025 #define obstack_chunk_alloc malloc
1026 #define obstack_chunk_free free
1027 obstack_init (&shobj->ob_str);
1028 obstack_init (&shobj->ob_sym);
1029 obstack_init (&ob_list);
1031 /* Process the symbols. */
1032 if (shobj->symtab != NULL)
1034 const ElfW(Sym) *sym = shobj->symtab;
1035 const ElfW(Sym) *sym_end
1036 = (const ElfW(Sym) *) ((const char *) sym + shobj->symtab_size);
1037 for (; sym < sym_end; sym++)
1038 if ((ELFW(ST_TYPE) (sym->st_info) == STT_FUNC
1039 || ELFW(ST_TYPE) (sym->st_info) == STT_NOTYPE)
1040 && sym->st_size != 0)
1042 struct known_symbol **existp;
1043 struct known_symbol *newsym
1044 = (struct known_symbol *) obstack_alloc (&shobj->ob_sym,
1045 sizeof (*newsym));
1046 if (newsym == NULL)
1047 error (EXIT_FAILURE, errno, _("cannot allocate symbol data"));
1049 newsym->name = &shobj->strtab[sym->st_name];
1050 newsym->addr = sym->st_value;
1051 newsym->size = sym->st_size;
1052 newsym->weak = ELFW(ST_BIND) (sym->st_info) == STB_WEAK;
1053 newsym->hidden = (ELFW(ST_VISIBILITY) (sym->st_other)
1054 != STV_DEFAULT);
1055 newsym->ticks = 0;
1056 newsym->calls = 0;
1058 existp = tfind (newsym, &symroot, symorder);
1059 if (existp == NULL)
1061 /* New function. */
1062 tsearch (newsym, &symroot, symorder);
1063 ++n;
1065 else
1067 /* The function is already defined. See whether we have
1068 a better name here. */
1069 if (((*existp)->hidden && !newsym->hidden)
1070 || ((*existp)->name[0] == '_' && newsym->name[0] != '_')
1071 || ((*existp)->name[0] != '_' && newsym->name[0] != '_'
1072 && ((*existp)->weak && !newsym->weak)))
1073 *existp = newsym;
1074 else
1075 /* We don't need the allocated memory. */
1076 obstack_free (&shobj->ob_sym, newsym);
1080 else
1082 /* Blarg, the binary is stripped. We have to rely on the
1083 information contained in the dynamic section of the object. */
1084 const ElfW(Sym) *symtab = (ElfW(Sym) *) D_PTR (shobj->map,
1085 l_info[DT_SYMTAB]);
1086 const char *strtab = (const char *) D_PTR (shobj->map,
1087 l_info[DT_STRTAB]);
1089 /* We assume that the string table follows the symbol table,
1090 because there is no way in ELF to know the size of the
1091 dynamic symbol table without looking at the section headers. */
1092 while ((void *) symtab < (void *) strtab)
1094 if ((ELFW(ST_TYPE)(symtab->st_info) == STT_FUNC
1095 || ELFW(ST_TYPE)(symtab->st_info) == STT_NOTYPE)
1096 && symtab->st_size != 0)
1098 struct known_symbol *newsym;
1099 struct known_symbol **existp;
1101 newsym =
1102 (struct known_symbol *) obstack_alloc (&shobj->ob_sym,
1103 sizeof (*newsym));
1104 if (newsym == NULL)
1105 error (EXIT_FAILURE, errno, _("cannot allocate symbol data"));
1107 newsym->name = &strtab[symtab->st_name];
1108 newsym->addr = symtab->st_value;
1109 newsym->size = symtab->st_size;
1110 newsym->weak = ELFW(ST_BIND) (symtab->st_info) == STB_WEAK;
1111 newsym->hidden = (ELFW(ST_VISIBILITY) (symtab->st_other)
1112 != STV_DEFAULT);
1113 newsym->ticks = 0;
1114 newsym->froms = NULL;
1115 newsym->tos = NULL;
1117 existp = tfind (newsym, &symroot, symorder);
1118 if (existp == NULL)
1120 /* New function. */
1121 tsearch (newsym, &symroot, symorder);
1122 ++n;
1124 else
1126 /* The function is already defined. See whether we have
1127 a better name here. */
1128 if (((*existp)->hidden && !newsym->hidden)
1129 || ((*existp)->name[0] == '_' && newsym->name[0] != '_')
1130 || ((*existp)->name[0] != '_' && newsym->name[0] != '_'
1131 && ((*existp)->weak && !newsym->weak)))
1132 *existp = newsym;
1133 else
1134 /* We don't need the allocated memory. */
1135 obstack_free (&shobj->ob_sym, newsym);
1139 ++symtab;
1143 sortsym = malloc (n * sizeof (struct known_symbol *));
1144 if (sortsym == NULL)
1145 abort ();
1147 twalk (symroot, printsym);
1151 static void
1152 add_arcs (struct profdata *profdata)
1154 uint32_t narcs = profdata->narcs;
1155 struct here_cg_arc_record *data = profdata->data;
1156 uint32_t cnt;
1158 for (cnt = 0; cnt < narcs; ++cnt)
1160 /* First add the incoming arc. */
1161 size_t sym_idx = find_symbol (data[cnt].self_pc);
1163 if (sym_idx != (size_t) -1l)
1165 struct known_symbol *sym = sortsym[sym_idx];
1166 struct arc_list *runp = sym->froms;
1168 while (runp != NULL
1169 && ((data[cnt].from_pc == 0 && runp->idx != (size_t) -1l)
1170 || (data[cnt].from_pc != 0
1171 && (runp->idx == (size_t) -1l
1172 || data[cnt].from_pc < sortsym[runp->idx]->addr
1173 || (data[cnt].from_pc
1174 >= (sortsym[runp->idx]->addr
1175 + sortsym[runp->idx]->size))))))
1176 runp = runp->next;
1178 if (runp == NULL)
1180 /* We need a new entry. */
1181 struct arc_list *newp = (struct arc_list *)
1182 obstack_alloc (&ob_list, sizeof (struct arc_list));
1184 if (data[cnt].from_pc == 0)
1185 newp->idx = (size_t) -1l;
1186 else
1187 newp->idx = find_symbol (data[cnt].from_pc);
1188 newp->count = data[cnt].count;
1189 newp->next = sym->froms;
1190 sym->froms = newp;
1192 else
1193 /* Increment the counter for the found entry. */
1194 runp->count += data[cnt].count;
1197 /* Now add it to the appropriate outgoing list. */
1198 sym_idx = find_symbol (data[cnt].from_pc);
1199 if (sym_idx != (size_t) -1l)
1201 struct known_symbol *sym = sortsym[sym_idx];
1202 struct arc_list *runp = sym->tos;
1204 while (runp != NULL
1205 && (runp->idx == (size_t) -1l
1206 || data[cnt].self_pc < sortsym[runp->idx]->addr
1207 || data[cnt].self_pc >= (sortsym[runp->idx]->addr
1208 + sortsym[runp->idx]->size)))
1209 runp = runp->next;
1211 if (runp == NULL)
1213 /* We need a new entry. */
1214 struct arc_list *newp = (struct arc_list *)
1215 obstack_alloc (&ob_list, sizeof (struct arc_list));
1217 newp->idx = find_symbol (data[cnt].self_pc);
1218 newp->count = data[cnt].count;
1219 newp->next = sym->tos;
1220 sym->tos = newp;
1222 else
1223 /* Increment the counter for the found entry. */
1224 runp->count += data[cnt].count;
1230 static int
1231 countorder (const void *p1, const void *p2)
1233 struct known_symbol *s1 = (struct known_symbol *) p1;
1234 struct known_symbol *s2 = (struct known_symbol *) p2;
1236 if (s1->ticks != s2->ticks)
1237 return (int) (s2->ticks - s1->ticks);
1239 if (s1->calls != s2->calls)
1240 return (int) (s2->calls - s1->calls);
1242 return strcmp (s1->name, s2->name);
1246 static double tick_unit;
1247 static uintmax_t cumu_ticks;
1249 static void
1250 printflat (const void *node, VISIT value, int level)
1252 if (value == leaf || value == postorder)
1254 struct known_symbol *s = *(struct known_symbol **) node;
1256 cumu_ticks += s->ticks;
1258 printf ("%6.2f%10.2f%9.2f%9" PRIdMAX "%9.2f %s\n",
1259 total_ticks ? (100.0 * s->ticks) / total_ticks : 0.0,
1260 tick_unit * cumu_ticks,
1261 tick_unit * s->ticks,
1262 s->calls,
1263 s->calls ? (s->ticks * 1000000) * tick_unit / s->calls : 0,
1264 /* FIXME: don't know about called functions. */
1265 s->name);
1270 /* ARGUSED */
1271 static void
1272 freenoop (void *p)
1277 static void
1278 generate_flat_profile (struct profdata *profdata)
1280 size_t n;
1281 void *data = NULL;
1283 tick_unit = 1.0 / *(uint32_t *) profdata->hist_hdr->prof_rate;
1285 printf ("Flat profile:\n\n"
1286 "Each sample counts as %g %s.\n",
1287 tick_unit, profdata->hist_hdr->dimen);
1288 fputs (" % cumulative self self total\n"
1289 " time seconds seconds calls us/call us/call name\n",
1290 stdout);
1292 for (n = 0; n < symidx; ++n)
1293 if (sortsym[n]->calls != 0 || sortsym[n]->ticks != 0)
1294 tsearch (sortsym[n], &data, countorder);
1296 twalk (data, printflat);
1298 tdestroy (data, freenoop);
1302 static void
1303 generate_call_graph (struct profdata *profdata)
1305 size_t cnt;
1307 puts ("\nindex % time self children called name\n");
1309 for (cnt = 0; cnt < symidx; ++cnt)
1310 if (sortsym[cnt]->froms != NULL || sortsym[cnt]->tos != NULL)
1312 struct arc_list *runp;
1313 size_t n;
1315 /* First print the from-information. */
1316 runp = sortsym[cnt]->froms;
1317 while (runp != NULL)
1319 printf (" %8.2f%8.2f%9" PRIdMAX "/%-9" PRIdMAX " %s",
1320 (runp->idx != (size_t) -1l
1321 ? sortsym[runp->idx]->ticks * tick_unit : 0.0),
1322 0.0, /* FIXME: what's time for the children, recursive */
1323 runp->count, sortsym[cnt]->calls,
1324 (runp->idx != (size_t) -1l ?
1325 sortsym[runp->idx]->name : "<UNKNOWN>"));
1327 if (runp->idx != (size_t) -1l)
1328 printf (" [%Zd]", runp->idx);
1329 putchar_unlocked ('\n');
1331 runp = runp->next;
1334 /* Info abount the function itself. */
1335 n = printf ("[%Zu]", cnt);
1336 printf ("%*s%5.1f%8.2f%8.2f%9" PRIdMAX " %s [%Zd]\n",
1337 (int) (7 - n), " ",
1338 total_ticks ? (100.0 * sortsym[cnt]->ticks) / total_ticks : 0,
1339 sortsym[cnt]->ticks * tick_unit,
1340 0.0, /* FIXME: what's time for the children, recursive */
1341 sortsym[cnt]->calls,
1342 sortsym[cnt]->name, cnt);
1344 /* Info about the functions this function calls. */
1345 runp = sortsym[cnt]->tos;
1346 while (runp != NULL)
1348 printf (" %8.2f%8.2f%9" PRIdMAX "/",
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);
1354 if (runp->idx != (size_t) -1l)
1355 printf ("%-9" PRIdMAX " %s [%Zd]\n",
1356 sortsym[runp->idx]->calls,
1357 sortsym[runp->idx]->name,
1358 runp->idx);
1359 else
1360 fputs ("??? <UNKNOWN>\n\n", stdout);
1362 runp = runp->next;
1365 fputs ("-----------------------------------------------\n", stdout);
1370 static void
1371 generate_call_pair_list (struct profdata *profdata)
1373 size_t cnt;
1375 for (cnt = 0; cnt < symidx; ++cnt)
1376 if (sortsym[cnt]->froms != NULL || sortsym[cnt]->tos != NULL)
1378 struct arc_list *runp;
1380 /* First print the incoming arcs. */
1381 runp = sortsym[cnt]->froms;
1382 while (runp != NULL)
1384 if (runp->idx == (size_t) -1l)
1385 printf ("\
1386 <UNKNOWN> %-34s %9" PRIdMAX "\n",
1387 sortsym[cnt]->name, runp->count);
1388 runp = runp->next;
1391 /* Next the outgoing arcs. */
1392 runp = sortsym[cnt]->tos;
1393 while (runp != NULL)
1395 printf ("%-34s %-34s %9" PRIdMAX "\n",
1396 sortsym[cnt]->name,
1397 (runp->idx != (size_t) -1l
1398 ? sortsym[runp->idx]->name : "<UNKNOWN>"),
1399 runp->count);
1400 runp = runp->next;