mips symbol table stripping

David Nelson david at horizon.kai.com
Sat Sep 23 00:50:01 AEST 1989


>From: Daniel McCoy <uiucuxc!pixar!mccoy>
>There is a set of functions for reading mips coff files, 
>(sgi: ldfcn(4), dec ldfcn(5)),
>but they make no provisions for writing things back out.

Don't forget staux(3X), stcu(3X), stfd(3X), stfe(3X), stio(3X) and
finally stprint(3X) in the IRIS-4D Programmer's Reference Manual
Volumn II, Section 3. My favorite was the section on the symbol table
in the Assembler manual. Just enough of a description to make you
think you might be able to do the task, but not enough to make it even
close to being easy. 

I spent a weekend trying to get a handle on the 'correct' way of
reading and recreating a symbol table. We needed to get rid of
declared but unreferenced global symbols (about 19Mb worth).  Monday I
found out that "ld -r" would do the trick and also using the "-x"
option to strip local symbols helped even more.

The result of the weekend was an ugly bit of code to print out the
contents of the symbol table. (I wonder how long it took to implement
odump... ) I'll include it here just in case it can be of use.

David Nelson               UUCP:      ...!uunet!uiucuxc!kailand!dnelson
Kuck and Associates, Inc.  Internet:  dnelson at kai.com 
1906 Fox Drive             Arpanet:   dnelson%kai.com at uxc.cso.uiuc.edu
Champaign, Ill. 61820      Optimizing software for supercomputers

---------- cut here ------------ cut here ------------ cut here ---------
/*
 * First hack at a program to muck around the mips symbol table.
 * odump will do a better job, but here you get the source.
 *
 * Written by:
 *	David Nelson               UUCP:      ...!uunet!uiucuxc!kailand!dnelson
 *	Kuck and Associates, Inc.  Internet:  dnelson at kai.com 
 *	1906 Fox Drive
 *	Champaign, Illinois   61820      Optimizing software for supercomputers
 *
 */
#include <stdio.h>
#include <filehdr.h>
#include <syms.h>
#include <ldfcn.h>

int verbose = 1;
LDFILE *infile = NULL;

print_st(int st)
    {
	switch (st)
	    {
	    case stNil:
		printf("stNil   ");
		break;
	    case stGlobal:
		printf("stGlobal");
		break;
	    case stStatic:
		printf("stStatic");
		break;
	    case stParam:
		printf("stParam ");
		break;
	    case stLocal:
		printf("stLocal ");
		break;
	    case stLabel:
		printf("stLabel ");
		break;
	    case stProc:
		printf("stProc  ");
		break;
	    case stBlock:
		printf("stBlock ");
		break;
	    case stEnd:
		printf("stEnd   ");
		break;
	    case stMember:
		printf("stMember");
		break;
	    case stTypedef:
		printf("stTypedef");
		break;
	    case stFile:
		printf("stFile  ");
		break;
	    case stRegReloc:
		printf("stRegReloc");
		break;
	    case stForward:
		printf("stForward");
		break;
	    case stStaticProc:
		printf("stStaticProc");
		break;
	    case stConstant:
		printf("stConstant");
		break;
	    }
    }

void print_sc(int sc)
    {
	switch (sc)
	    {
	    case scNil:
		printf("scNil");
		break;
	    case scText:
		printf("scText");
		break;
	    case scData:
		printf("scData");
		break;
	    case scBss:
		printf("scBss");
		break;
	    case scRegister:
		printf("scRegister");
		break;
	    case scAbs:
		printf("scAbs");
		break;
	    case scUndefined:
		printf("scUndefined");
		break;
	    case scCdbLocal:
		printf("scCdbLocal");
		break;
	    case scBits:
		printf("scBits");
		break;
	    case scCdbSystem:
		printf("scCdbSystem");
		break;
	    case scRegImage:
		printf("scRegImage");
		break;
	    case scInfo:
		printf("scInfo");
		break;
	    case scUserStruct:
		printf("scUserStruct");
		break;
	    case scSData:
		printf("scSData");
		break;
	    case scSBss:
		printf("scSBss");
		break;
	    case scRData:
		printf("scRData");
		break;
	    case scVar:
		printf("scVar");
		break;
	    case scCommon:
		printf("scCommon");
		break;
	    case scSCommon:
		printf("scSCommon");
		break;
	    case scVarRegister:
		printf("scVarRegister");
		break;
	    case scVariant:
		printf("scVariant");
		break;
	    case scSUndefined:
		printf("scSUndefined");
		break;
	    case scInit:
		printf("scInit");
		break;
	    case scMax:
		printf("scMax");
		break;
	    }
}

void print_sym(pSYMR sym)
    {
	printf("%20s\tvalue = %#8x\t", ((sym->iss) ? (char *)st_str_iss(sym->iss) : ""), sym->value);
	print_sc(sym->sc);
	printf("\t");
	print_st(sym->st);
	printf("\tindex = %#6x\n", sym->index);
    }

