rsp2elff.cxx 8.67 KB
#include <stdlib.h>
#include <string.h>
#include <fstream.h>
#include <symconst.h>

#include "rsp2elf.h"

source * fileList, * fileLast;

extern int hasLineInfo, includeConstants, labelCount;
extern ifstream lineFile;
extern char srcBuf[];
extern symbol * symTable;
extern unsigned long codeBase;
extern int textSectionSize;
extern int simplified;

char * lastFile = "";
int fileCount, procCount;
unsigned long codeBase = 0x1000;	 /* impossibly high address */

void DumpFileTable( void )
{
	source * sfp = fileList;
	range * rng;
	line * lin;

	while ( sfp )
	{
        	sfp->print();
		rng = sfp->firstRange();
		while ( rng )
		{
                	rng->print();
			rng = rng->next;
		}
		lin = sfp->GetLines();
		if ( lin )
		{
			cout << " LINES ";
			while ( lin )
			{
                		lin->print();
				lin = lin->next;
			}
			cout << endl;
		}
                sfp->PrintProcs();
		sfp->PrintSymbols();
		sfp = sfp->next;
	}
}

/************************************************************************
Function: GetFileOfAddr
Args: unsigned long addr - the address to look up
Type: int - returns number of file containing addr
Purpose: This function looks up an address by walking the list of files
	and their associated address ranges. When the address is found
	the index of the file is returned.
************************************************************************/
int GetFileOfAddr( unsigned long addr )
{
	source * sfp;
	int fileNumber = 0;

	if ( !fileList )
		return -1;
	sfp = fileList;
	while ( sfp )
	{
		if ( sfp->containsAddr( addr ) )
			return fileNumber;
		sfp = sfp->next;
		++fileNumber;
	}
	return -1;	/* couldn't find it */
}

/************************************************************************
Function: SymBaseOfFile
Args: int fileno - The number of the file, as returned by GetFileOfAddr()
Type: int - returns the index of the first symbol for that file
Purpose: This function looks up the  base symbol for the specified file
	(by position in the file list). It is needed so we can subtract
	off the base symbol and specify a relative symbol number for a
	symbol.
************************************************************************/
int SymBaseOfFile( int fileno )
{
	source * sfp = fileList;

	if ( fileno < 0 )
		return 0;
	while ( fileno-- )
	{
		sfp = sfp->next;
		if ( !sfp )
			return 0;
	}
	return sfp->FirstSymIs();
}

/************************************************************************
Function: AddSymToFile
Args: symbol * sym - the symbol to be added
Type: void
Purpose: This function adds a symbol to a file. If it is in the range
	of a proc, then it is added to the proc itself; otherwise,
        it is added to the orphan symbol list for the file itself
************************************************************************/
void AddSymToFile( symbol * sym )
{
	source * sfp = fileList;
	int fileNumber = sym->GetFile();
        proc * pro;

	if ( fileNumber < 0 )
	{
		--labelCount;	// Not a label in any valid code range, ignore it
		return;
	}
	while ( fileNumber-- )
		sfp = sfp->next;
	pro = sfp->GetProcs();
	while ( pro )
        {
		if ( pro->contains( sym->GetValue() ) )
		{
			// add it to this proc
			pro->AddSymbol( sym );
			return;
		}
		pro = pro->next;
	}
	// add it to the orphan list instead
	sfp->AddSymbol( sym );
}

/************************************************************************
Function: AddSyntheticProc
Args: none
Type: void
Purpose: This function adds a proc entry for the synthetic proc to
	the first file on the file list.
************************************************************************/
void AddSyntheticProc( void )
{
	proc * synth = new proc;
	line * nullLine = new line( 0 );

	synth->callMe( symTable->NameIs() );
	synth->newlow( codeBase, 0 );
	synth->newhigh( codeBase + textSectionSize - 1, nullLine );
	synth->AsgLineIndex( -1 );
	synth->next = fileList->GetProcs();
	++procCount;
	fileList->JamProc( synth );
}

/************************************************************************
Function: CleanupInfo
Args: none
Type: void
Purpose: This function walks the file list and adds the number of labels
	for all the procs in the file to the total count of labels for
	the file. This simplifies building debug info, since we will
	know how many symbols are needed for each file without having
	to traverse the list again. It also looks for files that have
	no user-specified procs. For these, it synthesizes a proc so that
	line numbers can be used.
************************************************************************/
void CleanupInfo( void )
{
	source * sfp = fileList;

	while ( sfp )
	{
		proc * pro;

		pro = sfp->GetProcs();
		if ( !pro && !simplified )
		{
			cout << "File " << sfp->filename() << 
				" has no procs - making one" << endl;
			sfp->MakeProcForFile();
			++procCount;
			pro = sfp->GetProcs();
		}
		while ( pro )
		{
			symbol * sym;

			sym = pro->GetLabels();
			while ( sym )
			{
				sfp->OneMoreLabel();
				sym = sym->pnext;
			}
			pro = pro->next;
		}
		sfp = sfp->next;
	}
}

