191017Sbde/*- 291017Sbde * Copyright (c) 1983, 1993 391017Sbde * The Regents of the University of California. All rights reserved. 491017Sbde * 591017Sbde * Redistribution and use in source and binary forms, with or without 691017Sbde * modification, are permitted provided that the following conditions 791017Sbde * are met: 891017Sbde * 1. Redistributions of source code must retain the above copyright 991017Sbde * notice, this list of conditions and the following disclaimer. 1091017Sbde * 2. Redistributions in binary form must reproduce the above copyright 1191017Sbde * notice, this list of conditions and the following disclaimer in the 1291017Sbde * documentation and/or other materials provided with the distribution. 1391017Sbde * 4. Neither the name of the University nor the names of its contributors 1491017Sbde * may be used to endorse or promote products derived from this software 1591017Sbde * without specific prior written permission. 1691017Sbde * 1791017Sbde * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1891017Sbde * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1991017Sbde * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2091017Sbde * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2191017Sbde * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2291017Sbde * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2391017Sbde * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2491017Sbde * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2591017Sbde * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2691017Sbde * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2791017Sbde * SUCH DAMAGE. 2891017Sbde */ 2991017Sbde 3091017Sbde#if 0 3191017Sbde/* From: */ 3291017Sbde#ifndef lint 3391017Sbdestatic char sccsid[] = "@(#)gprof.c 8.1 (Berkeley) 6/6/93"; 3491017Sbde#endif /* not lint */ 3591017Sbde#endif 3691017Sbde 3791017Sbde#include <sys/cdefs.h> 3891017Sbde__FBSDID("$FreeBSD: releng/10.3/usr.bin/gprof/aout.c 246783 2013-02-14 08:16:03Z charnier $"); 3991017Sbde 40129652Sstefanf#include <netinet/in.h> 41129652Sstefanf 4238928Sjdp#include <a.out.h> 43105243Scharnier#include <err.h> 44201383Sed#include <string.h> 4538928Sjdp 4638928Sjdp#include "gprof.h" 4738928Sjdp 4838928Sjdpstatic void getstrtab(FILE *, const char *); 4938928Sjdpstatic void getsymtab(FILE *, const char *); 5038928Sjdpstatic void gettextspace(FILE *); 5138928Sjdpstatic bool funcsymbol(struct nlist *); 5238928Sjdp 5338928Sjdpstatic char *strtab; /* string table in core */ 5438928Sjdpstatic long ssiz; /* size of the string table */ 5538928Sjdpstatic struct exec xbuf; /* exec header of a.out */ 5638928Sjdp 5738928Sjdp/* Things which get -E excluded by default. */ 5838928Sjdpstatic char *excludes[] = { "mcount", "__mcleanup", NULL }; 5938928Sjdp 6038928Sjdp /* 6138928Sjdp * Set up string and symbol tables from a.out. 6238928Sjdp * and optionally the text space. 6338928Sjdp * On return symbol table is sorted by value. 6438928Sjdp * 6538928Sjdp * Returns 0 on success, -1 on failure. 6638928Sjdp */ 6738928Sjdpint 6838928Sjdpaout_getnfile(const char *filename, char ***defaultEs) 6938928Sjdp{ 7038928Sjdp FILE *nfile; 7138928Sjdp 7238928Sjdp nfile = fopen( filename ,"r"); 73105243Scharnier if (nfile == NULL) 74105243Scharnier err( 1 , "%s", filename ); 7538928Sjdp fread(&xbuf, 1, sizeof(xbuf), nfile); 7638928Sjdp if (N_BADMAG(xbuf)) { 7738928Sjdp fclose(nfile); 7838928Sjdp return -1; 7938928Sjdp } 8038928Sjdp getstrtab(nfile, filename); 8138928Sjdp getsymtab(nfile, filename); 8238928Sjdp gettextspace( nfile ); 8338928Sjdp fclose(nfile); 8438928Sjdp# ifdef DEBUG 8538928Sjdp if ( debug & AOUTDEBUG ) { 8638928Sjdp register int j; 8738928Sjdp 8838928Sjdp for (j = 0; j < nname; j++){ 8991018Sbde printf("[getnfile] 0X%08lx\t%s\n", nl[j].value, nl[j].name); 9038928Sjdp } 9138928Sjdp } 9297631Swollman# endif /* DEBUG */ 9338928Sjdp *defaultEs = excludes; 9438928Sjdp return 0; 9538928Sjdp} 9638928Sjdp 9738928Sjdpstatic void 9838928Sjdpgetstrtab(FILE *nfile, const char *filename) 9938928Sjdp{ 10038928Sjdp 10138928Sjdp fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0); 102105243Scharnier if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0) 103105243Scharnier errx( 1 , "%s: no string table (old format?)" , filename ); 10438928Sjdp strtab = calloc(ssiz, 1); 105105243Scharnier if (strtab == NULL) 106105243Scharnier errx( 1 , "%s: no room for %ld bytes of string table", filename , ssiz); 107105243Scharnier if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) 108105243Scharnier errx( 1 , "%s: error reading string table" , filename ); 10938928Sjdp} 11038928Sjdp 11138928Sjdp /* 11238928Sjdp * Read in symbol table 11338928Sjdp */ 11438928Sjdpstatic void 11538928Sjdpgetsymtab(FILE *nfile, const char *filename) 11638928Sjdp{ 11738928Sjdp register long i; 11838928Sjdp int askfor; 11938928Sjdp struct nlist nbuf; 12038928Sjdp 12138928Sjdp /* pass1 - count symbols */ 12238928Sjdp fseek(nfile, (long)N_SYMOFF(xbuf), 0); 12338928Sjdp nname = 0; 12438928Sjdp for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 12538928Sjdp fread(&nbuf, sizeof(nbuf), 1, nfile); 12638928Sjdp if ( ! funcsymbol( &nbuf ) ) { 12738928Sjdp continue; 12838928Sjdp } 12938928Sjdp nname++; 13038928Sjdp } 131105243Scharnier if (nname == 0) 132105243Scharnier errx( 1 , "%s: no symbols" , filename ); 13338928Sjdp askfor = nname + 1; 13438928Sjdp nl = (nltype *) calloc( askfor , sizeof(nltype) ); 135105243Scharnier if (nl == 0) 136228629Sdim errx( 1 , "no room for %zu bytes of symbol table" , 137105243Scharnier askfor * sizeof(nltype) ); 13838928Sjdp 13938928Sjdp /* pass2 - read symbols */ 14038928Sjdp fseek(nfile, (long)N_SYMOFF(xbuf), 0); 14138928Sjdp npe = nl; 14238928Sjdp nname = 0; 14338928Sjdp for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { 14438928Sjdp fread(&nbuf, sizeof(nbuf), 1, nfile); 14538928Sjdp if ( ! funcsymbol( &nbuf ) ) { 14638928Sjdp# ifdef DEBUG 14738928Sjdp if ( debug & AOUTDEBUG ) { 14838928Sjdp printf( "[getsymtab] rejecting: 0x%x %s\n" , 14938928Sjdp nbuf.n_type , strtab + nbuf.n_un.n_strx ); 15038928Sjdp } 15197631Swollman# endif /* DEBUG */ 15238928Sjdp continue; 15338928Sjdp } 15438928Sjdp npe->value = nbuf.n_value; 15538928Sjdp npe->name = strtab+nbuf.n_un.n_strx; 15638928Sjdp# ifdef DEBUG 15738928Sjdp if ( debug & AOUTDEBUG ) { 15891018Sbde printf( "[getsymtab] %d %s 0x%08lx\n" , 15938928Sjdp nname , npe -> name , npe -> value ); 16038928Sjdp } 16197631Swollman# endif /* DEBUG */ 16238928Sjdp npe++; 16338928Sjdp nname++; 16438928Sjdp } 16538928Sjdp npe->value = -1; 16638928Sjdp} 16738928Sjdp 16838928Sjdp /* 16938928Sjdp * read in the text space of an a.out file 17038928Sjdp */ 17138928Sjdpstatic void 17238928Sjdpgettextspace(FILE *nfile) 17338928Sjdp{ 17438928Sjdp 17538928Sjdp textspace = (u_char *) malloc( xbuf.a_text ); 17638928Sjdp if ( textspace == 0 ) { 177228628Sdim warnx("no room for %u bytes of text space: can't do -c" , 17838928Sjdp xbuf.a_text ); 17938928Sjdp return; 18038928Sjdp } 18138928Sjdp (void) fseek( nfile , N_TXTOFF( xbuf ) , 0 ); 18238928Sjdp if ( fread( textspace , 1 , xbuf.a_text , nfile ) != xbuf.a_text ) { 18338928Sjdp warnx("couldn't read text space: can't do -c"); 18438928Sjdp free( textspace ); 18538928Sjdp textspace = 0; 18638928Sjdp return; 18738928Sjdp } 18838928Sjdp} 18938928Sjdp 19038928Sjdpstatic bool 19138928Sjdpfuncsymbol(struct nlist *nlistp) 19238928Sjdp{ 19338928Sjdp char *name, c; 19438928Sjdp 19538928Sjdp /* 19638928Sjdp * must be a text symbol, 19738928Sjdp * and static text symbols don't qualify if aflag set. 19838928Sjdp */ 19938928Sjdp if ( ! ( ( nlistp -> n_type == ( N_TEXT | N_EXT ) ) 20038928Sjdp || ( ( nlistp -> n_type == N_TEXT ) && ( aflag == 0 ) ) ) ) { 20138928Sjdp return FALSE; 20238928Sjdp } 20338928Sjdp /* 20438928Sjdp * name must start with an underscore if uflag is set. 20538928Sjdp * can't have any `funny' characters in name, 20638928Sjdp * where `funny' means `.' (.o file names) 20738928Sjdp * need to make an exception for sparc .mul & co. 20838928Sjdp * perhaps we should just drop this code entirely... 20938928Sjdp */ 21038928Sjdp name = strtab + nlistp -> n_un.n_strx; 21138928Sjdp if ( uflag && *name != '_' ) 21238928Sjdp return FALSE; 21338928Sjdp#ifdef sparc 21438928Sjdp if ( *name == '.' ) { 21538928Sjdp char *p = name + 1; 21638928Sjdp if ( *p == 'u' ) 21738928Sjdp p++; 21838928Sjdp if ( strcmp ( p, "mul" ) == 0 || strcmp ( p, "div" ) == 0 || 21938928Sjdp strcmp ( p, "rem" ) == 0 ) 22038928Sjdp return TRUE; 22138928Sjdp } 22238928Sjdp#endif 223105243Scharnier while ( (c = *name++) ) { 22438928Sjdp if ( c == '.' ) { 22538928Sjdp return FALSE; 22638928Sjdp } 22738928Sjdp } 22838928Sjdp return TRUE; 22938928Sjdp} 230