mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 16:34:07 +00:00
1223 lines
27 KiB
C
1223 lines
27 KiB
C
/*
|
|
Copyright 1982, 1983
|
|
Alcyon Corporation
|
|
8716 Production Ave.
|
|
San Diego, Ca. 92121
|
|
*/
|
|
|
|
char *version = "@(#)main.c 1.7 12/28/83";
|
|
|
|
#include "lo68.h"
|
|
#ifndef DECC
|
|
# include <signal.h>
|
|
#else
|
|
# include "Isignal"
|
|
#endif
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
|
|
#ifdef MC68000
|
|
# define LIBINDEX 8
|
|
char libname[] = "/lib/lib7.a"; /*default library name*/
|
|
char libxname[] = "/lib/lib "; /*library name*/
|
|
char *ofilname = "a.out";
|
|
char shortexit[] = "/lib/exit.o";
|
|
#else
|
|
# ifndef VMS
|
|
# define LIBINDEX 18
|
|
char libname[] = "/usr/local/lib/lib7.a"; /*default library name*/
|
|
char libxname[] = "/usr/local/lib/lib "; /*library name*/
|
|
char *ofilname = "c.out"; /*output file name*/
|
|
char shortexit[] = "/usr/local/lib/shortexit.o";
|
|
# else
|
|
# define LIBINDEX 8
|
|
char libname[] = "clib:lib7.a";
|
|
char libxname[] = "clib:lib ";
|
|
char *ofilname = "c.out"; /*output file name*/
|
|
char shortexit[] = "clib:exit.o";
|
|
# endif
|
|
#endif
|
|
|
|
#ifndef VMS
|
|
# define FILSEP '/'
|
|
# define NAMELOC 10 /* location in tfilname where letter is */
|
|
char tfilname[18] = "/tmp/_ldtmaXXXXX"; /*first temp file name*/
|
|
int shortfildes; /* file designator for short exit */
|
|
#else
|
|
# define FILSEP ']'
|
|
# define NAMELOC 5
|
|
char tfilname[18] = "wk:tmaXXXXX";
|
|
|
|
/**
|
|
* declarations for fix to sbrk problem. On the vax when files are opened
|
|
* between calls to sbrk, the allocated memory is not contiguous. Therefore
|
|
* all the input files are concatenated into one file which is opened prior
|
|
* to the calls to sbrk. This process creates a large overhead in disk I/O,
|
|
* but the structure of the program requires that the memory for the symbol
|
|
* table be continuous. It would be preferable to find a faster solution
|
|
* to the problem.
|
|
**/
|
|
int openfilloc[NFILE]; /* pointers to beginning of the input files */
|
|
int fdp = 0; /* index to openfilloc */
|
|
char *pt, *lpin;
|
|
#endif
|
|
|
|
long longseek();
|
|
|
|
char etexstr[] = "_etext\0\0";
|
|
char edatstr[] = "_edata\0\0";
|
|
char eendstr[] = "_end\0\0\0\0";
|
|
int ignflg;
|
|
int debug;
|
|
int exstat;
|
|
int mmuflag;
|
|
int errno; /* system call error number */
|
|
|
|
main(argc,argv)
|
|
int argc;
|
|
char **argv;
|
|
{
|
|
register char **p, *pc, *p1;
|
|
register i, j;
|
|
|
|
if( signal(SIGINT,SIG_IGN) != SIG_IGN )
|
|
signal(SIGINT,endit);
|
|
if( signal(SIGQUIT,SIG_IGN) != SIG_IGN )
|
|
signal(SIGQUIT,endit);
|
|
if( signal(SIGHUP,SIG_IGN) != SIG_IGN )
|
|
signal(SIGHUP,endit);
|
|
signal(SIGTERM,endit);
|
|
#ifdef MC68000
|
|
sysinfo(0,&mmuflag);
|
|
#else
|
|
mmuflag = 1;
|
|
#endif
|
|
#ifndef VMS
|
|
/* init the symbol table after all the files have been opened on the vax */
|
|
intsytab(); /*initialize the symbol table*/
|
|
#endif
|
|
firstsym = fsymp;
|
|
libfctr = lbfictr;
|
|
libptr = lbfioff;
|
|
if(argc <= 1) {
|
|
usage:
|
|
printf(": Invalid lo68 argument list\n");
|
|
endit(-1);
|
|
}
|
|
|
|
#ifdef VMS
|
|
/* open all files */
|
|
p = argv+1;
|
|
for (i=1; i < argc; i++) {
|
|
pc = *p++;
|
|
if(*pc == '-') {
|
|
switch(*++pc) {
|
|
case 'l':
|
|
pc--;
|
|
break;
|
|
case 'o':
|
|
p++;
|
|
i++;
|
|
case 'i':
|
|
case 'n':
|
|
case 's':
|
|
case 'X':
|
|
case 'Z':
|
|
case 'I':
|
|
case 'U':
|
|
case 'T':
|
|
case 'D':
|
|
case 'B':
|
|
case 'r':
|
|
case 'v':
|
|
continue;
|
|
}
|
|
}
|
|
|
|
pt = pc;
|
|
if (*pt == '-' && *++pt == 'l') {
|
|
if(*++pt) {
|
|
for(lpin = &libxname[LIBINDEX]; *pt; )
|
|
*lpin++ = *pt++;
|
|
*lpin++ = '.';
|
|
*lpin++ = 'a';
|
|
pt = libxname;
|
|
}
|
|
else /* else default library name -- /lib/lib7.a */
|
|
pt = libname;
|
|
}
|
|
else
|
|
pt = pc;
|
|
if ((openfilloc[fdp++]=open(pt,0)) < 0) {
|
|
printf("unable to open %s\n",pt);
|
|
printf("probably too many simultaneous opens for this system\n");
|
|
endit(-1);
|
|
}
|
|
}
|
|
fdp = 0;
|
|
intsytab(); /* initialize the symbol table */
|
|
#endif
|
|
p = argv+1;
|
|
if (!mmuflag)
|
|
saverbits++; /* relocation bits forced on nommu sys */
|
|
for(i=1; i<argc; i++) { /*process each argument*/
|
|
pc = *p++;
|
|
if(*pc == '-') {
|
|
switch(*++pc) {
|
|
|
|
case 'l': /*library*/
|
|
pc--;
|
|
break;
|
|
|
|
case 'o': /*output file name*/
|
|
ofilname = *p++;/*next arg is file name*/
|
|
i++;
|
|
continue;
|
|
|
|
case 'n': /*shared text*/
|
|
shtext = DEFSHTEXT;
|
|
if(*++pc == '2') /* mod 2k on shared text */
|
|
shtext = TWOKSHT;
|
|
else if( *pc == '4' )
|
|
shtext = FOURKSHT;
|
|
continue;
|
|
|
|
case 'i': /* i & d split*/
|
|
isplit++;
|
|
continue;
|
|
|
|
case 's': /*don't output symbol table*/
|
|
sflag++;
|
|
continue;
|
|
|
|
case 'X': /*keep local symbols except L**/
|
|
Xflag++;
|
|
continue;
|
|
|
|
case 'Z': /*offset the text base for standaone pgm*/
|
|
case 'T': /*another name for same flag*/
|
|
Zflag++;
|
|
textstart = lgetnum(++pc,16); /*get a long hex number*/
|
|
textbase = textstart;
|
|
continue;
|
|
|
|
case 'D': /*data segment base*/
|
|
Dflag++;
|
|
datastart = lgetnum(++pc,16);
|
|
continue;
|
|
|
|
case 'B': /*bss segment base*/
|
|
Bflag++;
|
|
bssstart = lgetnum(++pc,16);
|
|
continue;
|
|
|
|
case 'I': /*ignore 16-bit addr overflow*/
|
|
ignflg++;
|
|
continue;
|
|
|
|
case 'd':
|
|
debug++; /*[vlh] 4.2 debugging turned on... */
|
|
continue;
|
|
|
|
case 'r':
|
|
saverbits++; /*put relocation bits on c.out*/
|
|
continue;
|
|
|
|
case 'U': /*initial undefined symbol*/
|
|
p1 = lmte;
|
|
pc++;
|
|
for(j=SYNAMLEN; --j != -1; ) { /* 2 may 83 */
|
|
*p1++ = *pc;
|
|
if(*pc)
|
|
pc++;
|
|
}
|
|
((struct symtab *)lmte)->flags = SYXR; /*extern reference*/
|
|
addsym(0); /*put into symbol table*/
|
|
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++;
|
|
if(*pc == '-') {
|
|
switch(*++pc) {
|
|
|
|
case 'l': /*library*/
|
|
pc--;
|
|
break;
|
|
|
|
case 'o': /*output file name*/
|
|
p++; /*skip file name*/
|
|
i++;
|
|
continue;
|
|
|
|
case 'i':
|
|
case 'n':
|
|
case 's': /*don't output symbol table*/
|
|
case 'X':
|
|
case 'Z':
|
|
case 'I':
|
|
case 'U':
|
|
case 'T':
|
|
case 'D':
|
|
case 'B':
|
|
case 'r':
|
|
case 'v':
|
|
continue;
|
|
|
|
}
|
|
}
|
|
p2load(pc); /*read file or library*/
|
|
}
|
|
finalwr(); /*finish output file*/
|
|
}
|
|
|
|
/*
|
|
* 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
|
|
*/
|
|
p1load(ap)
|
|
char *ap;
|
|
{
|
|
#ifndef VMS
|
|
openfile(ap); /*get the file opened using ibuf*/
|
|
#else
|
|
vsetfile(ap); /* handles combined file */
|
|
#endif
|
|
#ifdef DEBUG
|
|
printf("Processing [%s]\n",ap);
|
|
#endif
|
|
if(couthd.ch_magic == LIBMAGIC) /*library*/
|
|
searchlib();
|
|
else {
|
|
do1load(0); /*load a *.o file*/
|
|
firstsym++;
|
|
addsizes();
|
|
}
|
|
close(ibuf.fd);
|
|
}
|
|
|
|
/**
|
|
* search a library for files to include. include an entry only
|
|
* if it has a global symbol which matches an external.
|
|
**/
|
|
long lbctr;
|
|
long libfilsize;
|
|
searchlib()
|
|
{
|
|
/* Don't worry about shortsearch on vax/vms */
|
|
#ifndef VMS
|
|
if(shortlflg || shortsearch()) /*optimize no lib routines to load*/
|
|
return;
|
|
#endif
|
|
lbctr = 2;
|
|
*libfctr = 0; /*no files from this library yet*/
|
|
while(rdlibhdr()) { /*read library file header*/
|
|
savsymtab(); /*save current state of symbol table*/
|
|
extmatch = 0;
|
|
noload = 0;
|
|
ifilname = libhd.lfname;
|
|
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;
|
|
longseek(lbctr,&ibuf); /*goto begin of next lib entry*/
|
|
}
|
|
libfctr++; /*point to next library file counter*/
|
|
}
|
|
|
|
/*read a library file header*/
|
|
rdlibhdr()
|
|
{
|
|
if (getarhd(&ibuf,&libhd) == -1) /* 4.1 new library routine */
|
|
return(0); /*end of file*/
|
|
libhd.lmodti = 0; /* provide end of string delim for name */
|
|
libfilsize = libhd.lfsize; /* copy out file size */
|
|
return(1);
|
|
}
|
|
|
|
/* open the file pointed to by ap*/
|
|
/* check for the -lx type library spec*/
|
|
openfile(ap)
|
|
char *ap;
|
|
{
|
|
register char *p, *lp;
|
|
#ifdef VAX11
|
|
unsigned short omagic;
|
|
#else
|
|
int omagic;
|
|
#endif
|
|
|
|
p = ap;
|
|
if(*p=='-' && *++p=='l') {
|
|
if(*++p) { /* 13 apr 83, multi-char libraries */
|
|
for (lp = &libxname[LIBINDEX]; *p; )
|
|
*lp++ = *p++;
|
|
*lp++ = '.';
|
|
*lp++ = 'a';
|
|
*lp = 0;
|
|
p = libxname;
|
|
}
|
|
else /* else default library name -- /lib/lib7.a */
|
|
p = libname;
|
|
}
|
|
else
|
|
p = ap;
|
|
if((ibuf.fd=open(p,0)) < 0) {
|
|
printf(": unable to open %s\n",p);
|
|
endit(-1);
|
|
}
|
|
ifilname = p; /*point to current file name for error msgs*/
|
|
if(read(ibuf.fd,&omagic.hibyte,1)!=1 || read(ibuf.fd,&omagic.lobyte,1)!=1) {
|
|
printf(": read error on file: %s\n",ifilname);
|
|
endit(-1);
|
|
}
|
|
couthd.ch_magic = omagic;
|
|
ibuf.cc = 0;
|
|
if (omagic != LIBMAGIC) {
|
|
seek(ibuf.fd,0,0); /* was lseek(ibuf.fd,0L,0); */
|
|
readhdr(); /*read file header*/
|
|
}
|
|
if(pass2) { /*need file descrptr for reloc bits*/
|
|
rbuf.fd = open(p,0);
|
|
rbuf.cc = 0;
|
|
}
|
|
}
|
|
|
|
#ifdef VMS
|
|
/**
|
|
* vsetfile - make usable the file pointed to by openfilloc[fdp]
|
|
* called from p1load only.
|
|
**/
|
|
vsetfile(ap)
|
|
char *ap;
|
|
{
|
|
unsigned short omagic;
|
|
|
|
ibuf.fd = openfilloc[fdp++];
|
|
ibuf.cc = 0;
|
|
ifilname = ap; /* point to current file name for error messages */
|
|
if(read(ibuf.fd,&omagic.hibyte,1)!=1 || read(ibuf.fd,&omagic.lobyte,1)!=1) {
|
|
printf(": read error on file: %s\n",ifilname);
|
|
endit(-1);
|
|
}
|
|
couthd.ch_magic = omagic;
|
|
ibuf.cc = 0;
|
|
if (omagic != LIBMAGIC) {
|
|
seek(ibuf.fd,0,0); /* was lseek(ibuf.fd,0L,0); */
|
|
readhdr();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* read the header of the input file*/
|
|
readhdr()
|
|
{
|
|
if (getchd(&ibuf,&couthd) == -1) { /* 4.1 new library routine */
|
|
printf(": error reading header: %s\n",ifilname);
|
|
endit(-1);
|
|
}
|
|
if(couthd.ch_magic != EX_MAGIC) {
|
|
printf(": file format error: %s %o\n",ifilname,(int)couthd.ch_magic);
|
|
endit(-1);
|
|
}
|
|
if(couthd.ch_rlbflg) {
|
|
printf(": no relocation bits: %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)
|
|
int libflg;
|
|
{
|
|
register long i, l, ret;
|
|
|
|
addfnsym(); /* put file name into symbol table */
|
|
*firstsym = lmte; /*remember where this symbol table starts*/
|
|
l = couthd.ch_tsize + couthd.ch_dsize + HDSIZE;
|
|
if(libflg)
|
|
l += lbctr + LIBHDSIZE;
|
|
ret = longseek(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;
|
|
}
|
|
}
|
|
|
|
/* put file name into symbol table */
|
|
|
|
addfnsym()
|
|
{
|
|
|
|
register char *p,*q;
|
|
register int i;
|
|
|
|
p = q = ifilname;
|
|
while(*p) {
|
|
if(*p == FILSEP) /* directory delimiter */
|
|
q = p+1;
|
|
p++;
|
|
}
|
|
p = lmte;
|
|
for(i=0; i<SYNAMLEN; i++) {
|
|
if(*q) {
|
|
*p++ = *q++;
|
|
}
|
|
else {
|
|
*p++ = '\0';
|
|
}
|
|
}
|
|
lmte->flags = SYFN|SYGL|SYTX; /* file name bit */
|
|
lmte->vl1 = textbase;
|
|
addmte();
|
|
}
|
|
|
|
/* get a temp file for the intermediate text*/
|
|
gettempf()
|
|
{
|
|
register short i,j;
|
|
struct stat stbuf;
|
|
|
|
while( mktemp(tfilname) ) {
|
|
#ifndef VMS
|
|
if( stat(tfilname,&stbuf) >= 0 )
|
|
continue; /* this file exists */
|
|
#endif
|
|
if( (j = creat(tfilname,0600)) >= 0 )
|
|
return(j);
|
|
else if (debug)
|
|
printf("couldn't creat, return value %d\n",j);
|
|
}
|
|
printf(": Unable to open temporary file\n");
|
|
endit(-1);
|
|
}
|
|
|
|
/* update the relocation counters with the sizes in the header*/
|
|
addsizes()
|
|
{
|
|
textbase = textbase + couthd.ch_tsize;
|
|
database = database + couthd.ch_dsize;
|
|
bssbase = bssbase + couthd.ch_bsize;
|
|
}
|
|
|
|
/* 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*/
|
|
if(((struct symtab *)p1)->flags&SYTX) { /* linking to text symbol */
|
|
printf("text/data symbol name conflict: %s\n",p1);
|
|
}
|
|
((struct symtab *)ap)->vl1 = ((struct symtab *)p1)->vl1;
|
|
return;
|
|
}
|
|
l = 0;
|
|
lemt(eirt);
|
|
do {
|
|
if(((struct symtab *)p)->vl1 > l)
|
|
l = ((struct symtab *)p)->vl1;
|
|
((struct symtab *)p)->vl1 = 0;
|
|
} while((p = nextsy(((struct symtab *)p)->tlnk)) != lmte);
|
|
/*now make a global entry for this common block*/
|
|
((struct symtab *)p)->flags = SYDF|SYGL|SYBS;
|
|
((struct symtab *)p)->vl1 = bssbase + bsssize;
|
|
/*copy address to first external*/
|
|
((struct symtab *)ap)->vl1 = ((struct symtab *)p)->vl1;
|
|
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(((struct symtab *)p)->tlnk)) != lmte) {
|
|
if(((struct symtab *)p)->vl1) { /*common*/
|
|
asgncomn(ap);
|
|
return;
|
|
}
|
|
}
|
|
if(spendsym(ap)) /*end, etext or edata*/
|
|
return;
|
|
if(undflg==0) {
|
|
printf(": Undefined:\n");
|
|
undflg++;
|
|
exstat++;
|
|
}
|
|
prtsym(p);
|
|
}
|
|
else /*assign symbol value*/
|
|
((struct symtab *)p)->vl1 = ((struct symtab *)pg)->vl1;
|
|
|
|
}
|
|
|
|
/* 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 == LIBMAGIC)
|
|
loadlib();
|
|
else {
|
|
do2load(0); /*load a *.o file*/
|
|
addsizes();
|
|
}
|
|
close(ibuf.fd);
|
|
close(rbuf.fd);
|
|
}
|
|
|
|
/*make the outut file and write the header*/
|
|
makeofile() /* 4.1 restructured */
|
|
{
|
|
register struct hdr2 *lb;
|
|
struct hdr2 olibhd;
|
|
|
|
if( (obuf.fd = creat(ofilname,0666)) < 0 ) { /* only make exec if all ok */
|
|
printf(": Unable to create %s\n",ofilname);
|
|
endit(-1);
|
|
}
|
|
obuf.cc = BSIZE;
|
|
obuf.cp = &obuf.cbuf[0];
|
|
lb = &olibhd;
|
|
if(Zflag|Dflag|Bflag) { /*expanded header: data & bss bases in header*/
|
|
lb->ch_magic = (unsigned short)EX_ABMAGIC;
|
|
lb->ch_dstart = datastart;
|
|
lb->ch_bstart = bssstart;
|
|
}
|
|
else if (isplit) /* i & d split */
|
|
lb->ch_magic = (unsigned short)EX_IDMAGIC;
|
|
else if(!shtext) /* standard */
|
|
lb->ch_magic = (unsigned short)EX_MAGIC;
|
|
else if (shtext == -1) /* 2k boundary */
|
|
lb->ch_magic = (unsigned short)EX_2KSTXT;
|
|
else /* 4k boundary */
|
|
lb->ch_magic = (unsigned short)EX_4KSTXT;
|
|
lb->ch_tsize = textsize;
|
|
lb->ch_dsize = datasize;
|
|
lb->ch_bsize = bsssize;
|
|
lb->ch_ssize = (long)(lmte - bmte);
|
|
lb->ch_stksize = stacksize;
|
|
lb->ch_entry = textstart;
|
|
if (saverbits) /* bits present ?? */
|
|
lb->ch_rlbflg = 0;
|
|
else
|
|
lb->ch_rlbflg = -1;
|
|
/* printf("tsz %d dsz %d bsz %d ssz %d bits %d\n",lb->ch_tsize,lb->ch_dsize,lb->ch_bsize,lb->ch_ssize,lb->ch_rlbflg); */
|
|
putchd(&obuf,lb);
|
|
|
|
tmpbinit(&tbuf); /*temp for data words*/
|
|
dafnc = tfilname[NAMELOC];
|
|
if(saverbits) {
|
|
tmpbinit(&rtbuf); /*temp for text relocation bits*/
|
|
rtfnc = tfilname[NAMELOC];
|
|
tmpbinit(&rdbuf); /*temp for data relocation bits*/
|
|
rdfnc = tfilname[NAMELOC];
|
|
}
|
|
}
|
|
|
|
tmpbinit(abufp)
|
|
struct iob *abufp;
|
|
{
|
|
register struct iob *bufp;
|
|
|
|
bufp = abufp;
|
|
bufp->fd = gettempf();
|
|
bufp->cc = BSIZE;
|
|
bufp->cp = &bufp->cbuf[0];
|
|
}
|
|
|
|
endit(xstat)
|
|
int xstat;
|
|
{
|
|
if(dafnc) {
|
|
tfilname[NAMELOC] = dafnc;
|
|
unlink(tfilname);
|
|
}
|
|
if(saverbits) {
|
|
tfilname[NAMELOC] = rtfnc;
|
|
unlink(tfilname);
|
|
tfilname[NAMELOC] = rdfnc;
|
|
unlink(tfilname);
|
|
}
|
|
if( xstat == 0 )
|
|
chmod(ofilname,0777); /* if all ok, make it executable [jws] */
|
|
#ifdef VMS
|
|
else
|
|
printf("load failed - status = %x\n",xstat);
|
|
#endif
|
|
exit(xstat);
|
|
}
|
|
|
|
/*
|
|
* 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 int i,j;
|
|
register long l;
|
|
|
|
#ifndef VMS
|
|
/* don't short load on a vms vax */
|
|
if(shortlflg) {
|
|
if(shortlflg == 1) /*need to load short exit*/
|
|
shortload();
|
|
shortlflg++;
|
|
return;
|
|
}
|
|
#endif
|
|
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*/
|
|
longseek(l,&ibuf); /*seek to beginning of file*/
|
|
longseek(l,&rbuf);
|
|
if (!rdlibhdr()) /*read the library header*/
|
|
printf("Bad Library Header....\n");
|
|
readhdr(); /*read the file header*/
|
|
lbctr = l;
|
|
do2load(1); /*load it*/
|
|
addsizes();
|
|
}
|
|
}
|
|
|
|
#ifndef PDP11
|
|
/* do a long seek on buffer bp given a long file offset*/
|
|
long
|
|
longseek(al,bp)
|
|
long al;
|
|
struct iob *bp;
|
|
{
|
|
long ret;
|
|
|
|
ret = lseek(bp->fd,al,0);
|
|
bp->cc = 0; /*input buffer empty*/
|
|
bp->cp = &bp->cbuf;
|
|
return(ret);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* look up the value of an external symbol given the external symbol
|
|
* number. Since externals are duplicated on the external hash chains,
|
|
* all external entries 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)
|
|
int 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(((struct symtab *)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)
|
|
int extno;
|
|
{
|
|
register struct symtab *p;
|
|
register char *pg;
|
|
register int i;
|
|
|
|
p = symptr + extno;
|
|
if((p->flags&SYXR)==0)
|
|
pg = (char *)p;
|
|
else {
|
|
pack(p,lmte);
|
|
pg = lemt(girt);
|
|
if(pg == lmte)
|
|
pg = lemt(eirt); /*may be common*/
|
|
}
|
|
i = ((struct symtab *)pg)->flags;
|
|
return((i&SYDA)? DRELOC : (i&SYTX)? TRELOC : (i&SYBS)? BRELOC : DABS);
|
|
}
|
|
|
|
/* load a file doing relocation and external resolution*/
|
|
/* libflg is set if we are loading from a library*/
|
|
do2load(libflg)
|
|
int libflg;
|
|
{
|
|
int longf;
|
|
short i, j;
|
|
register struct iob *p;
|
|
register struct iob *pr;
|
|
int saof, wasext;
|
|
short word;
|
|
register long tpc, l;
|
|
long l1;
|
|
|
|
tpc = 0;
|
|
p = &obuf;
|
|
pr = &rtbuf;
|
|
saof = -1;
|
|
symptr = (struct symtab *)*firstsym++; /*beginning of this symbol table*/
|
|
l = couthd.ch_tsize + couthd.ch_dsize + couthd.ch_ssize + HDSIZE;
|
|
if(libflg)
|
|
l += lbctr+LIBHDSIZE;
|
|
longseek(l,&rbuf); /*long seek */
|
|
l = couthd.ch_tsize;
|
|
do2l1:
|
|
while((l -= 2) >= 0) { /*relocate the text*/
|
|
longf = 0;
|
|
lgetw(&i,&ibuf); /*text or data word */
|
|
lgetw(&j,&rbuf); /*relocation word*/
|
|
tpc += 2; /*keep pc in this file*/
|
|
wasext = 0;
|
|
switch(j&7) { /*relocation bits*/
|
|
|
|
case INSABS: /*first word of instr*/
|
|
case DABS: /*data absolute*/
|
|
lputw(&i,p);
|
|
if(saverbits)
|
|
lputw(&j,pr); /*relocation bits*/
|
|
break;
|
|
|
|
case LUPPER: /*high word of long*/
|
|
l1.hiword = i;
|
|
if(saverbits)
|
|
lputw(&j,pr); /*upper word relocation bits*/
|
|
lgetw(&l1.loword,&ibuf);
|
|
lgetw(&j,&rbuf);
|
|
tpc += 2;
|
|
longf++; /*doing two words*/
|
|
l -= 2; /*count lower half*/
|
|
dorelc:
|
|
switch(j&7) {
|
|
|
|
case DABS:
|
|
if(saverbits)
|
|
lputw(&j,pr);
|
|
break;
|
|
|
|
case INSABS:
|
|
case LUPPER:
|
|
default:
|
|
goto do2l99;
|
|
|
|
case TRELOC:
|
|
l1 += textbase;
|
|
if(saverbits)
|
|
lputw(&j,pr);
|
|
break;
|
|
|
|
case DRELOC:
|
|
l1 += database;
|
|
if(saverbits)
|
|
lputw(&j,pr);
|
|
break;
|
|
|
|
case BRELOC:
|
|
l1 += bssbase;
|
|
if(saverbits)
|
|
lputw(&j,pr);
|
|
break;
|
|
|
|
case EXTVAR:
|
|
wasext++;
|
|
l1 += extval((int)j>>3);
|
|
if(saverbits) {
|
|
word = extbase((int)j>>3);
|
|
lputw(&word,pr);
|
|
}
|
|
break;
|
|
|
|
case EXTREL:
|
|
l1 = l1+extval((int)j>>3)-textbase-tpc+2;
|
|
if(l1<0xffff8000 || l1>0x7fff) {
|
|
printf(": relative address overflow at %lx in %s\n",
|
|
tpc,ifilname);
|
|
prextname((int)j>>3); /*give name referenced*/
|
|
exstat++;
|
|
}
|
|
l1.hiword = 0;
|
|
if(saverbits) {
|
|
word = DABS;
|
|
lputw(&word,pr);
|
|
}
|
|
goto outlowd;
|
|
|
|
}
|
|
if(ignflg==0 && longf==0 && l1&0xffff8000 && saof) {
|
|
printf(": short address overflow in %s\n",ifilname);
|
|
if(wasext)
|
|
prextname((int)j>>3);
|
|
exstat++;
|
|
if(libflg) {
|
|
l1 = *(libptr-1);
|
|
printf("library offset = %u\n",(int)l1.loword);
|
|
l1 = 0;
|
|
}
|
|
saof = 0;
|
|
}
|
|
if(longf)
|
|
lputw(&l1.hiword,p);
|
|
outlowd:
|
|
lputw(&l1.loword,p);
|
|
break;
|
|
|
|
case TRELOC:
|
|
case DRELOC:
|
|
case BRELOC:
|
|
case EXTVAR:
|
|
case EXTREL:
|
|
l1 = *(libptr-1);
|
|
if (!mmuflag) {
|
|
printf("library offset = %u\n",(int)l1.loword);
|
|
printf("16-bit reloc in %s\n",ifilname);
|
|
}
|
|
l1 = i; /*sign extend to long like 68000*/
|
|
goto dorelc;
|
|
|
|
default:
|
|
do2l99:
|
|
printf(": lo68: invalid relocation flag in %s\n",ifilname);
|
|
endit(-1);
|
|
|
|
}
|
|
}
|
|
if(p == &obuf) {
|
|
p = &tbuf; /*place to put data*/
|
|
pr = &rdbuf; /*file for data relocation 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);
|
|
osymt(); /*write the symbol table*/
|
|
if(saverbits) {
|
|
cpdata(&rtbuf,rtfnc);
|
|
cpdata(&rdbuf,rdfnc);
|
|
}
|
|
fflush(&obuf);
|
|
/* longseek was: lseek(obuf.fd,14L,0); */
|
|
if( longseek(14L,&obuf) < 0 || lwritel(obuf.fd,&stlen) == -1 ) {
|
|
printf(": output file write error\n");
|
|
exstat++;
|
|
}
|
|
endit(exstat);
|
|
}
|
|
|
|
/* copy the initialized data words from temp file to output file*/
|
|
cpdata(pb,fnc)
|
|
struct iob *pb;
|
|
char fnc;
|
|
{
|
|
register int i,cfn;
|
|
|
|
fflush(&obuf);
|
|
fflush(pb);
|
|
close(pb->fd);
|
|
tfilname[NAMELOC] = fnc;
|
|
if((cfn=open(tfilname,0)) < 0) {
|
|
printf(": unable to reopen %s\n",tfilname);
|
|
#ifdef DEBUG
|
|
printf(": errno=%o\n",errno);
|
|
#endif
|
|
endit(-1);
|
|
}
|
|
while((i=read(cfn,&pb->cbuf[0],BSIZE)) > 0) {
|
|
if(write(obuf.fd,&pb->cbuf[0],i) != i) {
|
|
printf(": output file write error\n");
|
|
endit(-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*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 = SYNAMLEN; --i != -1; ) /* 2 may 83 */
|
|
if(*p1++ != *p2++)
|
|
return(0);
|
|
return(1);
|
|
}
|
|
|
|
/* print an error message giving an external name*/
|
|
prextname(extno)
|
|
int 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');
|
|
}
|
|
|
|
#ifndef VMS
|
|
/**
|
|
* check to see if we only need to load exit -- no other
|
|
* library routines needed. if so, load exit only and
|
|
* return 1 else return 0.
|
|
**/
|
|
shortsearch()
|
|
{
|
|
register char *p;
|
|
register char **sx1, **sx2;
|
|
register int i;
|
|
|
|
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 = (char **)*sx2; /*first entry on this chain*/
|
|
while(1) {
|
|
if(((struct symtab *)sx2)->vl1 == 0)
|
|
if(eqstr("_exit\0\0\0",sx2)==0&&eqstr("_main\0\0\0",sx2)==0)
|
|
return(0);
|
|
p = (char *)sx2;
|
|
if(p == *sx1) /*end of chain*/
|
|
break;
|
|
sx2 = (char **)((struct symtab *)sx2)->tlnk; /*next entry in chain*/
|
|
}
|
|
}
|
|
/* found only exit undefined*/
|
|
if((i=open(shortexit,0)) < 0)
|
|
return(0); /*cant open short exit file*/
|
|
close(i);
|
|
close(ibuf.fd); /*close library -- dont need to scan it*/
|
|
openfile(shortexit);
|
|
do1load(0); /*load short exit*/
|
|
firstsym++;
|
|
addsizes();
|
|
shortlflg++;
|
|
return(1);
|
|
}
|
|
|
|
/* load the short exit routine*/
|
|
shortload()
|
|
{
|
|
close(ibuf.fd); /*dont need library*/
|
|
close(rbuf.fd);
|
|
openfile(shortexit);
|
|
do2load(0);
|
|
addsizes();
|
|
}
|
|
#endif
|
|
|
|
#ifndef MC68000
|
|
static char _uniqlet = 'a';
|
|
|
|
char *
|
|
mktemp(ap)
|
|
char *ap;
|
|
{
|
|
register char *p;
|
|
register int i,j;
|
|
|
|
p = ap;
|
|
i = getpid(); /* process id */
|
|
|
|
while( *p )
|
|
p++;
|
|
|
|
for(j = 5; --j != -1; ) {
|
|
*--p = ((i&7) + '0');
|
|
i =>> 3;
|
|
}
|
|
*--p = _uniqlet;
|
|
|
|
_uniqlet++;
|
|
if( _uniqlet > 'z' )
|
|
_uniqlet = 'A';
|
|
if( _uniqlet == 'Z' )
|
|
return(0);
|
|
return(ap);
|
|
}
|
|
#endif
|
|
|
|
#ifdef PDP11
|
|
/**
|
|
* longseek - do a long seek on buffer bp, given a long
|
|
* file offset.
|
|
**/
|
|
long
|
|
longseek(al,bp)
|
|
long al;
|
|
struct buf *bp;
|
|
{
|
|
long l, ret;
|
|
register short b,o;
|
|
|
|
l = al>>9;
|
|
b = l.loword; /* block # */
|
|
o = al.loword&0777; /* offset in block */
|
|
if((ret=seek(bp->fd,b,3)) < 0) { /* seek to block */
|
|
printf(": seek error on file %s\n",ifilname);
|
|
endit(-1);
|
|
}
|
|
if((l=seek(bp->fd,o,1)) < 0) { /* do offset */
|
|
printf(": seek error on file %s\n",ifilname);
|
|
endit(-1);
|
|
}
|
|
bp->cc = 0; /* input buff empty */
|
|
bp->cp = &bp->cbuf;
|
|
ret = (b*512) + o;
|
|
return(ret);
|
|
}
|
|
#endif
|