summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--contrib/gcc/config/i386/freebsd.h11
-rw-r--r--contrib/gcc/config/i386/freebsd.h.fixed11
-rw-r--r--lib/csu/amd64/Makefile6
-rw-r--r--lib/csu/amd64/crt1.c21
-rw-r--r--lib/csu/i386-elf/Makefile6
-rw-r--r--lib/csu/i386-elf/crt1.c21
-rw-r--r--sys/amd64/include/profile.h6
-rw-r--r--sys/i386/include/profile.h6
-rw-r--r--usr.bin/gprof/Makefile2
-rw-r--r--usr.bin/gprof/aout.c201
-rw-r--r--usr.bin/gprof/elf.c106
-rw-r--r--usr.bin/gprof/gprof.111
-rw-r--r--usr.bin/gprof/gprof.c217
-rw-r--r--usr.bin/gprof/gprof.h16
-rw-r--r--usr.bin/gprof4/Makefile2
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
OpenPOWER on IntegriCloud