[comp.sys.sgi] mips symbol table stripping

mccoy@pixar.UUCP (Daniel McCoy) (09/21/89)

Is there a tool around for manipulating the mips object file
symbol table?   (SGI 4D, DEC 3100, etc.)

I have created an object file which contains a large package 
linked together with the relocation preserved. (ld -r)
The idea is that customers will be able to link this package into
their application as a major subsystem. (They also have the
option of running it as a separate program.)
  
That works fine, but all of the global symbols that link the guts of
the package together are still present in the symbol table.

I want to preserve the set of symbols that define the interface 
to the package as well as undefined references to system libraries.   
I would like to either remove or remap any other symbols,
so as to avoid accidental symbol collisions with applications.

Changing the source of the package is not an option.

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.

strip(1) is pretty much all or nothing.

I'm in the process of rolling my own, but I would appreciate anything
that might be of help.

Thanks,

Dan McCoy    pixar!mccoy    (415) 258-8195   Pixar, San Rafael, Ca

david@horizon.kai.com (David Nelson) (09/22/89)

>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@kai.com 
1906 Fox Drive             Arpanet:   dnelson%kai.com@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@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@kai.com 
1906 Fox Drive             Arpanet:   dnelson%kai.com@uxc.cso.uiuc.edu
Champaign, Ill. 61820      Optimizing software for supercomputers