diff options
-rw-r--r-- | contrib/gcc/config/i386/freebsd.h | 11 | ||||
-rw-r--r-- | contrib/gcc/config/i386/freebsd.h.fixed | 11 | ||||
-rw-r--r-- | lib/csu/amd64/Makefile | 6 | ||||
-rw-r--r-- | lib/csu/amd64/crt1.c | 21 | ||||
-rw-r--r-- | lib/csu/i386-elf/Makefile | 6 | ||||
-rw-r--r-- | lib/csu/i386-elf/crt1.c | 21 | ||||
-rw-r--r-- | sys/amd64/include/profile.h | 6 | ||||
-rw-r--r-- | sys/i386/include/profile.h | 6 | ||||
-rw-r--r-- | usr.bin/gprof/Makefile | 2 | ||||
-rw-r--r-- | usr.bin/gprof/aout.c | 201 | ||||
-rw-r--r-- | usr.bin/gprof/elf.c | 106 | ||||
-rw-r--r-- | usr.bin/gprof/gprof.1 | 11 | ||||
-rw-r--r-- | usr.bin/gprof/gprof.c | 217 | ||||
-rw-r--r-- | usr.bin/gprof/gprof.h | 16 | ||||
-rw-r--r-- | usr.bin/gprof4/Makefile | 2 |
15 files changed, 420 insertions, 223 deletions
diff --git a/contrib/gcc/config/i386/freebsd.h b/contrib/gcc/config/i386/freebsd.h index 7563948..d55c8f8 100644 --- a/contrib/gcc/config/i386/freebsd.h +++ b/contrib/gcc/config/i386/freebsd.h @@ -405,9 +405,10 @@ do { \ #define FUNCTION_PROFILER(FILE, LABELNO) \ { \ if (flag_pic) \ - fprintf (FILE, "\tcall *mcount@GOT(%%ebx)\n"); \ + fprintf (FILE, "\tcall *%s@GOT(%%ebx)\n", \ + TARGET_AOUT ? "mcount" : ".mcount"); \ else \ - fprintf (FILE, "\tcall mcount\n"); \ + fprintf (FILE, "\tcall %s\n", TARGET_AOUT ? "mcount" : ".mcount"); \ } #define FUNCTION_PROFILER_EPILOGUE(FILE) \ @@ -415,9 +416,11 @@ do { \ if (TARGET_PROFILER_EPILOGUE) \ { \ if (flag_pic) \ - fprintf (FILE, "\tcall *mexitcount@GOT(%%ebx)\n"); \ + fprintf (FILE, "\tcall *%s@GOT(%%ebx)\n", \ + TARGET_AOUT ? "mexitcount" : ".mexitcount"); \ else \ - fprintf (FILE, "\tcall mexitcount\n"); \ + fprintf (FILE, "\tcall %s\n", \ + TARGET_AOUT ? "mexitcount" : ".mexitcount"); \ } \ } diff --git a/contrib/gcc/config/i386/freebsd.h.fixed b/contrib/gcc/config/i386/freebsd.h.fixed index 7563948..d55c8f8 100644 --- a/contrib/gcc/config/i386/freebsd.h.fixed +++ b/contrib/gcc/config/i386/freebsd.h.fixed @@ -405,9 +405,10 @@ do { \ #define FUNCTION_PROFILER(FILE, LABELNO) \ { \ if (flag_pic) \ - fprintf (FILE, "\tcall *mcount@GOT(%%ebx)\n"); \ + fprintf (FILE, "\tcall *%s@GOT(%%ebx)\n", \ + TARGET_AOUT ? "mcount" : ".mcount"); \ else \ - fprintf (FILE, "\tcall mcount\n"); \ + fprintf (FILE, "\tcall %s\n", TARGET_AOUT ? "mcount" : ".mcount"); \ } #define FUNCTION_PROFILER_EPILOGUE(FILE) \ @@ -415,9 +416,11 @@ do { \ if (TARGET_PROFILER_EPILOGUE) \ { \ if (flag_pic) \ - fprintf (FILE, "\tcall *mexitcount@GOT(%%ebx)\n"); \ + fprintf (FILE, "\tcall *%s@GOT(%%ebx)\n", \ + TARGET_AOUT ? "mexitcount" : ".mexitcount"); \ else \ - fprintf (FILE, "\tcall mexitcount\n"); \ + fprintf (FILE, "\tcall %s\n", \ + TARGET_AOUT ? "mexitcount" : ".mexitcount"); \ } \ } diff --git a/lib/csu/amd64/Makefile b/lib/csu/amd64/Makefile index a4c72b3..6432efe 100644 --- a/lib/csu/amd64/Makefile +++ b/lib/csu/amd64/Makefile @@ -1,9 +1,10 @@ # -# $Id: Makefile,v 1.6 1996/04/12 02:24:34 jdp Exp $ +# $Id: Makefile,v 1.1.1.1 1998/03/07 20:27:10 jdp Exp $ # SRCS= crt1.c crtbegin.c crtend.c crti.S crtn.S OBJS= ${SRCS:N*.h:R:S/$/.o/g} +OBJS+= gcrt1.o SOBJS= crtbegin.so crtend.so CFLAGS+= -elf CFLAGS+= -Wall -Wno-unused @@ -15,6 +16,9 @@ INTERNALLIB= true all: ${OBJS} ${SOBJS} +gcrt1.o: crt1.c + ${CC} ${CFLAGS} -DGCRT -c -o gcrt1.o ${.CURDIR}/crt1.c + realinstall: .for file in ${OBJS} ${SOBJS} ${INSTALL} ${COPY} -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \ diff --git a/lib/csu/amd64/crt1.c b/lib/csu/amd64/crt1.c index d89d501..a303997 100644 --- a/lib/csu/amd64/crt1.c +++ b/lib/csu/amd64/crt1.c @@ -22,7 +22,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: crt1.c,v 1.4 1996/04/12 02:24:35 jdp Exp $ + * $Id: crt1.c,v 1.1.1.1 1998/03/07 20:27:10 jdp Exp $ */ #ifndef __GNUC__ @@ -37,6 +37,13 @@ extern void _fini(void); extern void _init(void); extern int main(int, char **, char **); +#ifdef GCRT +extern void _mcleanup(void); +extern void monstartup(void *, void *); +extern int eprol; +extern int etext; +#endif + extern int _DYNAMIC; #pragma weak _DYNAMIC @@ -71,7 +78,19 @@ _start(char *arguments, ...) if(&_DYNAMIC != 0) atexit(rtld_cleanup); +#ifdef GCRT + atexit(_mcleanup); +#endif atexit(_fini); +#ifdef GCRT + monstartup(&eprol, &etext); +#endif _init(); exit( main(argc, argv, env) ); } + +#ifdef GCRT +__asm__(".text"); +__asm__("eprol:"); +__asm__(".previous"); +#endif diff --git a/lib/csu/i386-elf/Makefile b/lib/csu/i386-elf/Makefile index a4c72b3..6432efe 100644 --- a/lib/csu/i386-elf/Makefile +++ b/lib/csu/i386-elf/Makefile @@ -1,9 +1,10 @@ # -# $Id: Makefile,v 1.6 1996/04/12 02:24:34 jdp Exp $ +# $Id: Makefile,v 1.1.1.1 1998/03/07 20:27:10 jdp Exp $ # SRCS= crt1.c crtbegin.c crtend.c crti.S crtn.S OBJS= ${SRCS:N*.h:R:S/$/.o/g} +OBJS+= gcrt1.o SOBJS= crtbegin.so crtend.so CFLAGS+= -elf CFLAGS+= -Wall -Wno-unused @@ -15,6 +16,9 @@ INTERNALLIB= true all: ${OBJS} ${SOBJS} +gcrt1.o: crt1.c + ${CC} ${CFLAGS} -DGCRT -c -o gcrt1.o ${.CURDIR}/crt1.c + realinstall: .for file in ${OBJS} ${SOBJS} ${INSTALL} ${COPY} -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \ diff --git a/lib/csu/i386-elf/crt1.c b/lib/csu/i386-elf/crt1.c index d89d501..a303997 100644 --- a/lib/csu/i386-elf/crt1.c +++ b/lib/csu/i386-elf/crt1.c @@ -22,7 +22,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: crt1.c,v 1.4 1996/04/12 02:24:35 jdp Exp $ + * $Id: crt1.c,v 1.1.1.1 1998/03/07 20:27:10 jdp Exp $ */ #ifndef __GNUC__ @@ -37,6 +37,13 @@ extern void _fini(void); extern void _init(void); extern int main(int, char **, char **); +#ifdef GCRT +extern void _mcleanup(void); +extern void monstartup(void *, void *); +extern int eprol; +extern int etext; +#endif + extern int _DYNAMIC; #pragma weak _DYNAMIC @@ -71,7 +78,19 @@ _start(char *arguments, ...) if(&_DYNAMIC != 0) atexit(rtld_cleanup); +#ifdef GCRT + atexit(_mcleanup); +#endif atexit(_fini); +#ifdef GCRT + monstartup(&eprol, &etext); +#endif _init(); exit( main(argc, argv, env) ); } + +#ifdef GCRT +__asm__(".text"); +__asm__("eprol:"); +__asm__(".previous"); +#endif diff --git a/sys/amd64/include/profile.h b/sys/amd64/include/profile.h index 02c43ca..e034e61 100644 --- a/sys/amd64/include/profile.h +++ b/sys/amd64/include/profile.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)profile.h 8.1 (Berkeley) 6/11/93 - * $Id: profile.h,v 1.16 1998/07/10 09:26:41 bde Exp $ + * $Id: profile.h,v 1.17 1998/07/14 05:09:43 bde Exp $ */ #ifndef _MACHINE_PROFILE_H_ @@ -135,8 +135,12 @@ void stopguprof __P((struct gmonparam *p)); __BEGIN_DECLS #ifdef __GNUC__ +#ifdef __ELF__ +void mcount __P((void)) __asm(".mcount"); +#else void mcount __P((void)) __asm("mcount"); #endif +#endif static void _mcount __P((uintfptr_t frompc, uintfptr_t selfpc)); __END_DECLS diff --git a/sys/i386/include/profile.h b/sys/i386/include/profile.h index 02c43ca..e034e61 100644 --- a/sys/i386/include/profile.h +++ b/sys/i386/include/profile.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)profile.h 8.1 (Berkeley) 6/11/93 - * $Id: profile.h,v 1.16 1998/07/10 09:26:41 bde Exp $ + * $Id: profile.h,v 1.17 1998/07/14 05:09:43 bde Exp $ */ #ifndef _MACHINE_PROFILE_H_ @@ -135,8 +135,12 @@ void stopguprof __P((struct gmonparam *p)); __BEGIN_DECLS #ifdef __GNUC__ +#ifdef __ELF__ +void mcount __P((void)) __asm(".mcount"); +#else void mcount __P((void)) __asm("mcount"); #endif +#endif static void _mcount __P((uintfptr_t frompc, uintfptr_t selfpc)); __END_DECLS diff --git a/usr.bin/gprof/Makefile b/usr.bin/gprof/Makefile index 9aba213..29291cc 100644 --- a/usr.bin/gprof/Makefile +++ b/usr.bin/gprof/Makefile @@ -1,7 +1,7 @@ # @(#)Makefile 8.1 (Berkeley) 6/29/93 PROG= gprof -SRCS= gprof.c arcs.c dfn.c lookup.c ${MACHINE_ARCH}.c hertz.c \ +SRCS= gprof.c aout.c arcs.c dfn.c elf.c lookup.c ${MACHINE_ARCH}.c hertz.c \ printgprof.c printlist.c beforeinstall: diff --git a/usr.bin/gprof/aout.c b/usr.bin/gprof/aout.c new file mode 100644 index 0000000..940becb --- /dev/null +++ b/usr.bin/gprof/aout.c @@ -0,0 +1,201 @@ +#include <a.out.h> + +#include "gprof.h" + +static void getstrtab(FILE *, const char *); +static void getsymtab(FILE *, const char *); +static void gettextspace(FILE *); +static bool funcsymbol(struct nlist *); + +static char *strtab; /* string table in core */ +static long ssiz; /* size of the string table */ +static struct exec xbuf; /* exec header of a.out */ + +/* Things which get -E excluded by default. */ +static char *excludes[] = { "mcount", "__mcleanup", NULL }; + + /* + * Set up string and symbol tables from a.out. + * and optionally the text space. + * On return symbol table is sorted by value. + * + * Returns 0 on success, -1 on failure. + */ +int +aout_getnfile(const char *filename, char ***defaultEs) +{ + FILE *nfile; + int valcmp(); + + nfile = fopen( filename ,"r"); + if (nfile == NULL) { + perror( filename ); + done(); + } + fread(&xbuf, 1, sizeof(xbuf), nfile); + if (N_BADMAG(xbuf)) { + fclose(nfile); + return -1; + } + getstrtab(nfile, filename); + getsymtab(nfile, filename); + gettextspace( nfile ); + fclose(nfile); +# ifdef DEBUG + if ( debug & AOUTDEBUG ) { + register int j; + + for (j = 0; j < nname; j++){ + printf("[getnfile] 0X%08x\t%s\n", nl[j].value, nl[j].name); + } + } +# endif DEBUG + *defaultEs = excludes; + return 0; +} + +static void +getstrtab(FILE *nfile, const char *filename) +{ + + fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0); + if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0) { + warnx("%s: no string table (old format?)" , filename ); + done(); + } + strtab = calloc(ssiz, 1); + if (strtab == NULL) { + warnx("%s: no room for %d bytes of string table", filename , ssiz); + done(); + } + if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) { + warnx("%s: error reading string table", filename ); + done(); + } +} + + /* + * Read in symbol table + */ +static void +getsymtab(FILE *nfile, const char *filename) +{ + register long i; + int askfor; + struct nlist nbuf; + + /* pass1 - count symbols */ + fseek(nfile, (long)N_SYMOFF(xbuf), 0); + nname = 0; + for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { + fread(&nbuf, sizeof(nbuf), 1, nfile); + if ( ! funcsymbol( &nbuf ) ) { + continue; + } + nname++; + } + if (nname == 0) { + warnx("%s: no symbols", filename ); + done(); + } + askfor = nname + 1; + nl = (nltype *) calloc( askfor , sizeof(nltype) ); + if (nl == 0) { + warnx("no room for %d bytes of symbol table", askfor * sizeof(nltype) ); + done(); + } + + /* pass2 - read symbols */ + fseek(nfile, (long)N_SYMOFF(xbuf), 0); + npe = nl; + nname = 0; + for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { + fread(&nbuf, sizeof(nbuf), 1, nfile); + if ( ! funcsymbol( &nbuf ) ) { +# ifdef DEBUG + if ( debug & AOUTDEBUG ) { + printf( "[getsymtab] rejecting: 0x%x %s\n" , + nbuf.n_type , strtab + nbuf.n_un.n_strx ); + } +# endif DEBUG + continue; + } + npe->value = nbuf.n_value; + npe->name = strtab+nbuf.n_un.n_strx; +# ifdef DEBUG + if ( debug & AOUTDEBUG ) { + printf( "[getsymtab] %d %s 0x%08x\n" , + nname , npe -> name , npe -> value ); + } +# endif DEBUG + npe++; + nname++; + } + npe->value = -1; +} + + /* + * read in the text space of an a.out file + */ +static void +gettextspace(FILE *nfile) +{ + + if ( cflag == 0 ) { + return; + } + textspace = (u_char *) malloc( xbuf.a_text ); + if ( textspace == 0 ) { + warnx("ran out room for %d bytes of text space: can't do -c" , + xbuf.a_text ); + return; + } + (void) fseek( nfile , N_TXTOFF( xbuf ) , 0 ); + if ( fread( textspace , 1 , xbuf.a_text , nfile ) != xbuf.a_text ) { + warnx("couldn't read text space: can't do -c"); + free( textspace ); + textspace = 0; + return; + } +} + +static bool +funcsymbol(struct nlist *nlistp) +{ + char *name, c; + + /* + * must be a text symbol, + * and static text symbols don't qualify if aflag set. + */ + if ( ! ( ( nlistp -> n_type == ( N_TEXT | N_EXT ) ) + || ( ( nlistp -> n_type == N_TEXT ) && ( aflag == 0 ) ) ) ) { + return FALSE; + } + /* + * name must start with an underscore if uflag is set. + * can't have any `funny' characters in name, + * where `funny' means `.' (.o file names) + * need to make an exception for sparc .mul & co. + * perhaps we should just drop this code entirely... + */ + name = strtab + nlistp -> n_un.n_strx; + if ( uflag && *name != '_' ) + return FALSE; +#ifdef sparc + if ( *name == '.' ) { + char *p = name + 1; + if ( *p == 'u' ) + p++; + if ( strcmp ( p, "mul" ) == 0 || strcmp ( p, "div" ) == 0 || + strcmp ( p, "rem" ) == 0 ) + return TRUE; + } +#endif + while ( c = *name++ ) { + if ( c == '.' ) { + return FALSE; + } + } + return TRUE; +} diff --git a/usr.bin/gprof/elf.c b/usr.bin/gprof/elf.c new file mode 100644 index 0000000..3a59f53 --- /dev/null +++ b/usr.bin/gprof/elf.c @@ -0,0 +1,106 @@ +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/stat.h> + +#include <elf.h> +#include <err.h> +#include <fcntl.h> +#include <string.h> +#include <unistd.h> + +#include "gprof.h" + +static bool wantsym(const Elf_Sym *, const char *); + +/* Things which get -E excluded by default. */ +static char *excludes[] = { ".mcount", "_mcleanup", NULL }; + +int +elf_getnfile(const char *filename, char ***defaultEs) +{ + int fd; + Elf_Ehdr h; + struct stat s; + void *mapbase; + const char *base; + const Elf_Shdr *shdrs; + const Elf_Shdr *sh_symtab; + const Elf_Shdr *sh_strtab; + const char *strtab; + const Elf_Sym *symtab; + int symtabct; + int i; + + if ((fd = open(filename, O_RDONLY)) == -1) + err(1, "%s", filename); + if (read(fd, &h, sizeof h) != sizeof h || !IS_ELF(h)) { + close(fd); + return -1; + } + if (fstat(fd, &s) == -1) + err(1, "Cannot fstat %s", filename); + if ((mapbase = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0)) == + MAP_FAILED) + err(1, "Cannot mmap %s", filename); + close(fd); + + base = (const char *)mapbase; + shdrs = (const Elf_Shdr *)(base + h.e_shoff); + + /* Find the symbol table and associated string table section. */ + for (i = 1; i < h.e_shnum; i++) + if (shdrs[i].sh_type == SHT_SYMTAB) + break; + if (i == h.e_shnum) + errx(1, "%s has no symbol table", filename); + sh_symtab = &shdrs[i]; + sh_strtab = &shdrs[sh_symtab->sh_link]; + + symtab = (const Elf_Sym *)(base + sh_symtab->sh_offset); + symtabct = sh_symtab->sh_size / sh_symtab->sh_entsize; + strtab = (const char *)(base + sh_strtab->sh_offset); + + /* Count the symbols that we're interested in. */ + nname = 0; + for (i = 1; i < symtabct; i++) + if (wantsym(&symtab[i], strtab)) + nname++; + + /* Allocate memory for them, plus a terminating entry. */ + if ((nl = (nltype *)calloc(nname + 1, sizeof(nltype))) == NULL) + errx(1, "Insufficient memory for symbol table"); + + /* Read them in. */ + npe = nl; + for (i = 1; i < symtabct; i++) { + const Elf_Sym *sym = &symtab[i]; + + if (wantsym(sym, strtab)) { + npe->value = sym->st_value; + npe->name = strtab + sym->st_name; + npe++; + } + } + npe->value = -1; + + *defaultEs = excludes; + return 0; +} + +static bool +wantsym(const Elf_Sym *sym, const char *strtab) +{ + int type; + int bind; + + type = ELF_ST_TYPE(sym->st_info); + bind = ELF_ST_BIND(sym->st_info); + + if (type != STT_FUNC || + bind == STB_WEAK || + (aflag && bind == STB_LOCAL) || + (uflag && strchr(strtab + sym->st_name, '.') != NULL)) + return 0; + + return 1; +} diff --git a/usr.bin/gprof/gprof.1 b/usr.bin/gprof/gprof.1 index 76b5543..dc6f369 100644 --- a/usr.bin/gprof/gprof.1 +++ b/usr.bin/gprof/gprof.1 @@ -113,6 +113,7 @@ The static call graph of the program is discovered by a heuristic that examines the text space of the object file. Static-only parents or children are shown with call counts of 0. +This option is not supported on some architectures. .It Fl C Ar count Find a minimal set of arcs that can be broken to eliminate all cycles with .Ar count @@ -210,8 +211,14 @@ to accumulate profile data across several runs of an .Pa a.out file. .It Fl u -Suppresses the printing of functions whose name does not begin with -an underscore. +Suppresses the printing of functions whose names are not visible to +C programs. For the ELF object format, this means names that +contain the +.Ql \&. +character. For the a.out object format, it means names that do not +begin with a +.Ql _ +character. All relevant information about such functions belongs to the (non-suppressed) function with the next lowest address. This is useful for eliminating "functions" that are just labels diff --git a/usr.bin/gprof/gprof.c b/usr.bin/gprof/gprof.c index 185e2c6..0d4d63f 100644 --- a/usr.bin/gprof/gprof.c +++ b/usr.bin/gprof/gprof.c @@ -42,19 +42,16 @@ static const char copyright[] = static char sccsid[] = "@(#)gprof.c 8.1 (Berkeley) 6/6/93"; #endif static const char rcsid[] = - "$Id: gprof.c,v 1.6 1997/07/15 08:04:40 charnier Exp $"; + "$Id: gprof.c,v 1.7 1998/08/08 17:48:26 jdp Exp $"; #endif /* not lint */ #include <err.h> #include "gprof.h" - /* - * things which get -E excluded by default. - */ -char *defaultEs[] = { "mcount" , "__mcleanup" , 0 }; +static int valcmp(const void *, const void *); + static struct gmonhdr gmonhdr; -static bool uflag; static int lflag; static int Lflag; @@ -64,6 +61,7 @@ main(argc, argv) { char **sp; nltype **timesortnlp; + char **defaultEs; --argc; argv++; @@ -160,19 +158,25 @@ main(argc, argv) gmonname = GMONNAME; } /* + * get information from the executable file. + */ + if (elf_getnfile(a_outname, &defaultEs) == -1 && + aout_getnfile(a_outname, &defaultEs) == -1) + errx(1, "%s: bad format", a_outname); + /* + * sort symbol table. + */ + qsort(nl, nname, sizeof(nltype), valcmp); + /* * turn off default functions */ - for ( sp = &defaultEs[0] ; *sp ; sp++ ) { + for ( sp = defaultEs ; *sp ; sp++ ) { Eflag = TRUE; addlist( Elist , *sp ); eflag = TRUE; addlist( elist , *sp ); } /* - * get information about a.out file. - */ - getnfile(); - /* * get information about mon.out file(s). */ do { @@ -223,146 +227,6 @@ main(argc, argv) } /* - * Set up string and symbol tables from a.out. - * and optionally the text space. - * On return symbol table is sorted by value. - */ -getnfile() -{ - FILE *nfile; - int valcmp(); - - nfile = fopen( a_outname ,"r"); - if (nfile == NULL) { - perror( a_outname ); - done(); - } - fread(&xbuf, 1, sizeof(xbuf), nfile); - if (N_BADMAG(xbuf)) { - warnx("%s: bad format", a_outname ); - done(); - } - getstrtab(nfile); - getsymtab(nfile); - gettextspace( nfile ); - qsort(nl, nname, sizeof(nltype), valcmp); - fclose(nfile); -# ifdef DEBUG - if ( debug & AOUTDEBUG ) { - register int j; - - for (j = 0; j < nname; j++){ - printf("[getnfile] 0X%08x\t%s\n", nl[j].value, nl[j].name); - } - } -# endif DEBUG -} - -getstrtab(nfile) - FILE *nfile; -{ - - fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0); - if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0) { - warnx("%s: no string table (old format?)" , a_outname ); - done(); - } - strtab = calloc(ssiz, 1); - if (strtab == NULL) { - warnx("%s: no room for %d bytes of string table", a_outname , ssiz); - done(); - } - if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) { - warnx("%s: error reading string table", a_outname ); - done(); - } -} - - /* - * Read in symbol table - */ -getsymtab(nfile) - FILE *nfile; -{ - register long i; - int askfor; - struct nlist nbuf; - - /* pass1 - count symbols */ - fseek(nfile, (long)N_SYMOFF(xbuf), 0); - nname = 0; - for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { - fread(&nbuf, sizeof(nbuf), 1, nfile); - if ( ! funcsymbol( &nbuf ) ) { - continue; - } - nname++; - } - if (nname == 0) { - warnx("%s: no symbols", a_outname ); - done(); - } - askfor = nname + 1; - nl = (nltype *) calloc( askfor , sizeof(nltype) ); - if (nl == 0) { - warnx("no room for %d bytes of symbol table", askfor * sizeof(nltype) ); - done(); - } - - /* pass2 - read symbols */ - fseek(nfile, (long)N_SYMOFF(xbuf), 0); - npe = nl; - nname = 0; - for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { - fread(&nbuf, sizeof(nbuf), 1, nfile); - if ( ! funcsymbol( &nbuf ) ) { -# ifdef DEBUG - if ( debug & AOUTDEBUG ) { - printf( "[getsymtab] rejecting: 0x%x %s\n" , - nbuf.n_type , strtab + nbuf.n_un.n_strx ); - } -# endif DEBUG - continue; - } - npe->value = nbuf.n_value; - npe->name = strtab+nbuf.n_un.n_strx; -# ifdef DEBUG - if ( debug & AOUTDEBUG ) { - printf( "[getsymtab] %d %s 0x%08x\n" , - nname , npe -> name , npe -> value ); - } -# endif DEBUG - npe++; - nname++; - } - npe->value = -1; -} - - /* - * read in the text space of an a.out file - */ -gettextspace( nfile ) - FILE *nfile; -{ - - if ( cflag == 0 ) { - return; - } - textspace = (u_char *) malloc( xbuf.a_text ); - if ( textspace == 0 ) { - warnx("ran out room for %d bytes of text space: can't do -c" , - xbuf.a_text ); - return; - } - (void) fseek( nfile , N_TXTOFF( xbuf ) , 0 ); - if ( fread( textspace , 1 , xbuf.a_text , nfile ) != xbuf.a_text ) { - warnx("couldn't read text space: can't do -c"); - free( textspace ); - textspace = 0; - return; - } -} - /* * information from a gmon.out file is in two parts: * an array of sampling hits within pc ranges, * and the arcs. @@ -531,9 +395,14 @@ dumpsum( sumfile ) fclose( sfile ); } -valcmp(p1, p2) - nltype *p1, *p2; +static int +valcmp(v1, v2) + const void *v1; + const void *v2; { + const nltype *p1 = (const nltype *)v1; + const nltype *p2 = (const nltype *)v2; + if ( p1 -> value < p2 -> value ) { return LESSTHAN; } @@ -711,48 +580,6 @@ alignentries() } } -bool -funcsymbol( nlistp ) - struct nlist *nlistp; -{ - char *name, c; - - /* - * must be a text symbol, - * and static text symbols don't qualify if aflag set. - */ - if ( ! ( ( nlistp -> n_type == ( N_TEXT | N_EXT ) ) - || ( ( nlistp -> n_type == N_TEXT ) && ( aflag == 0 ) ) ) ) { - return FALSE; - } - /* - * name must start with an underscore if uflag is set. - * can't have any `funny' characters in name, - * where `funny' means `.' (.o file names) - * need to make an exception for sparc .mul & co. - * perhaps we should just drop this code entirely... - */ - name = strtab + nlistp -> n_un.n_strx; - if ( uflag && *name != '_' ) - return FALSE; -#ifdef sparc - if ( *name == '.' ) { - char *p = name + 1; - if ( *p == 'u' ) - p++; - if ( strcmp ( p, "mul" ) == 0 || strcmp ( p, "div" ) == 0 || - strcmp ( p, "rem" ) == 0 ) - return TRUE; - } -#endif - while ( c = *name++ ) { - if ( c == '.' ) { - return FALSE; - } - } - return TRUE; -} - done() { diff --git a/usr.bin/gprof/gprof.h b/usr.bin/gprof/gprof.h index 750fd2e..ce164d5 100644 --- a/usr.bin/gprof/gprof.h +++ b/usr.bin/gprof/gprof.h @@ -37,7 +37,6 @@ #include <sys/stat.h> #include <sys/gmon.h> -#include <a.out.h> #include <stdio.h> #include <stdlib.h> @@ -121,7 +120,7 @@ typedef struct arcstruct arctype; * its address, the number of calls and compute its share of cpu time. */ struct nl { - char *name; /* the name */ + const char *name; /* the name */ unsigned long value; /* the pc entry point */ unsigned long svalue; /* entry point aligned to histograms */ double time; /* ticks in this routine */ @@ -217,9 +216,6 @@ double totime; /* total time for all routines */ double printtime; /* total of time being printed */ double scale; /* scale factor converting samples to pc values: each sample covers scale bytes */ -char *strtab; /* string table in core */ -long ssiz; /* size of the string table */ -struct exec xbuf; /* exec header of a.out */ unsigned char *textspace; /* text space of a.out in core */ int cyclethreshold; /* with -C, minimum cycle size to ignore */ @@ -237,6 +233,7 @@ bool fflag; /* specific functions requested */ bool Fflag; /* functions requested with time */ bool kflag; /* arcs to be deleted */ bool sflag; /* sum multiple gmon.out files */ +bool uflag; /* suppress symbols hidden from C */ bool zflag; /* zero time/called functions, too */ /* @@ -259,6 +256,7 @@ struct stringlist *ktolist; /* addarc(); */ +int aout_getnfile(const char *, char ***); int arccmp(); arctype *arclookup(); /* @@ -280,17 +278,15 @@ bool dfn_numbered(); nltype **doarcs(); /* done(); +*/ +int elf_getnfile(const char *, char ***); +/* findcalls(); flatprofheader(); flatprofline(); */ -bool funcsymbol(); /* - getnfile(); getpfile(); - getstrtab(); - getsymtab(); - gettextspace(); gprofheader(); gprofline(); main(); diff --git a/usr.bin/gprof4/Makefile b/usr.bin/gprof4/Makefile index 5764656..aafabda 100644 --- a/usr.bin/gprof4/Makefile +++ b/usr.bin/gprof4/Makefile @@ -6,7 +6,7 @@ PROG= gprof4 NOMAN= noman -SRCS= gprof.c arcs.c dfn.c lookup.c ${MACHINE_ARCH}.c hertz.c \ +SRCS= gprof.c aout.c arcs.c dfn.c elf.c lookup.c ${MACHINE_ARCH}.c hertz.c \ printgprof.c printlist.c CFLAGS+=-DGPROF4 .PATH: ${.CURDIR}/../../usr.bin/gprof |