Ausam/sys/conf/source/sysld.c
#
/*
* special link editor for pdp 11/40 systems
* jeff rottman
*/
#include <param.h>
#define SIZAUT 8
#define CALLR0 04037
#define SIGINT 2
#define ARCMAGIC 0177545
#define FMAGIC 0407
#define NMAGIC 0410
#define IMAGIC 0411
#define KW 2048
#define EXTERN 040
#define UNDEF 00
#define ABS 01
#define TEXT 02
#define DATA 03
#define BSS 04
#define COMM 05 /* internal use only */
#define RABS 00
#define RTEXT 02
#define RDATA 04
#define RBSS 06
#define REXT 010
#define RELFLG 01
#define NROUT 256
#define NSYM 807
#define NSYMPR 500
#define NAUT 256 /* possible number of autoloads: 256 max */
#define NSEG 256 /* possible number of segments: 256 max */
#define RONLY 0400
char premeof[] "Premature EOF";
struct page {
int nuser;
int bno;
int nibuf;
int buff[256];
} page[2];
struct {
int nuser;
int bno;
} fpage;
struct stream {
int *ptr;
int bno;
int nibuf;
int size;
struct page *pno;
};
struct stream text;
struct stream reloc;
struct archdr {
char aname[14];
int atime[2];
char auid, agid;
int amode;
int asize[2];
} archdr;
struct filhdr {
int fmagic;
unsigned Tsize;
unsigned Dsize;
unsigned Bsize;
unsigned Ssize;
char *entry;
int pad;
int relflg;
} filhdr;
struct liblist {
int off;
int bno;
};
struct liblist liblist[NROUT];
struct liblist *libp { &liblist[0] };
struct symbol {
char sname[8];
char stype;
char spad;
int svalue;
int sseg; /* segment in which symbol lies. Only for common */
char saut; /* symbols autoload number */
char ssseg; /* saved sseg */
};
struct symbol cursym;
struct symbol symtab[NSYM];
struct symbol *hshtab[NSYM+2];
struct symbol *symp { symtab };
struct symbol **local[NSYMPR];
struct symbol *backed[NSYMPR];
struct symbol **backp;
struct symbol *p_etext;
struct symbol *p_edata;
struct symbol *p_end;
struct symbol *p_eover; /* address at which segment text ends (file), rounded up */
struct symbol *p_eto; /* top of onceonly segment (physical blocks) */
struct symbol *p_eu; /* physical address of process 0 (physical blocks) */
struct symbol *p_etoa; /* top on onceonly segment (virtual) */
struct symbol *p_eres; /* bottom of oncelonly segment (file) */
struct symbol *entrypt;
int Lflag; /* list some sizes not available later */
int xflag; /* discard local symbols */
int cflag; /* list common segments */
int Xflag; /* discard locals starting with 'L' */
int Sflag; /* discard all except locals and globals*/
int sflag; /* discard all symbols */
int Vflag; /* add overlay symbols */
int nwhere;
int ofilfnd;
char *ofilename "l.out";
int infil;
char *filname;
struct segdat {
unsigned tsize; /* size of text segment */
unsigned dsize; /* size of data segment */
unsigned csize; /* size of common segment */
unsigned bsize; /* size of bss segment */
unsigned spage; /* page number where it starts */
char *base; /* base address for segment text */
} segdat[NSEG];
struct autdat {
int autseg; /* segment number in which it lies */
char *realad; /* real address in kmem */
int nargs;
} autdat[NAUT];
#define NARGS 8
int save0[] {
013716, 0172352, 0012037, 0172352, 0004730, 0012637, 0172352, 0000207
};
int save1[] {
016616, 0000004, 0013766, 0172352, 0000004, 0012037, 0172352, 0004730,
005726, 0016637, 0000002, 0172352, 0000207
};
int save2[] {
016616, 0000004, 0016666, 0000002, 0000004, 0016666, 0000006, 0000002,
013766, 0172352, 0000006, 0012037, 0172352, 0004730, 0022626, 0016637,
000002, 0172352, 0011607
};
int save3[] {
0016601, 0000002, 0016616, 0000004, 0016666, 0000006, 0000002, 0016666,
0000010, 0000004, 0010166, 0000006, 0013766, 0172352, 0000010, 0012037,
0172352, 0004730, 0022626, 0016637, 0000004, 0172352, 0000176, 0000002
};
int save4[] {
0016601, 0000002, 0016616, 0000004, 0016666, 0000006, 0000002, 0016666,
0000010, 0000004, 0016666, 0000012, 0000006, 0010166, 0000010, 0013766,
0172352, 0000012, 0012037, 0172352, 0004730, 0022626, 0016637, 0000006,
0172352, 0000176, 0000004
};
int save5[] {
0016601, 0000002, 0016616, 0000004, 0016666, 0000006, 0000002, 0016666,
0000010, 0000004, 0016666, 0000012, 0000006, 0016666, 0000014, 0000010,
0010166, 0000012, 0013766, 0172352, 0000014, 0012037, 0172352, 0004730,
0022626, 0016637, 0000010, 0172352, 0000176, 0000006
};
int save6[] {
0016601, 0000002, 0016616, 0000004, 0016666, 0000006, 0000002, 0016666,
0000010, 0000004, 0016666, 0000012, 0000006, 0016666, 0000014, 0000010,
0016666, 0000016, 0000012, 0010166, 0000014, 0013766, 0172352, 0000016,
0012037, 0172352, 0004730, 0022626, 0016637, 0000012, 0172352, 0000176,
0000010
};
int save7[] {
0016601, 0000002, 0016616, 0000004, 0016666, 0000006, 0000002, 0016666,
0000010, 0000004, 0016666, 0000012, 0000006, 0016666, 0000014, 0000010,
0016666, 0000020, 0000012, 0016666, 0000020, 0000014, 0010166, 0000016,
0013766, 0172352, 0000016, 0012037, 0172352, 0004730, 0022626, 0016637,
0000014, 0172352, 0000176, 0000012
};
struct caldat {
int clong;
char *ccode;
char *calnam;
char *ccore;
int cused;
} caldat[NARGS] {
{ sizeof save0, save0, "..save0" },
{ sizeof save1, save1, "..save1" },
{ sizeof save2, save2, "..save2" },
{ sizeof save3, save3, "..save3" },
{ sizeof save4, save4, "..save4" },
{ sizeof save5, save5, "..save5" },
{ sizeof save6, save6, "..save6" },
{ sizeof save7, save7, "..save7" },
};
char *autotbl; /* address of core autoload table */
unsigned tsegsize; /* total size of segments */
unsigned tsegtxt;
unsigned tsegdat;
unsigned tsegbss;
unsigned tsegcom;
int ssize; /* size of symbol part of file */
int nsym;
int naut; /* number of autoloads */
int mseg; /* segment counter 2 */
int lastseg;
int nseg; /* number of segments */
int xseg; /* the active segment */
int torigin;
int dorigin;
int borigin;
int ctrel;
int cdrel;
int cbrel;
int errlev;
int delarg 4;
char tfname[] "/tmp/lxyyyyy";
int toutb[259];
int doutb[259];
int otoutb[259];
int odoutb[259];
int soutb[259];
struct symbol **lookup();
struct symbol **slookup();
int fout;
main(argc, argv)
char **argv;
{
register state, *ap;
register char *cp;
static xargc, xargv[500];
static char xdata[3000];
fout = dup(1);
read(open(argv[1], 0), xdata, sizeof xdata);
ap = xargv;
for (cp = xdata; *cp != '\0'; cp++) {
if (state) {
if (*cp==' ' || *cp=='\t' || *cp==',' || *cp=='\n') {
*cp = 0;
state = 0;
}
} else {
if (*cp!=' ' && *cp!='\t' && *cp!=',' && *cp!='\n') {
*ap++ = cp;
xargc++;
state++;
}
}
}
mainx(xargc, xargv);
exit(0);
}
mainx(argc, argv)
char **argv;
{
extern int delexit();
register c;
register char *ap, **p;
struct symbol **hp;
int k;
if ((signal(SIGINT, 1) & 01) == 0)
signal(SIGINT, delexit);
if (argc == 1)
exit(4);
p = argv + 1;
for (c = 1; c < argc; c++) {
filname = 0;
ap = *p++;
if (*ap == '-') switch (ap[1]) {
case 'o':
if (++c >= argc)
error(1, "Bad output file");
ofilename = *p++;
ofilfnd++;
continue;
case 'u':
case 'e':
if (++c >= argc)
error(1, "Bad 'use' or 'entry'");
if (*(hp = slookup(*p++)) == 0) {
*hp = symp;
enter();
}
if (ap[1] == 'e')
entrypt = *hp;
continue;
case 'l':
break;
case 'x':
xflag++;
continue;
case 'X':
Xflag++;
continue;
case 'c':
cflag++;
continue;
case 'L':
Lflag++;
continue;
case 'S':
Sflag++;
continue;
case 's':
sflag++;
xflag++;
continue;
case 'N':
nwhere = nseg + 1;
continue;
case 'O': /* a page 5 segment */
if (++nseg >= NSEG)
error(1, "Too many segments");
xseg = nseg;
continue;
case 'R': /* root segment */
xseg = 0;
continue;
case 'A': /* a list of autoloads */
while (c < argc-1 && **p != '-') {
++c;
k = getnum(*p);
if (k >= NARGS) {
printf("'%s' ", p++);
error(0, "too many args");
continue;
}
if (*(hp = slookup(*p++)) == 0) {
printf("'%s' ", p[-1]);
error(0, "Undefined autoload");
continue;
}
if ((*hp)->sseg == 0) {
printf("'%s' ", p[-1]);
error(0, "Not in segment");
}
if ((*hp)->stype != EXTERN+TEXT) {
printf("'%s' ", p[-1]);
error(0, "Autoload not in text");
continue;
}
if (++naut >= NAUT)
error(1, "Too many autoloads");
caldat[k].cused++;
autdat[naut].nargs = k;
(*hp)->saut = naut;
}
continue;
case 'T':
continue;
case 'V': /* add some overlay symbols */
Vflag++;
continue;
case 'C': /* a list of root commons */
while (c < argc-1 && **p != '-') {
++c;
if (*(hp = slookup(*p++)) == 0) {
printf("'%s' ", p[-1]);
error(0, "Undefined common");
continue;
}
(*hp)->sseg = 0;
}
continue;
}
load1arg(ap);
close(infil);
}
filname = 0;
middle();
setupout();
p = argv+1;
libp = liblist;
for (c=1; c<argc; c++) {
ap = *p++;
if (*ap == '-')
switch (ap[1]) {
case 'u':
case 'e':
case 'o':
++c;
++p;
default:
continue;
case 'A':
case 'C':
while (c < argc-1 && **p != '-') {
++c;
++p;
}
continue;
case 'O':
xseg = ++mseg;
continue;
case 'R':
xseg = 0;
continue;
case 'l':
break;
}
load2arg(ap);
close(infil);
}
finishout();
}
getnum(s)
register char *s;
{
register n;
n = 0;
while (*s)
if (*s++ == ':') {
s[-1] = 0;
while (*s)
n = n *10 + *s++ - '0';
break;
}
return(n);
}
load1arg(cp)
register char *cp;
{
register noff, nbno;
if (!getfile(cp)) {
load1(0, 0, 0);
return;
}
nbno = 0;
noff = 1;
for (;;) {
dseek(&text, nbno, noff, sizeof archdr);
if (text.size <= 0) {
libp->bno = -1;
libp++;
return;
}
mget(&archdr, sizeof archdr);
if (load1(1, nbno, noff + (sizeof archdr) / 2)) {
libp->bno = nbno;
libp->off = noff;
libp++;
}
noff =+ ((archdr.asize[1]&0777)+sizeof(archdr)+1) >> 1;
nbno =+ (archdr.asize[1] >> 9) & 0177;
nbno =+ (archdr.asize[0]) << 7;
nbno =+ noff >> 8;
noff =& 0377;
}
}
load1(libflg, bno, off)
{
register struct symbol *sp, **hp, ***cp;
struct symbol *ssymp;
int ndef, nloc, type, mtype;
readhdr(bno, off);
ctrel = segdat[xseg].tsize;
cdrel =+ segdat[xseg].dsize;
cbrel =+ segdat[xseg].bsize;
ndef = 0;
nloc = sizeof cursym - 4;
cp = local;
backp = backed;
ssymp = symp;
if (filhdr.relflg & RELFLG) {
error(0, "No relocation bits");
return(0);
}
off =+ (sizeof filhdr)/2 + filhdr.Tsize + filhdr.Dsize;
dseek(&text, bno, off, filhdr.Ssize);
while (text.size > 0) {
mget(&cursym, (sizeof cursym) - 4);
type = cursym.stype;
if (Sflag) {
mtype = type & 037;
if (mtype==1 || mtype>4)
continue;
}
if (!(type & EXTERN)) {
if (!Xflag || cursym.sname[0]!='L')
nloc =+ sizeof cursym - 4;
continue;
}
symreloc();
hp = lookup();
if ((sp = *hp) == 0) {
*hp = enter();
*cp++ = hp;
continue;
}
if (sp->stype != EXTERN+UNDEF)
continue;
if (cursym.stype == EXTERN+UNDEF) {
if (cursym.svalue > sp->svalue)
sp->svalue = cursym.svalue;
if (sp->sseg != xseg) {
sp->ssseg = sp->sseg;
sp->sseg = 0;
*backp++ = sp;
}
continue;
}
if (sp->svalue != 0 && cursym.stype == EXTERN+TEXT)
continue;
ndef++;
sp->stype = cursym.stype;
sp->svalue = cursym.svalue;
sp->sseg = xseg;
}
if (!libflg || ndef) {
segdat[xseg].tsize =+ filhdr.Tsize;
segdat[xseg].dsize =+ filhdr.Dsize;
segdat[xseg].bsize =+ filhdr.Bsize;
ssize =+ nloc;
return(1);
}
/*
* No symbols defined by this library member.
* Rip out the hash table entries and reset the symbol table.
*/
symp = ssymp;
while (cp > local)
**--cp = 0;
while (backp > backed) {
backp--;
(*backp)->sseg = (*backp)->ssseg & 0377;
}
return(0);
}
middle()
{
register struct symbol *sp;
register t, csize;
int nund, corigin;
long coreaddr;
long filesize, rootsize, segsize;
p_etext = *slookup("_etext");
p_edata = *slookup("_edata");
p_end = *slookup("_end");
p_eover = *slookup("_eover");
p_eto = *slookup("_eto");
p_etoa = *slookup("_etoa");
p_eu = *slookup("_eu");
p_eres = *slookup("_eres");
/*
* Assign common locations.
*/
ldrsym(p_etext, segdat[0].tsize, EXTERN+TEXT);
ldrsym(p_edata, segdat[0].dsize, EXTERN+DATA);
ldrsym(p_end, segdat[0].bsize, EXTERN+BSS);
if (cflag)
printf("\fCommon Size (seg)\n");
for (sp = symtab; sp < symp; sp++)
if (sp->stype==EXTERN+UNDEF && (t = sp->svalue)!=0) {
t = (t+1) & ~01;
sp->svalue = segdat[sp->sseg].csize;
sp->stype = EXTERN+COMM;
segdat[sp->sseg].csize =+ t;
if (cflag)
printf("%-8.8s %6o (%u)\n", sp->sname, t, sp->sseg);
}
/*
* Now set symbols to their final value
*/
autotbl = segdat[0].tsize;
segdat[0].tsize =+ naut * SIZAUT;
for (t = 0; t < NARGS; t++)
if (caldat[t].cused) {
caldat[t].ccore = segdat[0].tsize;
segdat[0].tsize =+ caldat[t].clong;
addsym(caldat[t].calnam, caldat[t].ccore, TEXT);
}
rootsize = segdat[0].tsize + segdat[0].dsize + segdat[0].csize + segdat[0].bsize;
filesize = segdat[0].tsize + segdat[0].dsize;
/* root segment may not exceed 20Kw */
/* total file text may not exceed 27Kw */
/* each segment may not exceed 4Kw */
if (rootsize > 20L * KW)
error(0, "root segment too large");
coreaddr = rootsize;
if (Lflag) {
printf("\fSegment Text Data Common Bss Total Base File Core\n");
printf("%-3u %6o%6o %6o%6o %6O %5o/%-6o %6o %6o\n",
0,
segdat[0].tsize, segdat[0].dsize,
segdat[0].csize, segdat[0].bsize,
rootsize,
0,0,0,0);
}
for (t = 1; t <= nseg; t++) {
if (t == nwhere) {
ldrsym(p_eu, ldiv(coreaddr + 63, 64), EXTERN+ABS);
/*coreaddr =+ (2*USIZE + 2)*64;*/
coreaddr =+ (3*USIZE + 3)*64; /* enough for 3 per-process areas + 1 seg */
ldrsym(p_eres, segdat[0].dsize + tsegsize, EXTERN+DATA);
}
segsize = segdat[t].tsize + segdat[t].dsize + segdat[t].csize + segdat[t].bsize;
tsegsize =+ segsize;
tsegtxt =+ segdat[t].tsize;
tsegdat =+ segdat[t].dsize;
tsegbss =+ segdat[t].bsize;
tsegcom =+ segdat[t].csize;
if (segsize > 4 * KW - (-coreaddr & 077))
error(0, "segment is too large");
segdat[t].spage = coreaddr >> 6;
segdat[t].base = 20 * KW + (coreaddr & 077);
if (Lflag)
printf("%-3u %6o%6o %6o%6o %6O %5o/%-6o %7O %7O\n",
t,
segdat[t].tsize, segdat[t].dsize,
segdat[t].csize, segdat[t].bsize,
segsize,
segdat[t].spage, segdat[t].base,
filesize, coreaddr);
filesize =+ segsize;
coreaddr =+ segsize;
if (Vflag)
segsym(t);
}
if (Lflag)
printf("Segs %6o%6o %6o%6o %6o %7O %7O\n",
tsegtxt, tsegdat, tsegcom, tsegbss, tsegsize, filesize, coreaddr);
if (filesize > 28L * KW)
error(0, "Too much text/data");
ldrsym(p_eover, segdat[0].dsize + tsegsize, EXTERN+DATA);
ldrsym(p_eto, ldiv(coreaddr, 64), EXTERN+ABS);
ldrsym(p_etoa, lrem(coreaddr, 64) + 24*KW, EXTERN+ABS);
if (nwhere == 0) {
ldrsym(p_eu, ldiv(coreaddr + 63, 64), EXTERN+ABS);
ldrsym(p_eres, 0, EXTERN+DATA);
}
nund = 0;
if (Lflag)
printf("\fAutoload Vector Real Seg Args\n");
for (sp = symtab; sp < symp; sp++) {
torigin = segdat[sp->sseg].base;
dorigin = torigin + segdat[sp->sseg].tsize;
corigin = dorigin + segdat[sp->sseg].dsize;
borigin = corigin + segdat[sp->sseg].csize;
switch (sp->stype) {
case EXTERN+UNDEF:
errlev =| 01;
if (sp->svalue == 0) {
if (!nund)
printf("Undefined:\n");
nund++;
printf("%.8s\n", sp->sname);
}
break;
case EXTERN+ABS:
default:
break;
case EXTERN+TEXT:
sp->svalue =+ torigin;
break;
case EXTERN+DATA:
sp->svalue =+ dorigin;
break;
case EXTERN+BSS:
sp->svalue =+ borigin;
break;
case EXTERN+COMM:
sp->stype = EXTERN+BSS;
sp->svalue =+ corigin;
break;
}
if (sp->saut) {
autdat[sp->saut & 0377].autseg = segdat[sp->sseg].spage;
autdat[sp->saut & 0377].realad = sp->svalue;
if (Vflag)
ovrsym(sp->sname, autotbl + SIZAUT*((sp->saut & 0377) - 1), TEXT);
if (Lflag)
printf("%-8.8s %6o %6o %3d. %2d.\n",
sp->sname,
autotbl + SIZAUT*((sp->saut & 0377) - 1),
autdat[sp->saut & 0377].realad,
sp->sseg,
autdat[sp->saut & 0377].nargs);
}
sp->spad = sp->sseg; /* save the segment no. on the output file */
}
if (sflag || xflag)
ssize = 0;
filhdr.fmagic = FMAGIC;
filhdr.Tsize = segdat[0].tsize;
filhdr.Dsize = segdat[0].dsize + tsegsize;
filhdr.Bsize = segdat[0].bsize + segdat[0].csize;
filhdr.Ssize = sflag ? 0 : (ssize + (sizeof cursym - 4) * (symp - symtab));
filhdr.entry = 0;
if ((sp = entrypt) != 0) {
if (sp->stype != EXTERN+TEXT)
error(0, "Entry point not in text");
else
filhdr.entry = sp->svalue | 01;
}
filhdr.pad = 0;
filhdr.relflg = 1;
for (t = 0; t <= nseg; t++) {
segdat[t].tsize =+ segdat[t].base;
segdat[t].dsize =+ segdat[t].tsize + segdat[t].csize;
segdat[t].bsize =+ segdat[t].csize;
}
nsym = ssize / (sizeof cursym - 4);
}
/*
* generate symbol of form "..saven" for each of
* argument management routines in paging scheme.
*/
addsym(name, val, type)
char *name;
int val;
int type;
{
register struct symbol **hp;
register struct symbol *sp;
hp = slookup(name);
if (*hp == 0) {
*hp = sp = symp;
cursym.svalue = val;
cursym.stype = type;
enter();
}
}
/*
* generate symbol of form ".xxxx" for each of the
* autoload vector entry-points. In practise, the
* initial underscore (_) is replaced with dot (.).
*/
ovrsym(name, val, type)
char *name;
int val;
int type;
{
register struct symbol **hp;
cp8c(name, cursym.sname);
cursym.sname[0] = '.';
cursym.svalue = val;
cursym.stype = type;
hp = lookup();
if (*hp == 0) {
*hp = symp;
enter();
}
}
/*
* generate symbol of form "..segnnn" for each of the
* autoload segments.
*/
segsym(t)
int t;
{
register int i;
register struct symbol **hp;
cp8c("..seg", cursym.sname);
i = t;
cursym.sname[7] = i%10 + '0';
i =/ 10;
cursym.sname[6] = i%10 + '0';
i =/ 10;
cursym.sname[5] = i + '0';
cursym.svalue = segdat[t].spage;
cursym.stype = ABS;
hp = lookup();
if (*hp == 0) {
*hp = symp;
enter();
}
}
ldrsym(sp, val, type)
register struct symbol *sp;
{
if (sp == 0)
return;
if (sp->stype != EXTERN+UNDEF || sp->svalue) {
printf("%.8s: ", sp->sname);
error(0, "Multiply defined");
return;
}
sp->stype = type;
sp->svalue = val;
sp->sseg = 0;
}
setupout()
{
register char *p;
register pid;
struct symbol *ep;
if ((toutb[0] = creat(ofilename, 0606)) < 0)
error(1, "Can't write output");
pid = getpid();
for (p = &tfname[12]; p > &tfname[7];) {
*--p = (pid&07) + '0';
pid =>> 3;
}
tcreat(doutb, 'a');
if (!sflag || !xflag)
tcreat(soutb, 'b');
tcreat(otoutb, 'c');
tcreat(odoutb, 'd');
mput(toutb, &filhdr, sizeof filhdr);
return;
}
tcreat(buf, letter)
int *buf;
{
tfname[6] = letter;
if ((buf[0] = creat(tfname, RONLY)) < 0)
error(1, "Can't create temp");
buf[1] = buf[2] = 0;
}
load2arg(acp)
char *acp;
{
register char *cp;
register struct liblist *lp;
cp = acp;
if (!getfile(cp)) {
while (*cp)
cp++;
while (cp >= acp && *--cp != '/');
mkfsym(++cp);
load2(0, 0);
return;
}
for (lp = libp; lp->bno != -1; lp++) {
dseek(&text, lp->bno, lp->off, sizeof archdr);
mget(&archdr, sizeof archdr);
mkfsym(archdr.aname);
load2(lp->bno, lp->off + (sizeof archdr) / 2);
}
libp = ++lp;
}
load2(bno, off)
{
register struct symbol *sp;
register int *lp, symno;
int type, mtype;
checkseg();
readhdr(bno, off);
ctrel = segdat[xseg].base;
cdrel =+ segdat[xseg].tsize;
cbrel =+ segdat[xseg].dsize;
/*
* Reread the symbol table, recording the numbering
* of symbols for fixing external references.
*/
lp = local;
symno = -1;
off =+ (sizeof filhdr)/2;
dseek(&text, bno, off+filhdr.Tsize+filhdr.Dsize, filhdr.Ssize);
while (text.size > 0) {
symno++;
mget(&cursym, sizeof cursym - 4);
symreloc();
type = cursym.stype;
if (Sflag) {
mtype = type & 037;
if (mtype==1 || mtype>4)
continue;
}
if (!(type & EXTERN)) {
if (!sflag && !xflag && (!Xflag || cursym.sname[0]!='L'))
mput(soutb, &cursym, sizeof cursym - 4);
continue;
}
if ((sp = *lookup()) == 0)
error(1, "internal error: symbol not found");
if (cursym.stype == EXTERN+UNDEF) {
if (lp >= &local[NSYMPR])
error(1, "Local symbol overflow");
*lp++ = symno;
*lp++ = sp;
continue;
}
if (cursym.stype!=sp->stype || cursym.svalue!=sp->svalue) {
printf("%.8s: ", cursym.sname);
error(0, "Multiply defined");
}
}
dseek(&text, bno, off, filhdr.Tsize);
dseek(&reloc, bno, off+(filhdr.Tsize+filhdr.Dsize)/2, filhdr.Tsize);
load2td(lp, ctrel, xseg ? otoutb : toutb);
dseek(&text, bno, off+(filhdr.Tsize/2), filhdr.Dsize);
dseek(&reloc, bno, off+filhdr.Tsize+(filhdr.Dsize/2), filhdr.Dsize);
load2td(lp, cdrel, xseg ? odoutb : doutb);
segdat[xseg].base =+ filhdr.Tsize;
segdat[xseg].tsize =+ filhdr.Dsize;
segdat[xseg].dsize =+ filhdr.Bsize;
}
checkseg()
{
register f, n, *p;
if (lastseg!=xseg && lastseg!=0) {
fflush(odoutb);
close(odoutb[0]);
tfname[6] = 'd';
f = open(tfname, 0);
while ((n = read(f, odoutb, 512)) > 0) {
n =>> 1;
p = odoutb;
do {
putw(*p++, otoutb);
} while (--n != 0);
}
close(f);
unlink(tfname);
tcreat(odoutb, 'd');
if (n = segdat[lastseg].bsize >> 1)
do {
putw(0, otoutb);
} while (--n != 0);
}
lastseg = xseg;
}
load2td(lp, creloc, b1)
int *lp;
{
register r, t;
int ad;
for (ad = 0;;) {
ad =+ 2;
/*
* The pickup code is copied from "get" for speed.
*/
if (--text.size <= 0) {
if (text.size < 0)
break;
text.size++;
t = get(&text);
} else if (--text.nibuf < 0) {
text.nibuf++;
text.size++;
t = get(&text);
} else
t = *text.ptr++;
if (--reloc.size <= 0) {
if (reloc.size < 0)
error(1, "Relocation error");
reloc.size++;
r = get(&reloc);
} else if (--reloc.nibuf < 0) {
reloc.nibuf++;
reloc.size++;
r = get(&reloc);
} else
r = *reloc.ptr++;
switch (r&016) {
case RTEXT:
t =+ ctrel;
if (!(r & 01) && xseg) {
register struct autdat *ap;
int spage;
spage = segdat[xseg].spage;
for (ap = autdat + naut; ap > autdat; ap--)
if (t==ap->realad && spage==ap->autseg) {
t = autotbl + SIZAUT*((ap - 1) - autdat);
break;
}
}
break;
case RDATA:
t =+ cdrel;
break;
case RBSS:
t =+ cbrel;
break;
case REXT:
{
register struct symbol *sp;
sp = lookloc(lp, r);
if (sp->stype == EXTERN+UNDEF) {
r = (r & 01) + ((nsym + (sp - symtab)) << 4) + REXT;
break;
}
if (sp->saut && t+(r&1 ? ad : 0)==0 && (xseg!=sp->sseg || !(r&01)))
t =+ autotbl + SIZAUT*((sp->saut & 0377) - 1) - sp->svalue;
else if (sp->sseg && xseg != (sp->sseg & 0377)) {
printf("'%.8s' ", sp->sname);
error(0, "Unlikely reference");
}
t =+ sp->svalue;
r = (r&01) + ((sp->stype-(EXTERN+ABS))<<1);
}
break;
}
if (r&01)
t =- creloc;
putw(t, b1);
}
}
finishout()
{
register n, *w;
register struct symbol *p;
for (n = 1; n <= naut; n++) {
putw(CALLR0, toutb);
putw(caldat[autdat[n].nargs].ccore, toutb);
putw(autdat[n].autseg, toutb);
putw(autdat[n].realad, toutb);
}
for (n = 0; n < NARGS; n++)
if (caldat[n].cused)
for (w = caldat[n].ccode; w < caldat[n].ccode + caldat[n].clong;)
putw(*w++, toutb);
copy(doutb, 'a');
xseg = 0;
checkseg();
copy(otoutb, 'c');
if (!sflag) {
if (!xflag)
copy(soutb, 'b');
for (p = symtab; p < symp; p++)
mput(toutb, p, sizeof cursym - 4);
}
fflush(toutb);
close(toutb[0]);
if (!ofilfnd) {
unlink("a.out");
link("l.out", "a.out");
ofilename = "a.out";
}
delarg = errlev;
delexit();
}
delexit()
{
register c;
unlink("l.out");
for (c = 'a'; c <= 'd'; c++) {
tfname[6] = c;
unlink(tfname);
}
if (!delarg)
chmod(ofilename, 0777);
flush();
exit(delarg);
}
copy(buf, c)
int *buf;
{
register f, *p, n;
fflush(buf);
close(buf[0]);
tfname[6] = c;
f = open(tfname, 0);
while ((n = read(f, doutb, 512)) > 1) {
n =>> 1;
p = doutb;
do {
putw(*p++, toutb);
} while (--n != 0);
}
close(f);
}
mkfsym(s)
char *s;
{
if (sflag || xflag)
return;
cp8c(s, cursym.sname);
cursym.stype = 037;
cursym.svalue = torigin;
mput(soutb, &cursym, sizeof cursym - 4);
}
mget(aloc, an)
int *aloc;
{
register *loc, n;
register *p;
n = an;
n =>> 1;
loc = aloc;
if ((text.nibuf =- n) >= 0) {
if ((text.size =- n) > 0) {
p = text.ptr;
do {
*loc++ = *p++;
} while (--n != 0);
text.ptr = p;
return;
} else
text.size =+ n;
}
text.nibuf =+ n;
do {
*loc++ = get(&text);
} while (--n != 0);
}
mput(buf, aloc, an)
int *aloc;
{
register *loc;
register n;
loc = aloc;
n = an>>1;
do {
putw(*loc++, buf);
} while (--n != 0);
}
dseek(sp, ab, o, s)
register struct stream *sp;
{
register struct page *p;
register b;
int n;
b = ab + ((o>>8) & 0377);
o =& 0377;
--sp->pno->nuser;
if ((p = &page[0])->bno!=b && (p = &page[1])->bno!=b)
if (p->nuser==0 || (p = &page[0])->nuser==0) {
if (page[0].nuser==0 && page[1].nuser==0)
if (page[0].bno < page[1].bno)
p = &page[0];
p->bno = b;
seek(infil, b, 3);
if ((n = read(infil, p->buff, 512)>>1) < 0)
n = 0;
p->nibuf = n;
} else
error(1, "No pages");
++p->nuser;
sp->bno = b;
sp->pno = p;
sp->ptr = p->buff + o;
if (s != -1)
sp->size = (s>>1) & 077777;
if ((sp->nibuf = p->nibuf-o) <= 0)
sp->size = 0;
}
get(sp)
register struct stream *sp;
{
if (--sp->nibuf < 0) {
dseek(sp, sp->bno+1, 0, -1);
--sp->nibuf;
}
if (--sp->size <= 0) {
if (sp->size < 0)
error(1, premeof);
++fpage.nuser;
--sp->pno->nuser;
sp->pno = &fpage;
}
return(*sp->ptr++);
}
getfile(cp)
register char *cp;
{
register c;
archdr.aname[0] = '\0';
filname = cp;
if (cp[0]=='-' && cp[1]=='l') {
if (cp[2] == '\0')
cp = "-la";
filname = "/usr/lib/libxxxxxxxxxxxxxxx";
for (c = 0; cp[c+2] != '\0'; c++)
filname[c+12] = cp[c+2];
filname[c+12] = '.';
filname[c+13] = 'a';
filname[c+14] = '\0';
if ((infil = open(filname+4, 0)) >= 0) {
filname =+ 4;
goto OK;
}
}
if ((infil = open(filname, 0)) < 0)
error(1, "cannot open");
OK:
page[0].bno = page[1].bno = -1;
page[0].nuser = page[1].nuser = 0;
text.pno = reloc.pno = &fpage;
fpage.nuser = 2;
dseek(&text, 0, 0, 2);
if (text.size <= 0)
error(1, premeof);
return(get(&text) == ARCMAGIC);
}
struct symbol **lookup()
{
int i;
register struct symbol **hp;
register char *cp, *cp1;
i = 0;
for (cp = cursym.sname; cp < &cursym.sname[8];)
i = (i<<1) + *cp++;
for (hp = &hshtab[(i & 077777)%NSYM + 2]; *hp != 0;) {
cp1 = (*hp)->sname;
for (cp = cursym.sname; cp < &cursym.sname[8];)
if (*cp++ != *cp1++)
goto no;
break;
no:
if (++hp >= &hshtab[NSYM+2])
hp = hshtab;
}
return(hp);
}
struct symbol **slookup(s)
char *s;
{
cp8c(s, cursym.sname);
cursym.stype = EXTERN+UNDEF;
cursym.svalue = 0;
return(lookup());
}
enter()
{
register struct symbol *sp;
if ((sp = symp) >= &symtab[NSYM])
error(1, "Symbol table overflow");
cp8c(cursym.sname, sp->sname);
sp->stype = cursym.stype;
sp->svalue = cursym.svalue;
sp->sseg = xseg;
sp->saut = 0;
symp++;
return(sp);
}
symreloc()
{
switch (cursym.stype) {
case TEXT:
case EXTERN+TEXT:
cursym.svalue =+ ctrel;
return;
case DATA:
case EXTERN+DATA:
cursym.svalue =+ cdrel;
return;
case BSS:
case EXTERN+BSS:
cursym.svalue =+ cbrel;
return;
case EXTERN+UNDEF:
return;
}
if (cursym.stype & EXTERN)
cursym.stype = EXTERN+ABS;
}
error(n, s)
char *s;
{
if (filname) {
printf("%s", filname);
if (archdr.aname[0])
printf("(%.14s)", archdr.aname);
printf(": ");
}
printf("%s\n", s);
if (n)
delexit();
errlev = 2;
}
lookloc(lp, r)
register int *lp;
{
register int *clp;
register sn;
sn = (r >> 4) & 07777;
for (clp = local; clp < lp; clp =+ 2)
if (clp[0] == sn)
return(clp[1]);
error(1, "Local symbol botch");
}
readhdr(bno, off)
{
register st, sd;
dseek(&text, bno, off, sizeof filhdr);
mget(&filhdr, sizeof filhdr);
if (filhdr.fmagic != FMAGIC)
error(1, "Bad format");
st = (filhdr.Tsize+01) & ~01;
filhdr.Tsize = st;
cdrel = -st;
sd = (filhdr.Dsize+01) & ~01;
cbrel = - (st+sd);
filhdr.Bsize = (filhdr.Bsize+01) & ~01;
}
cp8c(from, to)
char *from, *to;
{
register char *f, *t, *te;
f = from;
t = to;
te = t+8;
while ((*t++ = *f++) && t<te);
while (t < te)
*t++ = 0;
}