4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
40 static void debug_dup_del(nltype
*, nltype
*);
42 #define DPRINTF(msg, file) if (debug & ELFDEBUG) \
43 (void) printf(msg, file);
45 #define PRINTF(msg) if (debug & ELFDEBUG) \
48 #define DEBUG_DUP_DEL(keeper, louser) if (debug & ELFDEBUG) \
49 debug_dup_del(keeper, louser);
52 #define DPRINTF(msg, file)
54 #define DEBUG_DUP_DEL(keeper, louser)
57 size_t textbegin
, textsize
;
59 /* Prototype definitions first */
61 static void process(char *filename
, int fd
);
62 static void get_symtab(Elf
*elf
, mod_info_t
*module
);
63 static void get_textseg(Elf
*elf
, int fd
);
64 static void save_aout_info(char *);
67 fatal_error(char *error
)
69 (void) fprintf(stderr
,
70 "Fatal ELF error: %s (%s)\n", error
, elf_errmsg(-1));
75 is_shared_obj(char *name
)
81 if ((fd
= open(name
, O_RDONLY
)) == -1) {
82 (void) fprintf(stderr
, "%s: can't open `%s'\n", whoami
, name
);
86 if (elf_version(EV_CURRENT
) == EV_NONE
)
87 fatal_error("libelf is out of date");
89 if ((elf
= elf_begin(fd
, ELF_C_READ
, NULL
)) == NULL
)
90 fatal_error("can't read as ELF file");
92 if (gelf_getehdr(elf
, &ehdr
) == NULL
)
93 fatal_error("can't read ehdr");
98 if (ehdr
.e_type
== ET_DYN
)
105 save_aout_info(char *aoutname
)
108 extern fl_info_t aout_info
;
110 if (stat(aoutname
, &buf
) == -1) {
111 (void) fprintf(stderr
, "%s: can't get info on `%s'\n",
116 aout_info
.dev
= buf
.st_dev
;
117 aout_info
.ino
= buf
.st_ino
;
118 aout_info
.mtime
= buf
.st_mtime
;
119 aout_info
.size
= buf
.st_size
;
123 getnfile(char *aoutname
)
127 DPRINTF(" Attempting to open %s \n", aoutname
);
128 if ((fd
= open((aoutname
), O_RDONLY
)) == -1) {
129 (void) fprintf(stderr
, "%s: can't open `%s'\n",
133 process(aoutname
, fd
);
134 save_aout_info(aoutname
);
140 get_txtorigin(Elf
*elf
)
145 GElf_Addr txt_origin
= 0;
146 bool first_load_seg
= TRUE
;
148 if (gelf_getehdr(elf
, &ehdr
) == NULL
)
149 fatal_error("can't read ehdr");
151 for (ndx
= 0; ndx
< ehdr
.e_phnum
; ndx
++) {
152 if (gelf_getphdr(elf
, ndx
, &phdr
) == NULL
)
155 if ((phdr
.p_type
== PT_LOAD
) && !(phdr
.p_flags
& PF_W
)) {
156 if (first_load_seg
|| phdr
.p_vaddr
< txt_origin
)
157 txt_origin
= phdr
.p_vaddr
;
160 first_load_seg
= FALSE
;
168 process_namelist(mod_info_t
*module
)
173 if ((fd
= open(module
->name
, O_RDONLY
)) == -1) {
174 (void) fprintf(stderr
, "%s: can't read %s\n",
175 whoami
, module
->name
);
176 (void) fprintf(stderr
, "Exiting due to error(s)...\n");
181 * libelf's version already verified in processing a.out,
182 * so directly do elf_begin()
184 if ((elf
= elf_begin(fd
, ELF_C_READ
, NULL
)) == NULL
)
185 fatal_error("can't read as ELF file");
188 module
->txt_origin
= get_txtorigin(elf
);
189 get_symtab(elf
, module
);
190 module
->active
= TRUE
;
194 * Get the ELF header and, if it exists, call get_symtab()
195 * to begin processing of the file; otherwise, return from
196 * processing the file with a warning.
199 process(char *filename
, int fd
)
205 if (elf_version(EV_CURRENT
) == EV_NONE
)
206 fatal_error("libelf is out of date");
208 if ((elf
= elf_begin(fd
, ELF_C_READ
, NULL
)) == NULL
)
209 fatal_error("can't read as ELF file");
211 if (gelf_getclass(elf
) == ELFCLASS64
)
215 * Initialize active modules list. Note that we set the end
216 * address while reading the symbol table, in get_symtab
220 modules
.txt_origin
= get_txtorigin(elf
);
221 modules
.load_base
= modules
.txt_origin
;
222 if ((modules
.name
= malloc(strlen(filename
) + 1)) == NULL
) {
223 (void) fprintf(stderr
, "%s: can't malloc %d bytes",
224 whoami
, strlen(filename
) + 1);
225 exit(EX_UNAVAILABLE
);
227 (void) strcpy(modules
.name
, filename
);
229 get_symtab(elf
, &modules
);
231 modules
.load_end
= modules
.data_end
;
232 modules
.active
= TRUE
;
236 get_textseg(elf
, fd
);
240 get_textseg(Elf
*elf
, int fd
)
246 if (gelf_getehdr(elf
, &ehdr
) == NULL
)
247 fatal_error("can't read ehdr");
249 for (i
= 0; i
< ehdr
.e_phnum
; i
++) {
251 if (gelf_getphdr(elf
, i
, &phdr
) == NULL
)
254 if (!(phdr
.p_flags
& PF_W
) && (phdr
.p_filesz
> textsize
)) {
258 * We could have multiple loadable text segments;
259 * keep the largest we find.
265 * gprof is a 32-bit program; if this text segment
266 * has a > 32-bit offset or length, it's too big.
268 chk
= (size_t)phdr
.p_vaddr
+ (size_t)phdr
.p_filesz
;
269 if (phdr
.p_vaddr
+ phdr
.p_filesz
!= (GElf_Xword
)chk
)
270 fatal_error("text segment too large for -c");
272 textbegin
= (size_t)phdr
.p_vaddr
;
273 textsize
= (size_t)phdr
.p_filesz
;
275 textspace
= malloc(textsize
);
277 if (lseek(fd
, (off_t
)phdr
.p_offset
, SEEK_SET
) !=
278 (off_t
)phdr
.p_offset
)
279 fatal_error("cannot seek to text section");
281 if (read(fd
, textspace
, textsize
) != textsize
)
282 fatal_error("cannot read text");
287 fatal_error("can't find text segment");
292 debug_dup_del(nltype
* keeper
, nltype
* louser
)
294 (void) printf("remove_dup_syms: discarding sym %s over sym %s\n",
295 louser
->name
, keeper
->name
);
300 remove_dup_syms(nltype
*nl
, sztype
*sym_count
)
307 if ((orig_list
= malloc(sizeof (nltype
) * *sym_count
)) == NULL
) {
308 (void) fprintf(stderr
,
309 "gprof: remove_dup_syms: malloc failed\n");
310 (void) fprintf(stderr
, "Exiting due to error(s)...\n");
311 exit(EX_UNAVAILABLE
);
313 (void) memcpy(orig_list
, nl
, sizeof (nltype
) * *sym_count
);
315 for (i
= 0, index
= 0, nextsym
= 1; nextsym
< *sym_count
; nextsym
++) {
321 * If orig_list[nextsym] points to a new symvalue, then we
322 * will copy our keeper and move on to the next symbol.
324 if ((orig_list
+ i
)->value
< (orig_list
+ nextsym
)->value
) {
325 *(nl
+ index
++) = *(orig_list
+i
);
331 * If these two symbols have the same info, then we
332 * keep the first and keep checking for dups.
334 if ((orig_list
+ i
)->syminfo
==
335 (orig_list
+ nextsym
)->syminfo
) {
336 DEBUG_DUP_DEL(orig_list
+ i
, orig_list
+ nextsym
);
339 n_bind
= ELF32_ST_BIND((orig_list
+ nextsym
)->syminfo
);
340 i_type
= ELF32_ST_TYPE((orig_list
+ i
)->syminfo
);
341 n_type
= ELF32_ST_TYPE((orig_list
+ nextsym
)->syminfo
);
344 * If they have the same type we take the stronger
347 if (i_type
== n_type
) {
348 if (n_bind
== STB_WEAK
) {
349 DEBUG_DUP_DEL((orig_list
+ i
),
350 (orig_list
+ nextsym
));
353 DEBUG_DUP_DEL((orig_list
+ nextsym
),
360 * If the first symbol isn't of type NOTYPE then it must
363 if (i_type
!= STT_NOTYPE
) {
364 DEBUG_DUP_DEL((orig_list
+ i
),
365 (orig_list
+ nextsym
));
370 * Throw away the first one and take the new
373 DEBUG_DUP_DEL((orig_list
+ nextsym
), (orig_list
+ i
));
377 if ((orig_list
+ i
)->value
> (nl
+ index
- 1)->value
)
378 *(nl
+ index
++) = *(orig_list
+i
);
384 * compare either by name or by value for sorting.
385 * This is the comparison function called by qsort to
386 * sort the symbols either by name or value when requested.
389 compare(const void *arg1
, const void *arg2
)
391 nltype
*a
= (nltype
*)arg1
;
392 nltype
*b
= (nltype
*)arg2
;
394 if (a
->value
> b
->value
)
397 return ((a
->value
== b
->value
) - 1);
401 is_function(Elf
*elf
, GElf_Sym
*sym
)
407 * With shared objects, it is possible we come across a function
408 * that's global, but is undefined. The definition is probably
409 * elsewhere, so we'll have to skip it as far as this object is
412 if (sym
->st_shndx
== SHN_UNDEF
)
415 if (GELF_ST_TYPE(sym
->st_info
) == STT_FUNC
) {
416 if (GELF_ST_BIND(sym
->st_info
) == STB_GLOBAL
)
419 if (GELF_ST_BIND(sym
->st_info
) == STB_WEAK
)
422 if (!aflag
&& GELF_ST_BIND(sym
->st_info
) == STB_LOCAL
)
427 * It's not a function; determine if it's in an executable section.
429 if (GELF_ST_TYPE(sym
->st_info
) != STT_NOTYPE
)
433 * If it isn't global, and it isn't weak, and it either isn't
434 * local or the "all flag" isn't set, then get out.
436 if (GELF_ST_BIND(sym
->st_info
) != STB_GLOBAL
&&
437 GELF_ST_BIND(sym
->st_info
) != STB_WEAK
&&
438 (GELF_ST_BIND(sym
->st_info
) != STB_LOCAL
|| aflag
))
441 if (sym
->st_shndx
>= SHN_LORESERVE
)
444 scn
= elf_getscn(elf
, sym
->st_shndx
);
445 (void) gelf_getshdr(scn
, &shdr
);
447 if (!(shdr
.sh_flags
& SHF_EXECINSTR
))
454 get_symtab(Elf
*elf
, mod_info_t
*module
)
456 Elf_Scn
*scn
= NULL
, *sym_pri
= NULL
, *sym_aux
= NULL
;
457 GElf_Word strndx
= 0;
459 Elf_Data
*symdata_pri
;
460 Elf_Data
*symdata_aux
;
461 GElf_Xword nsyms_pri
, nsyms_aux
= 0;
462 nltype
*etext
= NULL
;
463 nltype
*l_nl
, *l_npe
;
465 extern sztype total_names
;
466 int symtab_found
= 0;
470 * Scan the section headers looking for a symbol table. Our
471 * preference is to use .symtab, because it contains the full
472 * set of symbols. If we find it, we stop looking immediately
473 * and use it. In the absence of a .symtab section, we are
474 * willing to use the dynamic symbol table (.dynsym), possibly
475 * augmented by the .SUNW_ldynsym, which contains local symbols.
477 while ((symtab_found
== 0) && ((scn
= elf_nextscn(elf
, scn
)) != NULL
)) {
480 if (gelf_getshdr(scn
, &shdr
) == NULL
)
483 switch (shdr
.sh_type
) {
485 nsyms_pri
= shdr
.sh_size
/ shdr
.sh_entsize
;
486 strndx
= shdr
.sh_link
;
488 /* Throw away .SUNW_ldynsym. It is for .dynsym only */
491 /* We have found the best symbol table. Stop looking */
496 /* We will use .dynsym if no .symtab is found */
497 nsyms_pri
= shdr
.sh_size
/ shdr
.sh_entsize
;
498 strndx
= shdr
.sh_link
;
502 case SHT_SUNW_LDYNSYM
:
503 /* Auxiliary table, used with .dynsym */
504 nsyms_aux
= shdr
.sh_size
/ shdr
.sh_entsize
;
510 if (sym_pri
== NULL
|| strndx
== 0)
511 fatal_error("can't find symbol table.\n");
513 nsyms
= (sztype
)(nsyms_pri
+ nsyms_aux
);
514 if ((nsyms_pri
+ nsyms_aux
) != (GElf_Xword
)nsyms
)
516 "32-bit gprof cannot handle more than 2^32 symbols");
518 if ((symdata_pri
= elf_getdata(sym_pri
, NULL
)) == NULL
)
519 fatal_error("can't read symbol data.\n");
521 if ((sym_aux
!= NULL
) &&
522 ((symdata_aux
= elf_getdata(sym_aux
, NULL
)) == NULL
))
523 fatal_error("can't read .SUNW_ldynsym symbol data.\n");
525 if ((l_nl
= l_npe
= (nltype
*)calloc(nsyms
+ PRF_SYMCNT
,
526 sizeof (nltype
))) == NULL
)
527 fatal_error("cannot allocate symbol data.\n");
530 * Now we need to cruise through the symbol table eliminating
531 * all non-functions from consideration, and making strings
536 for (i
= 1; i
< nsyms
; i
++) {
541 * Look up the symbol. In the case where we have a
542 * .SUNW_ldynsym/.dynsym pair, we treat them as a single
543 * logical table, with the data from .SUNW_ldynsym coming
544 * before the data in .dynsym.
547 (void) gelf_getsym(symdata_pri
, i
- nsyms_aux
, &gsym
);
549 (void) gelf_getsym(symdata_aux
, i
, &gsym
);
551 name
= elf_strptr(elf
, strndx
, gsym
.st_name
);
554 * We're interested in this symbol if it's a function or
555 * if it's the symbol "_etext"
557 if (is_function(elf
, &gsym
) || strcmp(name
, PRF_ETEXT
) == 0) {
560 l_npe
->value
= gsym
.st_value
;
561 l_npe
->sz
= gsym
.st_size
;
562 l_npe
->syminfo
= gsym
.st_info
;
563 l_npe
->module
= module
;
565 if (strcmp(name
, PRF_ETEXT
) == 0)
569 GELF_ST_BIND(gsym
.st_info
) == STB_LOCAL
) {
571 * If the "locals only" flag is on, then
572 * we add the local symbols to the
575 addlist(Elist
, name
);
576 addlist(elist
, name
);
578 DPRINTF("Index %lld:", l_nname
);
579 DPRINTF("\tValue: 0x%llx\t", l_npe
->value
);
580 DPRINTF("Name: %s \n", l_npe
->name
);
585 if (strcmp(name
, PRF_END
) == 0)
586 module
->data_end
= gsym
.st_value
;
590 fatal_error("no valid functions found");
593 * Finally, we need to construct some dummy entries.
596 l_npe
->name
= PRF_EXTSYM
;
597 l_npe
->value
= etext
->value
+ 1;
598 l_npe
->syminfo
= GELF_ST_INFO(STB_GLOBAL
, STT_FUNC
);
599 l_npe
->module
= module
;
604 l_npe
->name
= PRF_MEMTERM
;
605 l_npe
->value
= (pctype
)-1;
606 l_npe
->syminfo
= GELF_ST_INFO(STB_GLOBAL
, STT_FUNC
);
607 l_npe
->module
= module
;
612 * We're almost done; all we need to do is sort the symbols
613 * and then remove the duplicates.
615 qsort(l_nl
, (size_t)l_nname
, sizeof (nltype
), compare
);
616 remove_dup_syms(l_nl
, &l_nname
);
620 module
->nname
= l_nname
;
622 total_names
+= l_nname
;