summaryrefslogtreecommitdiff
path: root/usr.bin/gprof/aout.c
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>2002-05-08 16:46:36 +0000
committerArtur Grabowski <art@cvs.openbsd.org>2002-05-08 16:46:36 +0000
commit584e4fed1fb6695c8603287739b1b68ef791f48c (patch)
tree4fe9f999dfd7e5221b0cb16b978e75faf7a98dee /usr.bin/gprof/aout.c
parent37392dec62ee72737d0bdef8be7fa39faa75df0b (diff)
Split out symbol handling into a separate file.
Implement symbol handling for ELF (based on FreeBSD). Implement dummy support for alpha, hppa, powerpc and sparc64. Tested during the last 2 months on various archs (never comitted because other stuff got in the way). Some fixups to i386 support from mickey@ This lets us switch all elf archs to this gprof.
Diffstat (limited to 'usr.bin/gprof/aout.c')
-rw-r--r--usr.bin/gprof/aout.c224
1 files changed, 224 insertions, 0 deletions
diff --git a/usr.bin/gprof/aout.c b/usr.bin/gprof/aout.c
new file mode 100644
index 00000000000..a84e648d0c4
--- /dev/null
+++ b/usr.bin/gprof/aout.c
@@ -0,0 +1,224 @@
+/*-
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#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
+getnfile(const char *filename, char ***defaultEs)
+{
+ FILE *nfile;
+
+ nfile = fopen( filename ,"r");
+ if (nfile == NULL)
+ err(1, "fopen: %s", filename);
+
+ fread(&xbuf, 1, sizeof(xbuf), nfile);
+ if (N_BADMAG(xbuf)) {
+ /* Bail out and let other binary formats try. */
+ fclose(nfile);
+ return (-1);
+ }
+ getstrtab(nfile, filename);
+ getsymtab(nfile, filename);
+ gettextspace(nfile);
+ fclose(nfile);
+#ifdef DEBUG
+ if (debug & AOUTDEBUG) {
+ int j;
+
+ for (j = 0; j < nname; j++) {
+ printf("[getnfile] 0X%08lx\t%s\n", nl[j].value,
+ nl[j].name);
+ }
+ }
+#endif
+ *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)
+ errx(1, "%s: no string table (old format?)" , filename );
+ strtab = calloc(ssiz, 1);
+ if (strtab == NULL)
+ errx(1, "%s: no room for %d bytes of string table", filename,
+ ssiz);
+ if (fread(strtab + sizeof(ssiz), ssiz - sizeof(ssiz), 1, nfile) != 1)
+ errx(1, "%s: error reading string table", filename );
+}
+
+/*
+ * Read in symbol table
+ */
+static void
+getsymtab(FILE *nfile, const char *filename)
+{
+ struct nlist nbuf;
+ int askfor;
+ long i;
+
+ /* 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))
+ nname++;
+ }
+ if (nname == 0)
+ errx(1, "%s: no symbols", filename);
+
+ askfor = nname + 1;
+ nl = calloc(askfor , sizeof(nltype));
+ if (nl == 0)
+ errx(1, "No room for %d bytes of symbol table",
+ askfor * sizeof(nltype));
+
+ /* 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
+ continue;
+ }
+ npe->value = nbuf.n_value;
+ npe->name = strtab + nbuf.n_un.n_strx;
+#ifdef DEBUG
+ if (debug & AOUTDEBUG) {
+ printf("[getsymtab] %d %s 0x%08lx\n",
+ nname, npe->name, npe->value);
+ }
+#endif
+ 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 = 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;
+#ifdef sparc
+ if (nlistp -> n_value & 3)
+ return (FALSE);
+ 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);
+}