/************************************************************************
Function: BuildFileTable
Args: none
Type: void
Purpose: This function reads the line file (.sym) and builds a linked list
	of the source files used to build this executable. For each
	source file, there is a list of the address ranges contained in
	the file with one record for each contiguous block of addresses.
	In general, including a .s file forces another record because
	instructions will have been generated. This is not a rule, of
	course; the program simply looks for an address that did not
	match the last one + 4. The resulting file table also tracks
	source lines for each file.

	Note that the .sym file contains other directives besides .lines.
	These are also processed here. .sname and .vname records are
	added to the symbol table as constants only if the user has
	requested that constants are to be included. .unname records are
	ignored. The proc records (entry and end) are used to build the
	proclist for this file.
************************************************************************/
void BuildFileTable( void )
{
	char *s, *addr, *file, *name;
	int sourceLine;
	source * sfile;
	line * l;
	unsigned long IMEMloc;
	int procPending = 0, isInsideProc = 0;;
	class proc * newProc;

	if ( !hasLineInfo )
		return;
	lineFile.seekg( 0 );	/* just in case... */
	while ( lineFile.getline( srcBuf, 1024 ) != NULL )
	{
		/* parse line, see if it's the same file as last time */

		s = strtok( srcBuf, " \t\n" );
		if ( strcmp( s, "line" ) )
		{
			if ( !strcmp( s, "sname" ) ||	/* scalar reg name */
				!strcmp( s, "vname" ) )	/* vector reg name */
			{
				if ( !includeConstants )
					continue;
				name = strtok( NULL, " \t\n" );	/* get name */
				sourceLine = atoi( strtok( NULL, " \t\n" ) );	/* regnum */
				if ( (s = (char *) malloc( strlen( name ) + 1 )) == NULL )
					nospace();
				strcpy( s, name );
				NewSymbol( s, sourceLine, stConstant );
			}
			else if ( !strcmp( s, "entry" ) )
			{
				name = strtok( NULL, " \t\n" );	/* get name */
				if ( !name )
				{
					cerr << "Bad entry directive" << endl;
					continue;
				}
				newProc = new proc;
				newProc->callMe( name );
				procPending = 1;
				isInsideProc = 1;
				++procCount;
			}
			else if ( !strcmp( s, "end" ) )
			{
				name = strtok( NULL, " \t\n" );	/* get name */
				isInsideProc = 0;
				newProc->newhigh( IMEMloc + IMEM_START + 3, l );
			}
			else if ( strcmp( s, "unname" ) )	/* ignore it */
				cerr << "Unknown directive type " << s
					<< endl;
			continue;
		}

		/* Got a line directive */

		addr = strtok( NULL, " \t\n" );
		IMEMloc = strtoul( addr, (char **) NULL, 16 ) & 0xfff;
		if ( IMEMloc < codeBase )
			codeBase = IMEMloc;
		file = strtok( NULL, " \t\n" );
		sourceLine = atoi( strtok( NULL, " \t\n" ) );

		if ( strcmp( lastFile, file ) )		/* name change */
		{
			sfile = fileList;
			while ( sfile )
			{
				if ( !strcmp( sfile->filename(), file ) )
					break;
				sfile = sfile->next;
			}
			if ( !sfile )	/* not in list, add it */
			{
				sfile = new source;
				if ( !fileList )
					fileList = fileLast = sfile;
				else
				{
					fileLast->next = sfile;
					fileLast = sfile;
				}
				sfile->callMe( file );
				++fileCount;
			}
		}
		lastFile = sfile->filename();

		if ( procPending )	/* take care of it now */
		{
			NewSymbol( newProc->nameIs(), IMEMloc + IMEM_START,
				stProc );
			newProc->newlow( IMEMloc + IMEM_START, sourceLine );
                        sfile->AddProc( newProc );
		}

		sfile->newRange( IMEMloc + IMEM_START, sourceLine );

		/*
			We are now pointing to the right file list.
			See if this is more of the same region or a
			new one.
		*/

		l = new line( sourceLine );
		if ( isInsideProc )
			newProc->AddLine( l );
		else	// orphan
			sfile->AddLine( l );
		procPending = 0;
	}
}