void print_ext(pEXTR extr)
    {
	pSYMR sym = &(extr->asym);
	printf("%20s\tvalue = %#8x\t", ((sym->iss) ? (char *)st_str_extiss(sym->iss) : ""), sym->value);
	print_sc(sym->sc);
	printf("\t");
	print_st(sym->st);
	printf("\tindex = %#6x\n", sym->index);
    }

void get_sym_info( )
    {
	int num_extern;
	int num_local;
	int num_dense;
	pCHDRR cur_pCHDR;
	int syms_in_file;
	int i;

	if (FSEEK(infile,HEADER(infile).f_symptr,BEGINNING) != 0) {
		perror("seeking to the symbol table");
		exit(1);
	    }
	if (st_readst(fileno(IOPTR(infile)), 'r', 0, (pCHDRR)0, -1) != 0) {
		perror("reading the symbol table");
		exit(1);
	    }
	st_setfd(0);	/* we will start with the first 'file' when printing local syms */

	cur_pCHDR = (pCHDRR) st_currentpchdr();
	num_local = cur_pCHDR->hdr.isymMax;
	num_extern = cur_pCHDR->cext;
	num_dense = cur_pCHDR->cdn;
	if (verbose) {
		printf("      pdn = %#x\n", cur_pCHDR->pdn);
		printf("      cdn = %d\n", num_dense);
		printf("   cdnMax = %d\n", cur_pCHDR->cdnMax);
		printf("num_local = %d\n", num_local);
		printf("num_extern = %d\n", num_extern);
	    }

	/* print local symbols */
	syms_in_file = PFD(infile)[st_currentifd()].csym;	/* how many syms in this 'file' */
	for (i=0; i<num_local; i++) {
		if (syms_in_file <= 0) {	/* go to the next 'file' */
			st_setfd(st_currentifd()+1);	/* must be set to use the string table */
			syms_in_file = PFD(infile)[st_currentifd()].csym;
		    }
		syms_in_file -= 1;
		printf("symbol: %3d ",i);
		print_sym( &(cur_pCHDR->psym[i]) );
	    }

	/* external symbols (not arranged by 'file') */
	for (i=0; i<num_extern; i++) {
		printf("extern: %3d ",i);
		print_ext( &(cur_pCHDR->pext[i]) );
	    }
    }

void get_info(char *filename)
    {
	printf("filename = \"%s\"\n", filename);
	if ((infile = ldopen(filename,infile)) == NULL) {
		perror("opening input file");
		exit(1);
	    }
	if (ISARCHIVE(TYPE(infile)))
	    printf("it looks like an archive\n");
	if (verbose) {
		printf("f_magic = %#06x\n", HEADER(infile).f_magic);	/* magic number */
		printf("f_nscns = %d\n", HEADER(infile).f_nscns);	/* number of sections */
		printf("f_timdat = %d\n", HEADER(infile).f_timdat);	/* time & date stamp */
		printf("f_symptr = %d\n", HEADER(infile).f_symptr);	/* file pointer to symbolic header */
		printf("f_nsyms = %d\n", HEADER(infile).f_nsyms);	/* sizeof(symbolic hdr) */
		printf("f_opthdr = %d\n", HEADER(infile).f_opthdr);	/* sizeof(optional hdr) */
		printf("f_flags = 0x%04x\n", HEADER(infile).f_flags);	/* flags */
	    }
	if (HEADER(infile).f_flags != 0) {
		printf("I cannot work with this file");
		if ((HEADER(infile).f_flags & F_RELFLG) == F_RELFLG)
		    printf(", the relocation entries have been stripped");
		if ((HEADER(infile).f_flags & F_EXEC) == F_EXEC)
		    printf(", it is an executable");
		if ((HEADER(infile).f_flags & F_LNNO) == F_LNNO)
		    printf(", there are no line number entries");
		if ((HEADER(infile).f_flags & F_LSYMS) == F_LSYMS)
		    printf(", the local symbols have been stripped");
		printf(".\n");
		exit(1);
	    }

	get_sym_info( );
    }

int main(int argc, char *argv[])
    {
	char *filename = NULL;
	if (argc != 2) {
		fprintf( stderr, "Usage: %s file.o\n", argv[0]);
		exit(1);
	    }
	filename = argv[argc-1];
	
	/* now collect info on the named file. */
	get_info(filename);
	
	return 0;
    }
---------- cut here ------------ cut here ------------ cut here ---------
David Nelson               UUCP:      ...!uunet!uiucuxc!kailand!dnelson
Kuck and Associates, Inc.  Internet:  dnelson at kai.com 
1906 Fox Drive             Arpanet:   dnelson%kai.com at uxc.cso.uiuc.edu
Champaign, Ill. 61820      Optimizing software for supercomputers



More information about the Comp.sys.sgi mailing list