2 * $FreeBSD: src/usr.bin/gprof/elf.c,v 1.2.2.1 2001/07/11 23:59:11 obrien Exp $
3 * $DragonFly: src/usr.bin/gprof/elf.c,v 1.2 2003/06/17 04:29:27 dillon Exp $
9 #include <machine/elf.h>
18 static bool wantsym(const Elf_Sym
*, const char *);
20 /* Things which get -E excluded by default. */
21 static char *excludes
[] = { ".mcount", "_mcleanup", NULL
};
24 elf_getnfile(const char *filename
, char ***defaultEs
)
31 const Elf_Shdr
*shdrs
;
32 const Elf_Shdr
*sh_symtab
;
33 const Elf_Shdr
*sh_strtab
;
35 const Elf_Sym
*symtab
;
39 if ((fd
= open(filename
, O_RDONLY
)) == -1)
40 err(1, "%s", filename
);
41 if (read(fd
, &h
, sizeof h
) != sizeof h
|| !IS_ELF(h
)) {
45 if (fstat(fd
, &s
) == -1)
46 err(1, "Cannot fstat %s", filename
);
47 if ((mapbase
= mmap(0, s
.st_size
, PROT_READ
, MAP_SHARED
, fd
, 0)) ==
49 err(1, "Cannot mmap %s", filename
);
52 base
= (const char *)mapbase
;
53 shdrs
= (const Elf_Shdr
*)(base
+ h
.e_shoff
);
55 /* Find the symbol table and associated string table section. */
56 for (i
= 1; i
< h
.e_shnum
; i
++)
57 if (shdrs
[i
].sh_type
== SHT_SYMTAB
)
60 errx(1, "%s has no symbol table", filename
);
61 sh_symtab
= &shdrs
[i
];
62 sh_strtab
= &shdrs
[sh_symtab
->sh_link
];
64 symtab
= (const Elf_Sym
*)(base
+ sh_symtab
->sh_offset
);
65 symtabct
= sh_symtab
->sh_size
/ sh_symtab
->sh_entsize
;
66 strtab
= (const char *)(base
+ sh_strtab
->sh_offset
);
68 /* Count the symbols that we're interested in. */
70 for (i
= 1; i
< symtabct
; i
++)
71 if (wantsym(&symtab
[i
], strtab
))
74 /* Allocate memory for them, plus a terminating entry. */
75 if ((nl
= (nltype
*)calloc(nname
+ 1, sizeof(nltype
))) == NULL
)
76 errx(1, "Insufficient memory for symbol table");
80 for (i
= 1; i
< symtabct
; i
++) {
81 const Elf_Sym
*sym
= &symtab
[i
];
83 if (wantsym(sym
, strtab
)) {
84 npe
->value
= sym
->st_value
;
85 npe
->name
= strtab
+ sym
->st_name
;
91 *defaultEs
= excludes
;
96 wantsym(const Elf_Sym
*sym
, const char *strtab
)
101 type
= ELF_ST_TYPE(sym
->st_info
);
102 bind
= ELF_ST_BIND(sym
->st_info
);
104 if (type
!= STT_FUNC
||
105 (aflag
&& bind
== STB_LOCAL
) ||
106 (uflag
&& strchr(strtab
+ sym
->st_name
, '.') != NULL
))