mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 08:24:18 +00:00
1605 lines
49 KiB
C
1605 lines
49 KiB
C
/*
|
|
Copyright 1981
|
|
Alcyon Corporation
|
|
8474 Commerce Av.
|
|
San Diego, Ca. 92121
|
|
*/
|
|
|
|
#include "cout.h"
|
|
#include "lo68.h"
|
|
struct lib2hdr *lib2hd = 0;
|
|
#define BLKSIZE 512
|
|
|
|
/* 68000 linking loader*/
|
|
/* Bill Allen*/
|
|
|
|
/* This loader is basically a two pass operation. The first pass*/
|
|
/* reads all the relocatable object files including any libraries.*/
|
|
/* It builds the full symbol table, resolves all external symbol*/
|
|
/* references if possible, and calculates the total size of the*/
|
|
/* text, data, and bss segements. Pass 2 then does the binding,*/
|
|
/* the relocation, and produces the final output file.*/
|
|
|
|
#define MAGIC1 MAGIC+1 /*magic # for data & bss base specified*/
|
|
|
|
#ifdef VMS
|
|
char libname[] = "lib:lib6.a"; /*default library name*/
|
|
#define LIBCHAR libname[7] /* Character to be modified */
|
|
#endif
|
|
|
|
#ifdef CPM
|
|
char libname[] = "lib6.a";
|
|
#define LIBCHAR libname[3] /* Character to be modified */
|
|
#endif
|
|
|
|
#ifdef UNIX
|
|
char libname[] = "/lib/lib6.a"; /* Default library name */
|
|
#define LIBCHAR libname[8] /* Character to be modified */
|
|
#endif
|
|
|
|
char *ofilname = "c.out"; /*output file name*/
|
|
|
|
#ifdef UNIX /************************/
|
|
char *tfbase = "loXXXXXX"; /* Temp base name */
|
|
char *tdisk = "/tmp/"; /* Temp disk name */
|
|
#else /* CP/M and VMS */
|
|
char *tfbase = "loXXXXXA"; /* Temp base name */
|
|
char *tdisk = ""; /* Temp disk name */
|
|
#endif /************************/
|
|
|
|
char *tfchar = 0; /* -> changeable character */
|
|
char tfilname[80] = {0}; /*first temp file name*/
|
|
#define TFCHAR *tfchar /* Name to simplify assignments */
|
|
char etexstr[] = "_etext\0\0";
|
|
char edatstr[] = "_edata\0\0";
|
|
char eendstr[] = "_end\0\0\0\0";
|
|
int endit();
|
|
long lgetnum();
|
|
char *lemt();
|
|
char *nextsy();
|
|
char *sbrk();
|
|
int readshort();
|
|
int ignflg =0;
|
|
int debug =0;
|
|
int exstat =0;
|
|
|
|
#ifdef VAX
|
|
struct { char lobyte; char hibyte; };
|
|
#endif
|
|
|
|
#ifdef PDP11
|
|
struct { char lobyte; char hibyte; };
|
|
#endif
|
|
|
|
#ifdef MC68000
|
|
struct { char hibyte; char lobyte; };
|
|
#endif
|
|
|
|
long lseek();
|
|
main(argc,argv)
|
|
char **argv;
|
|
{
|
|
|
|
register char **p;
|
|
register char *pc;
|
|
register i;
|
|
register char *p1;
|
|
register int j;
|
|
|
|
/* signal(2,endit);*/ /*catch rubout*/
|
|
buildf(); /* Construct temp file names */
|
|
intsytab(); /*initialize the symbol table*/
|
|
firstsym = fsymp;
|
|
libfctr = lbfictr;
|
|
libptr = lbfioff;
|
|
if(argc <= 1) {
|
|
usage:
|
|
printf(": Invalid lo68 argument list\n");
|
|
endit(-1);
|
|
}
|
|
p = argv+1;
|
|
for(i=1; i<argc; i++) { /*process each argument*/
|
|
pc = *p++;
|
|
/*
|
|
* Compare for a file named ".o" and skip it for CP/M and VAX
|
|
* command file operation.
|
|
*/
|
|
if(_strcmp (pc,".o") == 0)
|
|
continue; /* Just skip this one */
|
|
|
|
|
|
if(*pc == '-') {
|
|
switch(*++pc) {
|
|
|
|
case 'l': /*library*/
|
|
pc--;
|
|
break;
|
|
|
|
case 'o': /*output file name*/
|
|
if(*(pc+1) != '\0') /* No space? */
|
|
{
|
|
printf(": Illegal option %s\n",*(--p));
|
|
exit(-1);
|
|
}
|
|
ofilname = *p++; /*next arg is file name*/
|
|
i++;
|
|
continue;
|
|
|
|
case 's': /*don't output symbol table*/
|
|
sflag++;
|
|
continue;
|
|
|
|
case 'X': /*keep local symbols except L**/
|
|
case 'x':
|
|
Xflag++;
|
|
continue;
|
|
|
|
case 'Z': /*offset the text base for standaone pgm*/
|
|
case 'z':
|
|
|
|
case 'T': /*another name for same flag*/
|
|
case 't':
|
|
Zflag++;
|
|
textstart = lgetnum(++pc,16); /*get a long hex number*/
|
|
textbase = textstart;
|
|
continue;
|
|
|
|
case 'D': /*data segment base*/
|
|
case 'd':
|
|
Dflag++;
|
|
datastart = lgetnum(++pc,16);
|
|
continue;
|
|
|
|
case 'B': /*bss segment base*/
|
|
case 'b':
|
|
Bflag++;
|
|
bssstart = lgetnum(++pc,16);
|
|
continue;
|
|
|
|
case 'I': /*ignore 16-bit addr overflow*/
|
|
case 'i':
|
|
ignflg++;
|
|
continue;
|
|
|
|
case 'r':
|
|
saverbits++; /*put relocation bits on c.out*/
|
|
continue;
|
|
|
|
case 'U': /*initial undefined symbol*/
|
|
case 'u':
|
|
p1 = lmte;
|
|
pc++;
|
|
for(j=0; j<SYNAMLEN; j++) {
|
|
*p1++ = *pc;
|
|
if(*pc)
|
|
pc++;
|
|
}
|
|
|
|
lmte->flags = SYXR; /*external reference*/
|
|
addsym(0); /*put into symbol table*/
|
|
continue;
|
|
|
|
case 'f': /* Temp file prefix */
|
|
tdisk = *p++; /* Prefix */
|
|
i++;
|
|
buildf(); /* build file names */
|
|
continue;
|
|
|
|
}
|
|
}
|
|
p1load(pc); /*read file or library*/
|
|
}
|
|
resolve(); /*resolve externals and assign addresses*/
|
|
pass2++; /*now in pass 2*/
|
|
p = argv+1;
|
|
firstsym = fsymp;
|
|
libfctr = lbfictr;
|
|
libptr = lbfioff;
|
|
makeofile(); /*make the output file*/
|
|
for(i=1; i<argc; i++) { /*process each argument*/
|
|
pc = *p++;
|
|
|
|
/*
|
|
* Skip files named ".o" again ...
|
|
*/
|
|
if(_strcmp(pc,".o") == 0)
|
|
continue;
|
|
|
|
if(*pc == '-') {
|
|
switch(*++pc) {
|
|
|
|
case 'l': /*library*/
|
|
pc--;
|
|
break;
|
|
|
|
case 'f': /* Temp file name */
|
|
case 'o': /*output file name*/
|
|
p++; /*skip file name*/
|
|
i++;
|
|
continue;
|
|
|
|
|
|
case 's': /*don't output symbol table*/
|
|
case 'X':
|
|
case 'x':
|
|
case 'Z':
|
|
case 'z':
|
|
case 'I':
|
|
case 'i':
|
|
case 'U':
|
|
case 'u':
|
|
case 'T':
|
|
case 't':
|
|
case 'D':
|
|
case 'd':
|
|
case 'B':
|
|
case 'b':
|
|
case 'r':
|
|
continue;
|
|
|
|
}
|
|
}
|
|
p2load(pc); /*read file or library*/
|
|
}
|
|
finalwr(); /*finish output file*/
|
|
}
|
|
buildf()
|
|
{
|
|
tfilname[0]=0; /* Null out present filename */
|
|
strcat (tfilname,tdisk); /* Put disk name in first */
|
|
strcat (tfilname,tfbase); /* Put in filename now */
|
|
|
|
/******************************/
|
|
#ifdef UNIX /* On UNIX, */
|
|
mktemp (tfilname); /* Make a temp filename */
|
|
#endif /******************************/
|
|
|
|
tfchar = &tfilname[strlen(tfilname)-1]; /* Set pointer */
|
|
|
|
}
|
|
|
|
/* pass 1 load routine:*/
|
|
/* read the file or library and build the symbol table*/
|
|
/* symbols are organized on the initial reference tables*/
|
|
/* with externals on eirt and globals on girt*/
|
|
int ii=0;
|
|
p1load(ap)
|
|
char *ap;
|
|
{
|
|
ii = 0;
|
|
openfile(ap); /*get the file opened using ibuf*/
|
|
if(couthd.ch_magic == LIB1MAGIC) { /*library*/
|
|
libhdsize = LIB1HDSIZE; /*old ar header size*/
|
|
searchlib();
|
|
}
|
|
else if(couthd.ch_magic == LIB2MAGIC) { /*library*/
|
|
libhdsize = sizeof *lib2hd; /*new ar header size*/
|
|
searchlib();
|
|
}
|
|
else if(couthd.ch_magic == LIB3MAGIC) {
|
|
getw(&ibuf);
|
|
getw(&ibuf);
|
|
getw(&ibuf);
|
|
libhdsize = LIB3HDSIZE;
|
|
searchlib();
|
|
}
|
|
else {
|
|
do1load(0); /*load a *.o file*/
|
|
firstsym++;
|
|
addsizes();
|
|
}
|
|
close(ibuf.fildes);
|
|
}
|
|
|
|
/* search a library for files to include. include an entry only*/
|
|
/* if it has a global symbol which matches an external.*/
|
|
|
|
long lbctr =0;
|
|
long libfilsize =0;
|
|
|
|
searchlib()
|
|
{
|
|
|
|
*libfctr = 0; /*no files from this library yet*/
|
|
lbctr = sizeof(short); /*current library position - skip magic*/
|
|
while(rdlibhdr()) { /*read library file header*/
|
|
savsymtab(); /*save current state of symbol table*/
|
|
extmatch = 0;
|
|
noload = 0;
|
|
ifilname = libhd;
|
|
readhdr(); /*read the file header*/
|
|
do1load(1); /*load this files symbol table & try match*/
|
|
if(extmatch > noload) { /*found a match*/
|
|
if(noload)
|
|
prdup(lastdup); /*print dup defn*/
|
|
addsizes(); /*add this files sizes*/
|
|
firstsym++;
|
|
*libfctr += 1; /*count files loaded from this library*/
|
|
*libptr++ = lbctr; /*remember offset in library*/
|
|
}
|
|
else { /*dont need this file*/
|
|
restsymtab(); /*restore symbol table*/
|
|
}
|
|
if(libfilsize&1) { /*one byte of padding*/
|
|
getc(&ibuf);
|
|
lbctr++;
|
|
}
|
|
lbctr += libfilsize + libhdsize;
|
|
lbseek(lbctr,&ibuf); /*goto begin of next lib entry*/
|
|
}
|
|
libfctr++; /*point to next library file counter*/
|
|
}
|
|
|
|
/*read a library file header*/
|
|
rdlibhdr()
|
|
{
|
|
|
|
register char *p;
|
|
register int i;
|
|
register char *pc;
|
|
|
|
p = libhd;
|
|
for( i = 0; i < sizeof *lib2hd; i++ )
|
|
*p++ = getc(&ibuf);
|
|
libhd->l2modti = 0;
|
|
libfilsize = libhd->l2fsize;
|
|
if( libhd->l2fname[0] == '\0' )
|
|
return(0);
|
|
return(1);
|
|
}
|
|
|
|
/* open the file pointed to by ap*/
|
|
/* check for the -lx type library spec*/
|
|
|
|
openfile(ap)
|
|
char *ap;
|
|
{
|
|
|
|
register char *p;
|
|
register short i;
|
|
|
|
p = ap;
|
|
if(*p=='-' && *++p=='l') {
|
|
if(*++p)
|
|
LIBCHAR = *p;
|
|
else
|
|
LIBCHAR = '6'; /*default library name*/
|
|
p = libname;
|
|
}
|
|
else
|
|
p = ap;
|
|
if((ibuf.fildes=fopen(p,&ibuf,1)) < 0) {
|
|
printf(": unable to open %s\n",p);
|
|
endit(-1);
|
|
}
|
|
ifilname = p; /*point to current file name for error msgs*/
|
|
if( readshort(ibuf.fildes,&couthd.ch_magic) ) {
|
|
printf(": read error on file: %s\n",ifilname);
|
|
endit(-1);
|
|
}
|
|
ibuf.nunused = 0;
|
|
if( couthd.ch_magic != LIB2MAGIC ) {
|
|
lseek(ibuf.fildes,0L,0);
|
|
readhdr(); /*read file header*/
|
|
}
|
|
if(pass2) { /*need file descrptr for reloc bits*/
|
|
fopen(p,&rbuf,1);
|
|
}
|
|
}
|
|
|
|
/* read the header of the input file*/
|
|
|
|
int readshort(fd,s)
|
|
int fd;
|
|
short *s;
|
|
{
|
|
short ts;
|
|
|
|
if( read(fd,&ts,sizeof(short)) != sizeof(short) )
|
|
return(1);
|
|
*s = ts;
|
|
return(0);
|
|
}
|
|
readhdr()
|
|
{
|
|
|
|
register int i;
|
|
register short *p;
|
|
|
|
p = &couthd;
|
|
for( i = 0; i < (sizeof couthd)/2; i++ )
|
|
*p++ = getw(&ibuf);
|
|
if(couthd.ch_magic != MAGIC) {
|
|
printf(": file format error: %s\n",ifilname);
|
|
endit(-1);
|
|
}
|
|
if(couthd.ch_rlbflg) {
|
|
printf(": File format error");
|
|
printf(": no relocation bits in %s\n",ifilname);
|
|
endit(-1);
|
|
}
|
|
}
|
|
|
|
/* load one *.o format file using ibuf*/
|
|
/* put the symbols into the symbol table relocating each one*/
|
|
/* and finally add this files sizes into running totals*/
|
|
|
|
/* libflg is set if we are in a library*/
|
|
|
|
do1load(libflg)
|
|
{
|
|
|
|
register long i;
|
|
register long l;
|
|
|
|
*firstsym = lmte; /*remember where this symbol table starts*/
|
|
l = couthd.ch_tsize + couthd.ch_dsize + sizeof couthd;
|
|
if( libflg )
|
|
l += lbctr + sizeof *lib2hd;
|
|
lbseek(l,&ibuf);
|
|
i = couthd.ch_ssize; /*size of symbol table*/
|
|
while(i > 0) {
|
|
getsym(); /*read one symbol entry*/
|
|
relocsym(); /*fix its address*/
|
|
addsym(libflg); /*add to symbol table*/
|
|
i -= OSTSIZE;
|
|
}
|
|
}
|
|
|
|
/* get one symbol entry from the input file and put it into*/
|
|
/* the symbol table entry pointed to by lmte*/
|
|
|
|
getsym()
|
|
{
|
|
|
|
register int i;
|
|
register short *p;
|
|
|
|
p = lmte;
|
|
for(i=0; i<SYNAMLEN/(sizeof *p); i++)
|
|
*p++ = getw(&ibuf);
|
|
*p++ = getw(&ibuf); /* flags */
|
|
/* *p++=0; */ /* skip upp half of internal flags on VAX */
|
|
p->hiword = getw(&ibuf); /* sym value high word */
|
|
p->loword = getw(&ibuf); /* sym vaue low word */
|
|
}
|
|
|
|
/* relocate the symbol value pointed to by lmte according to*/
|
|
/* symbol type and corresponding relocation base*/
|
|
|
|
relocsym()
|
|
{
|
|
register long l;
|
|
|
|
l = 0;
|
|
if(lmte->flags&SYXR) /*external*/
|
|
return;
|
|
if(lmte->flags&SYTX)
|
|
l = textbase;
|
|
else if(lmte->flags&SYDA)
|
|
l = database;
|
|
else if(lmte->flags&SYBS)
|
|
l = bssbase;
|
|
else {
|
|
if(lmte->flags&SYEQ) /*equated*/
|
|
return; /* abs*/
|
|
printf(": File Format error: Invalid symbol flags = %o\n",
|
|
(int)lmte->flags);
|
|
endit(-1);
|
|
}
|
|
lmte->vl1 += l;
|
|
}
|
|
|
|
/* add a symbol to the symbol table*/
|
|
/* if symbol is an external, put it on eirt even if it does*/
|
|
/* already exist*/
|
|
/* if symbol is a global, put it on girt and error if it exists*/
|
|
/* in any case, add it to the end of the symbol table*/
|
|
/* if libflg is set, we are searching a library. In this case, when*/
|
|
/* a global is encountered, search the external symbols and set*/
|
|
/* extmatch if a match is found.*/
|
|
|
|
addsym(libflg)
|
|
{
|
|
|
|
register char *p;
|
|
|
|
/* if(debug) {*/
|
|
/* printf("addsym: file=%s symbol=%s flags=%o\n",ifilname,lmte,(int)lmte->flags);*/
|
|
/* }*/
|
|
if(lmte->flags&SYXR) { /*external*/
|
|
p = lemt(eirt);
|
|
mmte();
|
|
}
|
|
else if(lmte->flags&SYGL) { /*global*/
|
|
if(libflg) { /*global in a library*/
|
|
p = lemt(eirt); /*look up in externals*/
|
|
if(p != lmte) { /*found a match*/
|
|
extmatch++;
|
|
}
|
|
}
|
|
p = lemt(girt);
|
|
if(p == lmte)
|
|
mmte();
|
|
else {
|
|
dupdef:
|
|
if(libflg) {
|
|
noload++;
|
|
lastdup = p;
|
|
}
|
|
else if(p->flags != lmte->flags || p->vl1 != lmte->vl1)
|
|
prdup(p); /*dup defn msg*/
|
|
}
|
|
}
|
|
else { /*normal symbol*/
|
|
if(lmte->name[0] == 'L') /*compiler label*/
|
|
return;
|
|
if(Xflag==0) /*dont save local symbols*/
|
|
return;
|
|
addmte();
|
|
}
|
|
}
|
|
|
|
prdup(p)
|
|
char *p;
|
|
{
|
|
|
|
printf(": %s duplicate definition in %s\n",p,ifilname);
|
|
exstat++;
|
|
}
|
|
|
|
/* initialize the symbol table and the heads of the hash lists*/
|
|
|
|
intsytab()
|
|
{
|
|
|
|
register char **p1, **p2;
|
|
register i;
|
|
|
|
bmte = (sbrk((sizeof *symptr)*SZMT+2));
|
|
if((long)bmte&1)
|
|
bmte++;
|
|
emte = bmte + (sizeof *symptr)*SZMT; /*end of main table*/
|
|
lmte=bmte; /*beginning main table*/
|
|
cszmt = SZMT; /*current size of main table*/
|
|
p1 = eirt;
|
|
p2 = girt;
|
|
for(i=0; i<32; i++) {
|
|
*p1++ = p1;
|
|
*p1++ = 0;
|
|
*p2++ = p2;
|
|
*p2++ = 0;
|
|
}
|
|
}
|
|
/* method for looking up entries in the main table*/
|
|
/**/
|
|
/* Note: The entry to be looked up must be placed at the end*/
|
|
/* of the main table. The global cell 'lmte'(last main*/
|
|
/* entry) points to the next available entry in the main*/
|
|
/* table. The address of an initial reference table must*/
|
|
/* also be provided.*/
|
|
|
|
/* 1) Compute the hash code for the symbol and add it to the base address*/
|
|
/* of the initial reference table given as input. Thus, two words are*/
|
|
/* accessed which define the chain on which the symbol must be if it is*/
|
|
/* in the table at all.*/
|
|
|
|
/* 2) Alter the table link of the last symbol in the chain so that it */
|
|
/* points to the symbol being looked up. Note that the symbol to be */
|
|
/* looked up is always placed at the end of the main table before */
|
|
/* calling the lookup routine. This essentially adds one more element*/
|
|
/* to the end of the chain, namely the symbol to be looked up.*/
|
|
|
|
/* 3) Now start at the first symbol in the chain and follow the chain*/
|
|
/* looking for a symbol equal to the smbol being looked up. It is*/
|
|
/* quaranteed that such a symbol will be found because it is always */
|
|
/* the last symbol on the chain.*/
|
|
|
|
/* 4) When the symbol is found, check to see if it is the last symbol*/
|
|
/* on the chain. If not, the symbol being looked for is in the table*/
|
|
/* and has been found. If it is the last symbol, the symbol being */
|
|
/* looked up is not in the table.*/
|
|
|
|
/* 5) In the case the looked up symbol is not found, it is usually added*/
|
|
/* to the end of the table. This is done simply b changing the */
|
|
/* initial reference table entry which points to the previous*/
|
|
/* last symbol on the chain so that is now points to the symbol at the*/
|
|
/* end of the main table. In case the symbol just looked up is not to*/
|
|
/* be added to the main table then no action is needed . This means*/
|
|
/* that the table link of the last symbol on a chain may point any-*/
|
|
/* where.*/
|
|
|
|
/* look up entry in the main table*/
|
|
/* call with:*/
|
|
/* address of initial reference table*/
|
|
/* entry to be looked up at the end of the main table*/
|
|
/* returns:*/
|
|
/* a pointer to the entry. if this pointer is equal to*/
|
|
/* lmte then the symbol was not previously in the table.*/
|
|
|
|
char *lemt(airt)
|
|
char **airt;
|
|
{
|
|
|
|
register char *mtpt;
|
|
|
|
pirt = airt + hash(); /*pointer to entry in irt*/
|
|
mtpt = pirt->irfe; /*pointer to first entry in chain*/
|
|
if(mtpt==0) /*empty chain*/
|
|
mtpt = lmte; /*start at end of main table*/
|
|
else
|
|
(pirt->irle)->tlnk = lmte; /*last entry in chain is new symbol*/
|
|
return(nextsy(mtpt)); /*return next match on chain*/
|
|
}
|
|
|
|
char *nextsy(amtpt)
|
|
char *amtpt;
|
|
{
|
|
|
|
register char *mtpt;
|
|
register int *p1, *p2;
|
|
register int i;
|
|
|
|
mtpt = amtpt;
|
|
|
|
/*loop to locate entry in main table*/
|
|
lemtl:
|
|
p1 = &mtpt->name[0];
|
|
p2 = &lmte->name[0];
|
|
for(i=0; i<SYNAMLEN/(sizeof i); i++) {
|
|
if(*p1++ != *p2++) {
|
|
mtpt = mtpt->tlnk; /*go to next entry in chain*/
|
|
goto lemtl;
|
|
}
|
|
}
|
|
return(mtpt);
|
|
}
|
|
|
|
/*make an entry in the main table*/
|
|
/* assumes:*/
|
|
/* entry to be made is pointed at by lmte*/
|
|
/* pirt points to the correct initial reference table entry*/
|
|
|
|
mmte()
|
|
{
|
|
|
|
pirt->irle = lmte; /*pointer to last entry in chain*/
|
|
if(pirt->irfe == 0) /*first entry in chain*/
|
|
pirt->irfe = lmte;
|
|
addmte();
|
|
}
|
|
|
|
/* add the symbol pointed to by lmte to symbol table*/
|
|
addmte()
|
|
{
|
|
|
|
lmte += (sizeof *symptr); /*bump last main table entry pointer*/
|
|
if(lmte >= emte) { /*main table overflow*/
|
|
if(sbrk((sizeof *symptr)*ICRSZMT) == -1){ /*get more memory*/
|
|
printf(": symbol table overflow\n");
|
|
exit(-1);
|
|
}
|
|
else {
|
|
emte += (sizeof *symptr)*ICRSZMT; /*move end of main table*/
|
|
cszmt += ICRSZMT;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* compute a hash code for the last entry in the main table*/
|
|
/* returns the hash code*/
|
|
|
|
hash()
|
|
{
|
|
|
|
register ht1, i; /*temps*/
|
|
register char *p;
|
|
|
|
ht1 = 0;
|
|
p = &lmte->name[0];
|
|
for(i=0; i<SYNAMLEN; i++)
|
|
ht1 += *p++;
|
|
return(ht1&076); /*make hash code even and between 0 and 62*/
|
|
}
|
|
|
|
/* pack a string into an entry in the main table*/
|
|
/* call with:*/
|
|
/* pointer to the string*/
|
|
/* pointer to desired entry in the main table*/
|
|
|
|
pack(apkstr,apkptr)
|
|
int *apkstr;
|
|
int *apkptr;
|
|
{
|
|
|
|
register int i;
|
|
register int *pkstr, *pkptr;
|
|
|
|
pkstr = apkstr;
|
|
pkptr = apkptr;
|
|
for(i=0; i<SYNAMLEN/(sizeof i); i++)
|
|
*pkptr++ = *pkstr++;
|
|
}
|
|
/* get a temp file for the intermediate text*/
|
|
|
|
gettempf()
|
|
{
|
|
|
|
register i,j;
|
|
|
|
/* while(tfilname[10] <= 'z') {
|
|
if((j=creat(tfilname,0600))>=0)
|
|
return(j);
|
|
tfilname[10]++;
|
|
}
|
|
printf(": Unable to open temporary file: %s\n",tfilname);
|
|
endit(-1);
|
|
}*/
|
|
(TFCHAR)++;
|
|
if((j=creat(tfilname,0600,1)) >= 0)
|
|
{
|
|
return(j);
|
|
}
|
|
printf(": Unable to open temporary file: %s\n",tfilname);
|
|
endit(-1);
|
|
}
|
|
/* update the relocation counters with the sizes in the header*/
|
|
|
|
addsizes()
|
|
{
|
|
|
|
textbase += couthd.ch_tsize;
|
|
database += couthd.ch_dsize;
|
|
bssbase += couthd.ch_bsize;
|
|
}
|
|
|
|
/*save the current state of the symbol table -- it may be restored later*/
|
|
|
|
savsymtab()
|
|
{
|
|
|
|
register char **p1, **p2;
|
|
register i;
|
|
|
|
savlmte = lmte;
|
|
p2 = eirt;
|
|
p1 = saveirt;
|
|
for(i=0; i<SZIRT; i++)
|
|
*p1++ = *p2++;
|
|
p2 = girt;
|
|
p1 = savgirt;
|
|
for(i=0; i<SZIRT; i++)
|
|
*p1++ = *p2++;
|
|
}
|
|
|
|
/*restore the symbol table as it was when we last saved it*/
|
|
restsymtab()
|
|
{
|
|
|
|
register char **p1, **p2;
|
|
register i;
|
|
|
|
lmte = savlmte;
|
|
p1 = eirt;
|
|
p2 = saveirt;
|
|
for(i=0; i<SZIRT; i++)
|
|
*p1++ = *p2++;
|
|
p1 = girt;
|
|
p2 = savgirt;
|
|
for(i=0; i<SZIRT; i++)
|
|
*p1++ = *p2++;
|
|
}
|
|
|
|
/* resolve the external variable addresses and set the*/
|
|
/* base address of the data and bss segments.*/
|
|
/* also allocate storage for the common variables.*/
|
|
|
|
resolve()
|
|
{
|
|
|
|
register char *p;
|
|
|
|
textsize = textbase - textstart;
|
|
datasize = database;
|
|
bsssize = bssbase;
|
|
if(Dflag)
|
|
database = datastart;
|
|
else {
|
|
database = (textbase+1)&~1;
|
|
datastart = database;
|
|
}
|
|
if(Bflag)
|
|
bssbase = bssstart;
|
|
else {
|
|
bssbase = (database+datasize+1)&~1;
|
|
bssstart = bssbase;
|
|
}
|
|
textbase = textstart;
|
|
fixsyms(); /*relocate symbols with addresses*/
|
|
fixexts(); /*fix external addresses & commons*/
|
|
if(etextptr) {
|
|
pack(etexstr,lmte);
|
|
p=lemt(eirt);
|
|
do {
|
|
p->vl1 = textsize;
|
|
p->flags &= ~SYXR; /*no longer external*/
|
|
p->flags |= SYDF|SYGL;
|
|
} while((p=nextsy(p->tlnk)) != lmte);
|
|
}
|
|
if(edataptr) {
|
|
pack(edatstr,lmte);
|
|
p=lemt(eirt);
|
|
do {
|
|
p->vl1 = textsize+datasize;
|
|
p->flags &= ~SYXR; /*no longer external*/
|
|
p->flags |= SYDF|SYGL;
|
|
} while((p=nextsy(p->tlnk)) != lmte);
|
|
}
|
|
if(endptr) {
|
|
pack(eendstr,lmte);
|
|
p=lemt(eirt);
|
|
do {
|
|
p->vl1 = textsize+datasize+bsssize;
|
|
p->flags &= ~SYXR; /*no longer external*/
|
|
p->flags |= SYDF|SYGL;
|
|
} while((p=nextsy(p->tlnk)) != lmte);
|
|
}
|
|
}
|
|
|
|
/* fix symbol addresses that have been assigned by adding in*/
|
|
/* database and bssbase*/
|
|
|
|
fixsyms()
|
|
{
|
|
|
|
register struct symtab *p;
|
|
|
|
for(p=bmte; p<lmte; p++) { /*look at each symbol*/
|
|
if(p->flags&SYXR)
|
|
continue;
|
|
if(p->flags&SYDA) /*data symbol*/
|
|
p->vl1 += database;
|
|
else if(p->flags&SYBS) /* bss symbol*/
|
|
p->vl1 += bssbase;
|
|
}
|
|
}
|
|
|
|
/* get addresses for all external symbols and common symbols*/
|
|
fixexts()
|
|
{
|
|
|
|
register char *p;
|
|
register char **sx1, **sx2;
|
|
|
|
for(sx1=eirt; sx1<&eirt[63]; sx1 += 2) { /*go thru externals*/
|
|
if(*(sx2 = sx1+1)==0) /*this chain empty*/
|
|
continue;
|
|
|
|
/* go thru symbols on chain*/
|
|
sx2 = *sx2; /*first entry on this chain*/
|
|
while(1) {
|
|
if(sx2->vl1)
|
|
asgncomn(sx2); /*assign a common address*/
|
|
else
|
|
asgnext(sx2); /*match to a global*/
|
|
p = sx2;
|
|
if(p == *sx1) /*end of chain*/
|
|
break;
|
|
sx2 = sx2->tlnk; /*next entry in chain*/
|
|
}
|
|
}
|
|
}
|
|
|
|
/* assign an address for a block of bss common*/
|
|
asgncomn(ap)
|
|
char *ap;
|
|
{
|
|
|
|
register char *p, *p1;
|
|
register long l;
|
|
|
|
p = ap;
|
|
pack(p,lmte);
|
|
p1 = lemt(girt);
|
|
if(p1 != lmte) { /*matches a global entry*/
|
|
ap->vl1 = p1->vl1;
|
|
return;
|
|
}
|
|
l = 0;
|
|
lemt(eirt);
|
|
do {
|
|
if(p->vl1 > l)
|
|
l = p->vl1;
|
|
p->vl1 = 0;
|
|
} while((p=nextsy(p->tlnk)) != lmte);
|
|
/*now make a global entry for this common block*/
|
|
p->flags = SYDF|SYGL|SYBS;
|
|
p->vl1 = bssbase + bsssize;
|
|
ap->vl1 = p->vl1; /*copy address to first external*/
|
|
bsssize += l;
|
|
lemt(girt); /*set ptrs for global chain*/
|
|
mmte(); /*add to global chain*/
|
|
}
|
|
|
|
/* assign an address to an external by matching it with a global*/
|
|
/* print an error message if no match*/
|
|
asgnext(ap)
|
|
char *ap;
|
|
{
|
|
|
|
register char *p, *pg;
|
|
|
|
p = ap;
|
|
pack(p,lmte); /*copy current symbol name*/
|
|
pg = lemt(girt);
|
|
if(pg == lmte) { /*no match in global symbols*/
|
|
pg=lemt(eirt); /*set ptrs for external chains*/
|
|
if(pg==lmte) {
|
|
printf(": asgnext botch\n");
|
|
endit(-1);
|
|
}
|
|
while((p=nextsy(p->tlnk)) != lmte) {
|
|
if(p->vl1) { /*common*/
|
|
asgncomn(ap);
|
|
return;
|
|
}
|
|
}
|
|
if(spendsym(ap)) /*end, etext or edata*/
|
|
return;
|
|
if(undflg==0) {
|
|
printf(": Undefined symbol(s)\n");
|
|
undflg++;
|
|
exstat++;
|
|
}
|
|
prtsym(p);
|
|
}
|
|
else {
|
|
p->vl1 = pg->vl1; /*assign symbol value*/
|
|
}
|
|
}
|
|
|
|
/* print a symbol name for an error message*/
|
|
prtsym(ap)
|
|
char *ap;
|
|
{
|
|
|
|
register i;
|
|
register char *p;
|
|
|
|
p = ap;
|
|
for(i=0; i<SYNAMLEN; i++) {
|
|
if(*p)
|
|
putchar(*p++);
|
|
else
|
|
break;
|
|
}
|
|
putchar('\n');
|
|
}
|
|
|
|
/* pass 2 load routine:*/
|
|
/* read the file or library and do relocation */
|
|
|
|
p2load(ap)
|
|
char *ap;
|
|
{
|
|
|
|
openfile(ap); /*get the file opened using ibuf*/
|
|
if(couthd.ch_magic == LIB1MAGIC) {
|
|
libhdsize = LIB1HDSIZE;
|
|
loadlib();
|
|
}
|
|
else if(couthd.ch_magic == LIB2MAGIC) {
|
|
libhdsize = sizeof *lib2hd;
|
|
loadlib();
|
|
}
|
|
else if(couthd.ch_magic == LIB3MAGIC) {
|
|
libhdsize = LIB3HDSIZE;
|
|
loadlib();
|
|
}
|
|
else {
|
|
do2load(0); /*load a *.o file*/
|
|
addsizes();
|
|
}
|
|
close(ibuf.fildes);
|
|
close(rbuf.fildes);
|
|
}
|
|
|
|
/*make the outut file and write the header*/
|
|
|
|
makeofile()
|
|
{
|
|
|
|
long l;
|
|
|
|
if((obuf.fildes=creat(ofilname,0666,1)) < 0) {
|
|
printf(": Unable to create %s\n",ofilname);
|
|
endit(-1);
|
|
}
|
|
obuf.nunused = 512;
|
|
obuf.xfree = &obuf.buff[0];
|
|
if(Dflag|Bflag)
|
|
putw(MAGIC1,&obuf); /*data & bss bases in header*/
|
|
else
|
|
putw(MAGIC,&obuf); /*normal header*/
|
|
/* putw(0,&obuf);*/ /* pad for VAX header */
|
|
|
|
#ifdef VAX
|
|
putw(textsize.loword,&obuf);
|
|
putw(textsize.hiword,&obuf);
|
|
putw(datasize.loword,&obuf);
|
|
putw(datasize.hiword,&obuf);
|
|
putw(bsssize.loword,&obuf);
|
|
putw(bsssize.hiword,&obuf);
|
|
l = lmte - bmte;
|
|
putw(l.loword,&obuf);
|
|
putw(l.hiword,&obuf);
|
|
putw(stacksize.loword,&obuf);
|
|
putw(stacksize.hiword,&obuf);
|
|
putw(textstart.loword,&obuf);
|
|
putw(textstart.hiword,&obuf);
|
|
if(saverbits) {
|
|
putw(0,&obuf); /*relocation bits present*/
|
|
/* putw(0,&obuf); */
|
|
}
|
|
else {
|
|
putw(-1,&obuf); /*relocation bits removed*/
|
|
/* putw(0,&obuf);*/ /*pad for VAX header */
|
|
}
|
|
|
|
if(Dflag|Bflag) { /*output expanded header*/
|
|
putw(datastart.loword,&obuf);
|
|
putw(datastart.hiword,&obuf);
|
|
putw(bssstart.loword,&obuf);
|
|
putw(bssstart.hiword,&obuf);
|
|
}
|
|
#endif
|
|
|
|
#ifdef PDP11
|
|
putw(textsize.loword,&obuf);
|
|
putw(textsize.hiword,&obuf);
|
|
putw(datasize.loword,&obuf);
|
|
putw(datasize.hiword,&obuf);
|
|
putw(bsssize.loword,&obuf);
|
|
putw(bsssize.hiword,&obuf);
|
|
l = lmte - bmte;
|
|
putw(l.loword,&obuf);
|
|
putw(l.hiword,&obuf);
|
|
putw(stacksize.loword,&obuf);
|
|
putw(stacksize.hiword,&obuf);
|
|
putw(textstart.loword,&obuf);
|
|
putw(textstart.hiword,&obuf);
|
|
if(saverbits) {
|
|
putw(0,&obuf); /*relocation bits present*/
|
|
/* putw(0,&obuf); */
|
|
}
|
|
else {
|
|
putw(-1,&obuf); /*relocation bits removed*/
|
|
/* putw(0,&obuf);*/ /*pad for VAX header */
|
|
}
|
|
|
|
if(Dflag|Bflag) { /*output expanded header*/
|
|
putw(datastart.loword,&obuf);
|
|
putw(datastart.hiword,&obuf);
|
|
putw(bssstart.loword,&obuf);
|
|
putw(bssstart.hiword,&obuf);
|
|
}
|
|
#endif
|
|
|
|
#ifdef MC68000
|
|
putw(textsize.hiword,&obuf);
|
|
putw(textsize.loword,&obuf);
|
|
putw(datasize.hiword,&obuf);
|
|
putw(datasize.loword,&obuf);
|
|
putw(bsssize.hiword,&obuf);
|
|
putw(bsssize.loword,&obuf);
|
|
l = lmte - bmte;
|
|
putw(l.hiword,&obuf);
|
|
putw(l.loword,&obuf);
|
|
putw(stacksize.hiword,&obuf);
|
|
putw(stacksize.loword,&obuf);
|
|
putw(textstart.hiword,&obuf);
|
|
putw(textstart.loword,&obuf);
|
|
if(saverbits) {
|
|
putw(0,&obuf); /*relocation bits present*/
|
|
/* putw(0,&obuf); */
|
|
}
|
|
else {
|
|
putw(-1,&obuf); /*relocation bits removed*/
|
|
/* putw(0,&obuf);*/ /*pad for VAX header */
|
|
}
|
|
|
|
if(Dflag|Bflag) { /*output expanded header*/
|
|
putw(datastart.hiword,&obuf);
|
|
putw(datastart.loword,&obuf);
|
|
putw(bssstart.hiword,&obuf);
|
|
putw(bssstart.loword,&obuf);
|
|
}
|
|
#endif
|
|
|
|
tmpbinit(&tbuf); /*temp for data words*/
|
|
dafnc = TFCHAR;
|
|
if(saverbits) {
|
|
tmpbinit(&rtbuf); /*temp for text relocatin bits*/
|
|
rtfnc = TFCHAR;
|
|
tmpbinit(&rdbuf); /*temp for data relocation bits*/
|
|
rdfnc = TFCHAR;
|
|
}
|
|
}
|
|
|
|
tmpbinit(abufp)
|
|
struct buf *abufp;
|
|
{
|
|
|
|
register struct buf *bufp;
|
|
|
|
bufp = abufp;
|
|
bufp->fildes = gettempf();
|
|
bufp->nunused = BUFSIZE;
|
|
bufp->xfree = &bufp->buff[0];
|
|
}
|
|
|
|
endit(stat)
|
|
{
|
|
|
|
if(dafnc) {
|
|
TFCHAR = dafnc;
|
|
unlink(tfilname);
|
|
}
|
|
if(saverbits) {
|
|
TFCHAR = rtfnc;
|
|
unlink(tfilname);
|
|
TFCHAR = rdfnc;
|
|
unlink(tfilname);
|
|
}
|
|
exit(stat);
|
|
}
|
|
|
|
/* load files from a library. the library is open in ibuf, the*/
|
|
/* count of files to load is pointed to by libfctr, and the offset*/
|
|
/* of each file is pointed to by libptr.*/
|
|
|
|
loadlib()
|
|
{
|
|
|
|
register i,j;
|
|
register long l;
|
|
|
|
i = *libfctr++; /*# files to load from this library*/
|
|
if(i==0)
|
|
return; /*none to load*/
|
|
while(i--) { /*load the files*/
|
|
l = *libptr++; /*library offset for this file*/
|
|
lbseek(l,&ibuf); /*seek to beginning of file*/
|
|
lbseek(l,&rbuf);
|
|
rdlibhdr(); /*read the library header*/
|
|
readhdr(); /*read the file header*/
|
|
lbctr = l;
|
|
do2load(1); /*load it*/
|
|
addsizes();
|
|
}
|
|
}
|
|
|
|
/* do a long seek on buffer bp given a long file offset*/
|
|
/* last argument indicates relative or absolute seek*/
|
|
|
|
lbseek(al,bp)
|
|
long al;
|
|
struct buf *bp;
|
|
{
|
|
register long bn;
|
|
|
|
bn = (al/BLKSIZE)*BLKSIZE;
|
|
if(lseek(bp->fildes,bn,0) < 0) {
|
|
printf(": seek error on file %s\n",ifilname);
|
|
endit();
|
|
}
|
|
bp->nunused = 0; /*input buff empty*/
|
|
bp->xfree = &bp->buff[0];
|
|
for( ; bn < al; bn++ )
|
|
getc(bp);
|
|
}
|
|
|
|
/* look up the value of an external symbol given the external symbol*/
|
|
/* number. Since externals are not duplicated on the hash chains,*/
|
|
/* all externals don't have values assigned in the symbol table,*/
|
|
/* so the external name must be looked on the global chains and*/
|
|
/* the value of the matching symbol used. symptr points to the*/
|
|
/* first symbol for the current file's symbol table*/
|
|
|
|
long extval(extno)
|
|
{
|
|
|
|
register struct symtab *p;
|
|
register char *pg;
|
|
|
|
p = symptr + extno;
|
|
if((p->flags&SYXR)==0) {
|
|
return(p->vl1);
|
|
}
|
|
pack(p,lmte);
|
|
pg = lemt(girt);
|
|
if(pg == lmte)
|
|
pg = lemt(eirt); /*may be common*/
|
|
return(pg->vl1); /*return globals address*/
|
|
}
|
|
|
|
/* look up the relocation base for an external symbol. must use same*/
|
|
/* method as in extval for the same reasons (see comment above)*/
|
|
|
|
extbase(extno)
|
|
{
|
|
|
|
register struct symtab *p;
|
|
register char *pg;
|
|
register int i;
|
|
|
|
p = symptr + extno;
|
|
if((p->flags&SYXR)==0) {
|
|
pg = p;
|
|
}
|
|
else {
|
|
pack(p,lmte);
|
|
pg = lemt(girt);
|
|
if(pg == lmte)
|
|
pg = lemt(eirt); /*may be common*/
|
|
}
|
|
i = pg->flags;
|
|
if(i&SYDA)
|
|
return(DRELOC);
|
|
else if(i&SYTX)
|
|
return(TRELOC);
|
|
else if(i&SYBS)
|
|
return(BRELOC);
|
|
return(DABS);
|
|
}
|
|
|
|
/* load a file doing relocation and external resolution*/
|
|
/* libflg is set if we are loading from a library*/
|
|
|
|
|
|
do2load(libflg)
|
|
{
|
|
|
|
register i,j;
|
|
int longf;
|
|
register struct buf *p;
|
|
register struct buf *pr;
|
|
int saof;
|
|
register long tpc;
|
|
register long l;
|
|
long l1;
|
|
int wasext;
|
|
|
|
tpc = 0;
|
|
p = &obuf;
|
|
pr = &rtbuf;
|
|
saof = -1;
|
|
symptr = *firstsym++; /*beginning of this symbol table*/
|
|
l = couthd.ch_tsize + couthd.ch_dsize + couthd.ch_ssize + HDSIZE;
|
|
if(libflg)
|
|
l += lbctr + sizeof *lib2hd;
|
|
lbseek(l,&rbuf); /*long seek */
|
|
l = couthd.ch_tsize;
|
|
do2l1:
|
|
while((l -= 2) >= 0) { /*relocate the text*/
|
|
longf = 0;
|
|
i = getw(&ibuf);
|
|
j = getw(&rbuf);
|
|
tpc += 2; /*keep pc in this file*/
|
|
wasext = 0;
|
|
switch(j&7) { /*relocation bits*/
|
|
|
|
case INSABS: /*first word of instr*/
|
|
case DABS: /*data absolute*/
|
|
putw(i,p);
|
|
if(saverbits)
|
|
putw(j,pr); /*relocation bits*/
|
|
break;
|
|
|
|
case LUPPER: /*high word of long*/
|
|
l1.hiword = i;
|
|
if(saverbits)
|
|
putw(j,pr); /*upper word relocation bits*/
|
|
l1.loword = getw(&ibuf);
|
|
j = getw(&rbuf);
|
|
tpc += 2;
|
|
longf++; /*doing two words*/
|
|
l -= 2; /*count lower half*/
|
|
dorelc:
|
|
switch(j&7) {
|
|
|
|
case DABS:
|
|
if(saverbits)
|
|
putw(j,pr);
|
|
break;
|
|
case INSABS:
|
|
case LUPPER:
|
|
default:
|
|
goto do2199;
|
|
|
|
case TRELOC:
|
|
l1 += textbase;
|
|
if(saverbits)
|
|
putw(j,pr);
|
|
break;
|
|
|
|
case DRELOC:
|
|
l1 += database;
|
|
if(saverbits)
|
|
putw(j,pr);
|
|
break;
|
|
|
|
case BRELOC:
|
|
l1 += bssbase;
|
|
if(saverbits)
|
|
putw(j,pr);
|
|
break;
|
|
|
|
case EXTVAR:
|
|
wasext++;
|
|
l1 += extval(j>>3);
|
|
if(saverbits)
|
|
putw(extbase(j>>3),pr);
|
|
break;
|
|
|
|
case EXTREL:
|
|
l1 = l1+extval(j>>3)-textbase-tpc+2;
|
|
if(l1< (-32768L) || l1>0x7fff) {
|
|
printf(": relative address overflow at %lx in %s\n",
|
|
tpc,ifilname);
|
|
prextname(j>>3); /*give name referenced*/
|
|
exstat++;
|
|
}
|
|
l1.hiword = 0;
|
|
if(saverbits)
|
|
putw(DABS,pr);
|
|
goto outlowd;
|
|
|
|
}
|
|
if(ignflg==0 && longf==0 && l1&0xffff8000 && saof) {
|
|
printf(": short address overflow in %s\n",ifilname);
|
|
if(wasext)
|
|
prextname(j>>3);
|
|
exstat++;
|
|
if(libflg) {
|
|
l1 = *(libptr-1);
|
|
printf("library offset = %x\n",(int)l1.loword);
|
|
l1 = 0;
|
|
}
|
|
saof = 0;
|
|
}
|
|
if(longf)
|
|
putw(l1.hiword,p);
|
|
outlowd:
|
|
putw(l1.loword,p);
|
|
break;
|
|
|
|
case TRELOC:
|
|
case DRELOC:
|
|
case BRELOC:
|
|
case EXTVAR:
|
|
case EXTREL:
|
|
#ifdef NOMMU
|
|
l1 = *(libptr-1);
|
|
printf("library offset = %u\n",l1.loword);
|
|
printf("16-bit reloc in %s\n",ifilname);
|
|
#endif
|
|
l1 = i; /*sign extend to long like 68000*/
|
|
goto dorelc;
|
|
|
|
default:
|
|
do2199:
|
|
printf(": File format error: invalid relocation flag in %s\n",ifilname);
|
|
endit(-1);
|
|
|
|
}
|
|
}
|
|
if(p == &obuf) {
|
|
p = &tbuf; /*place to put data*/
|
|
pr = &rdbuf; /*file for data relocatin bits*/
|
|
l = couthd.ch_dsize;
|
|
goto do2l1; /*now do the data*/
|
|
}
|
|
}
|
|
|
|
/* do the final writting to the output file*/
|
|
/* copy the initialized data from the temp file to the output file*/
|
|
/* write the symbol table to the output file*/
|
|
|
|
finalwr()
|
|
{
|
|
|
|
if((textsize+textstart) != textbase) {
|
|
printf(": finalwr: text size error\n");
|
|
exstat++;
|
|
}
|
|
cpdata(&tbuf,dafnc,datasize);
|
|
osymt(); /*write the symbol table*/
|
|
if(saverbits) {
|
|
cpdata(&rtbuf,rtfnc,textsize);
|
|
cpdata(&rdbuf,rdfnc,datasize);
|
|
}
|
|
myfflush(&obuf);
|
|
if(lseek(obuf.fildes,14L,0)<0 || write(obuf.fildes,&stlen,4)!=4) {
|
|
printf(": output file write error\n");
|
|
exstat++;
|
|
}
|
|
endit(exstat);
|
|
}
|
|
|
|
/* copy the initialized data words from temp file to output file*/
|
|
cpdata(pb,fnc,size)
|
|
register struct buf *pb;
|
|
long size;
|
|
{
|
|
register j;
|
|
myfflush(pb);
|
|
close(pb->fildes);
|
|
TFCHAR = fnc;
|
|
if((fopen(tfilname,pb,1)) < 0) {
|
|
printf(": unable to reopen %s\n",tfilname);
|
|
endit(-1);
|
|
}
|
|
while (size > 0)
|
|
{
|
|
j = getw(pb); /* Fetch word from source buffer */
|
|
putw(j,&obuf);
|
|
size -= 2; /* Down by 2 bytes */
|
|
}
|
|
}
|
|
|
|
/* output symbol table to file*/
|
|
|
|
osymt()
|
|
{
|
|
|
|
register struct symtab *p;
|
|
|
|
stlen = 0;
|
|
if(sflag) /*no symbol table desired*/
|
|
return;
|
|
|
|
/* now output the symbols deleting externals*/
|
|
|
|
for(p=bmte; p<lmte; p++) {
|
|
if(p->flags&SYXR) /*external symbol*/
|
|
continue;
|
|
if((p->flags&SYGL)==0 && (p->name[0]=='L' || Xflag==0))
|
|
continue;
|
|
osyme(p);
|
|
}
|
|
}
|
|
|
|
/* output symbols in a form to be read by a debugger*/
|
|
/* call with pointer to symbol table entry*/
|
|
|
|
long ll =0;
|
|
|
|
osyme(aosypt)
|
|
struct symtab *aosypt;
|
|
{
|
|
register struct symtab *osypt;
|
|
register short *p1;
|
|
register int i;
|
|
|
|
osypt = aosypt; /*pointer to symbol table entry*/
|
|
|
|
p1 = &(osypt->name[0]);
|
|
|
|
stlen += OSTSIZE; /*one more symbol out*/
|
|
|
|
/*output symbol to loader file*/
|
|
p1 = &(osypt->name[0]);
|
|
for(i=0; i<SYNAMLEN/2; i++) { /*output symbol name*/
|
|
putw(*p1++,&obuf);
|
|
}
|
|
|
|
putw(osypt->flags,&obuf); /*output symbol flags*/
|
|
ll = osypt->vl1;
|
|
putw(ll.hiword,&obuf); /*output symbol value*/
|
|
putw(ll.loword,&obuf);
|
|
}
|
|
|
|
/*get constant given radix*/
|
|
/* this routine only works for radixes of 2, 8, 16*/
|
|
/* so as to avoid lmul because of floating point*/
|
|
long lgetnum(apc,ardx)
|
|
char *apc;
|
|
int ardx;
|
|
{
|
|
|
|
register trdx,j;
|
|
register char *pc;
|
|
register long i;
|
|
|
|
pc = apc;
|
|
if(ardx==16)
|
|
trdx = 4; /*radix as power of 2*/
|
|
else if(ardx==8)
|
|
trdx = 3;
|
|
else if(ardx==2)
|
|
trdx = 1;
|
|
else
|
|
return(0);
|
|
i=0;
|
|
while(1) {
|
|
j = *pc++;
|
|
if(j>='0' && j<='9')
|
|
j -= '0';
|
|
else
|
|
if(j>='a' && j<='f')
|
|
j = j-'a'+10;
|
|
else if(j>='A' && j<='F')
|
|
j = j-'A'+10;
|
|
else
|
|
break; /*not valid numeric char*/
|
|
if(j>=0 && j<ardx)
|
|
i = (i<<trdx)+j;
|
|
else
|
|
break;
|
|
}
|
|
return(i);
|
|
}
|
|
|
|
/* look for and define if found etext, edata, and end*/
|
|
|
|
spendsym(ap)
|
|
struct symtab *ap;
|
|
{
|
|
|
|
register struct symtab *p;
|
|
|
|
p = ap;
|
|
if(eqstr(etexstr,&p->name[0])) {
|
|
etextptr = p;
|
|
return(1);
|
|
}
|
|
if(eqstr(edatstr,&p->name[0])) {
|
|
edataptr = p;
|
|
return(1);
|
|
}
|
|
if(eqstr(eendstr,&p->name[0])) {
|
|
endptr = p;
|
|
return(1);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
/* test two symbol names for equality*/
|
|
|
|
eqstr(ap1,ap2)
|
|
char *ap1, *ap2;
|
|
{
|
|
|
|
register char *p1, *p2;
|
|
register int i;
|
|
|
|
p1 = ap1;
|
|
p2 = ap2;
|
|
for(i=0; i<SYNAMLEN; i++) {
|
|
if(*p1++ != *p2++) {
|
|
return(0);
|
|
}
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
/* print an error message giving an external name*/
|
|
|
|
prextname(extno)
|
|
{
|
|
|
|
register struct symtab *p;
|
|
register char *pc;
|
|
|
|
p = symptr + extno;
|
|
printf(": external name: ");
|
|
for(pc = &p->name[0]; pc < &p->name[SYNAMLEN]; pc++) {
|
|
if(*pc == 0)
|
|
break;
|
|
putchar(*pc);
|
|
}
|
|
putchar('\n');
|
|
}
|
|
|