char LD
[] = "@(#)ld.c 1.10 78/12/07 15:34:58"; /* sccs ident */
* header of 8 words magic number 0410:
data starts immediately after
* size of text relocation info
* size of data relocation info
* 'segment' origin comments
* text: 32 0 padded to multiple of 4 bytes
* data: 32+textsize 0 padded to multiple of 4 bytes
* text relocation: 32+textsize+datasize
* data relocation: 32+textsize+datasize+textrelocationsize
* symbol table: 32+textsize+datasize+textrelocationsize+datarelocationsize
struct {short hiword
; short loword
;}; /* stupid fp-11 */
fixl(p
) register long *p
;{
t
=p
->hiword
; p
->hiword
=p
->loword
; p
->loword
=t
;
writel(p
,n
,f
) long *p
; FILE *f
; {
fwrite(p
,sizeof(*p
),n
,f
);
fwrite(&(*p
).loword
,2,1,f
);
fwrite(&(*p
).hiword
,2,1,f
);
long htoi(p
) register char *p
; {/* hex to integer conversion */
if (*p
<='9' && *p
>='0') n
+= *p
- '0';
else if (*p
<='f' && *p
>='a') n
+= *p
-'a' +10;
else if (*p
<='F' && *p
>='A') n
+= *p
-'A' +10;
#define COMM 0x12 /* for internal use only */
* address reference types
char premeof
[] = "Premature EOF";
long ctsav
, cdsav
, cbsav
;
long offt
, offd
, offb
, offtr
, offdr
, offs
;
/* one entry for each archive member referenced;
* set in first pass; needs restoring for overlays
short symhash
; /* index of hash table entry pointing to this symbol */
int locindex
; /* index to symbol in file */
SYMBOL
*locsymbol
; /* ptr to symbol table */
SYMBOL cursym
; /* current symbol */
SYMBOL
*symtab
; /* actual symbols */
SYMBOL
*lastsym
; /* last symbol entered */
SYMBOL
*nextsym
; /* next available symbol table entry */
int nsym
; /* number of symbols allocated in symtab */
SYMBOL
*hshtab
[NSYM
+2]; /* hash table for symbols */
int xflag
; /* discard local symbols */
int Xflag
; /* discard locals starting with 'L' */
int Sflag
; /* discard all except locals and globals*/
int rflag
; /* preserve relocation bits, don't define common */
int arflag
; /* original copy of rflag */
int sflag
; /* discard all symbols */
int nflag
= 1; /* pure procedure */
int dflag
; /* define common even with rflag */
int iflag
; /* I/D space separated */
BOOL vflag
; /* overlays used */
char *ofilename
= "l.out";
/* cumulative sizes set in pass 1 */
/* symbol relocation; both passes */
symwrite(sp
,n
,f
) SYMBOL
*sp
; FILE *f
; {
fwrite(sp
,sizeof(*symtab
),n
,f
);
fwrite(sp
,sizeof(*symtab
)-sizeof(sp
->svalue
),1,f
);
writel(&(sp
->svalue
),1,f
); sp
++;
if (signal(SIGINT
, SIG_IGN
) != SIG_IGN
)
nextsym
=symtab
=sbrk(0); nsym
=0;
/* scan files once to find symdefs */
if (trace
) printf("%s:\n", *p
);
error(1, "Bad output file");
error(1, "Bad 'use' or 'entry'");
error(1, "-v: arg missing");
while (--vscan
>=0 && found
==FALSE
)
found
= eq(vnodes
[vscan
].vname
, *p
);
error(1, "-D: arg missing");
error(1, "-D: too small");
error(1, "-T: arg missing");
error(1, "-T: too late, some text already loaded");
if (-1==(local
=sbrk(NSYMPR
*sizeof(*local
)))) error(1,"Memory overflow");
if (trace
) printf("%s:\n", ap
);
for (dnum
= htoi(*p
); dorigin
<dnum
; dorigin
++) putc(0, dout
);
v
->symsav
= nextsym
-symtab
;
register SYMBOL
*saved
,*sp
;
saved
= symtab
+ v
->symsav
;
hshtab
[(--sp
)->symhash
]=0;
/* scan file to find defined symbols */
dseek(&text
, loc
, (long)sizeof(archdr
));
mget((short *)&archdr
, sizeof archdr
, &text
);
if (load1(1, loc
+sizeof(archdr
))) {
if (archdr
.ar_size
.loword
==0) fixl(&archdr
.ar_size
);
loc
+= round(archdr
.ar_size
, 1) + sizeof(archdr
);
/* single file or archive member */
/* if (filhdr.a_trsize+filhdr.a_drsize==0) {
/* error(0, "No relocation bits");
loc
+= filhdr
.a_text
+ filhdr
.a_data
+
filhdr
.a_trsize
+ filhdr
.a_drsize
+ sizeof(filhdr
);
dseek(&text
, loc
, filhdr
.a_syms
);
if (Xflag
==0 || cursym
.sname
[0]!='L' || type
&STABTYPS
)
if ((sp
= lastsym
)->stype
!= EXTERN
+UNDEF
)
if (cursym
.stype
== EXTERN
+UNDEF
) {
if (cursym
.svalue
> sp
->svalue
)
sp
->svalue
= cursym
.svalue
;
if (sp
->svalue
!= 0 && cursym
.stype
== EXTERN
+TEXT
)
sp
->stype
= cursym
.stype
;
sp
->svalue
= cursym
.svalue
;
dsize
+= round(filhdr
.a_data
, FW
);
bsize
+= round(filhdr
.a_bss
, FW
);
trsize
+= filhdr
.a_trsize
;
drsize
+= filhdr
.a_drsize
;
* No symbols defined by this library member.
* Rip out the hash table entries and reset the symbol table.
hshtab
[(--nextsym
)->symhash
]=0;
register SYMBOL
*sp
, *symp
;
long csize
, t
, corigin
, ocsize
;
p_data
= *slookup("_data");
p_etext
= *slookup("_etext");
p_edata
= *slookup("_edata");
p_end
= *slookup("_end");
* If there are any undefined symbols, save the relocation bits.
for (sp
= symtab
; sp
<symp
; sp
++)
if (sp
->stype
==EXTERN
+UNDEF
&& sp
->svalue
==0
&& sp
!=p_end
&& sp
!=p_edata
&& sp
!=p_etext
* Assign common locations.
database
= round(tsize
+textbase
, (nflag
? PAGRND
:FW
));
ldrsym(p_data
, (long)0 , EXTERN
+DATA
);
ldrsym(p_etext
, tsize
, EXTERN
+TEXT
);
ldrsym(p_edata
, dsize
, EXTERN
+DATA
);
ldrsym(p_end
, bsize
, EXTERN
+BSS
);
for (sp
= symtab
; sp
<symp
; sp
++) {
if ((s
=sp
->stype
)==EXTERN
+UNDEF
&& (t
= sp
->svalue
)!=0) {
csize
= round(csize
, rnd
);
if (((s
&TMASK
) == EXTERN
+UNDEF
) && (s
& STABTYPS
)) {
sp
->stype
= (s
& STABTYPS
) | (EXTERN
+COMM
);
* Now set symbols to their final value
csize
= round(csize
, FW
);
corigin
= dorigin
+ dsize
;
borigin
= corigin
+ csize
;
for (sp
= symtab
; sp
<symp
; sp
++) switch (sp
->stype
& TMASK
) {
if ((arflag
==0 || dflag
) && sp
->svalue
==0) {
printf("%.8s\n", sp
->sname
);
sp
->stype
= (sp
->stype
& STABTYPS
) | (EXTERN
+BSS
);
nsym
= ssize
/ (sizeof cursym
);
if (sp
->stype
!= EXTERN
+UNDEF
|| sp
->svalue
) {
printf("%.8s: ", sp
->sname
);
error(0, "Multiply defined (internal)");
extern char _sibuf
[BUFSIZ
]; /* the space is forced upon us; might as well use it */
tout
= fopen(ofilename
, "w");
error(1, "cannot create output");
dout
= tcreat(&doutn
, "/tmp/ldaaXXXXX");
if (sflag
==0 || xflag
==0)
sout
= tcreat(&soutn
, "/tmp/ldbaXXXXX");
trout
= tcreat(&troutn
, "/tmp/ldcaXXXXX");
drout
= tcreat(&droutn
, "/tmp/lddaXXXXX");
filhdr
.a_magic
= nflag
? NMAGIC
:OMAGIC
;
filhdr
.a_text
= nflag
? tsize
:round(tsize
, FW
);
filhdr
.a_trsize
= trsize
;
filhdr
.a_drsize
= drsize
;
filhdr
.a_syms
= sflag
? 0: (ssize
+ (sizeof cursym
)*(nextsym
-symtab
));
if (entrypt
->stype
!=EXTERN
+TEXT
)
error(0, "Entry point not in text");
filhdr
.a_entry
= entrypt
->svalue
;
filhdr
.a_trsize
= (rflag
? trsize
:0);
filhdr
.a_drsize
= (rflag
? drsize
:0);
if ((fp
= fopen(tnm
, "w")) == NULL
)
error(1, "Cannot create temp file");
while (cp
>= acp
&& *--cp
!= '/');
} else { /* scan archive members referenced */
for (lp
= libp
; lp
->loc
!= -1; lp
++) {
dseek(&text
, lp
->loc
, (long)sizeof(archdr
));
mget((short *)&archdr
, sizeof(archdr
), &text
);
load2(lp
->loc
+ (long)sizeof(archdr
));
* Reread the symbol table, recording the numbering
* of symbols for fixing external references.
dseek(&text
, loc
+filhdr
.a_text
+filhdr
.a_data
+
filhdr
.a_trsize
+filhdr
.a_drsize
, filhdr
.a_syms
);
if ((type
&EXTERN
) == 0) {
if (!sflag
&&!xflag
&&(!Xflag
||cursym
.sname
[0]!='L'||type
&STABTYPS
))
symwrite(&cursym
, 1, sout
);
if ((sp
= *lookup()) == 0)
error(1, "internal error: symbol not found");
if (cursym
.stype
== EXTERN
+UNDEF
) {
error(1, "Local symbol overflow");
if(cursym
.stype
& STABTYPS
) continue;
if (cursym
.stype
!=sp
->stype
|| cursym
.svalue
!=sp
->svalue
) {
printf("%.8s: ", cursym
.sname
);
error(0, "Multiply defined");
dseek(&text
, loc
, filhdr
.a_text
);
dseek(&reloc
, loc
+filhdr
.a_text
+filhdr
.a_data
, filhdr
.a_trsize
);
load2td(lp
, ctrel
, tout
, trout
);
dseek(&text
, loc
+filhdr
.a_text
, filhdr
.a_data
);
dseek(&reloc
, loc
+filhdr
.a_text
+filhdr
.a_data
+filhdr
.a_trsize
, filhdr
.a_drsize
);
load2td(lp
, cdrel
, dout
, drout
);
while (filhdr
.a_data
&FW
) {
putc(0, dout
); filhdr
.a_data
++;
torigin
+= filhdr
.a_text
;
dorigin
+= filhdr
.a_data
;
load2td(lp
, creloc
, b1
, b2
)
if (reloc
.size
==0) {while (text
.size
) putc(get(&text
),b1
); break;}
t
=getl(&reloc
); /* position of relocatable stuff */
if (rflag
) putl(t
+creloc
,b2
); /* remember for subsequent link editing */
while (text
.pos
<t
) putc(get(&text
),b1
); /* advance to proper position */
r1
=get3(&reloc
); /* kind of relocation */
switch (r2
&06) {/* read raw datum according to its length */
case LEN1
: tw
=get(&text
); break;
case LEN2
: tw
=gets(&text
); break;
case LEN4
: tw
=getl(&text
); break;
sp
=lookloc(lp
,r1
); /* find the symbol */
if (sp
->stype
==EXTERN
+UNDEF
) { /* still undefined */
r2
=(r2
&(REFMASK
+REXT
+ROFF
));
r1
= nsym
+(sp
-symtab
); /* new reloc */
if (sp
->stype
==EXTERN
+DATA
&& r2
&ROFF
) {
else if (sp
->stype
==EXTERN
+BSS
&& r2
&ROFF
) {
else if (sp
->stype
==EXTERN
+ABS
&& r2
&ROFF
) {
else if (sp
->stype
==EXTERN
+TEXT
&& r2
&ROFF
) {
else {if (r2
&ROFF
) {if (rflag
) {error(0,"!-r; see JFR"); rflag
=0;}}
tw
+= sp
->svalue
- database
;
} else switch (r1
&TYMASK
) {
case RTEXT
: tw
+= ctrel
; break;
case RTEXTO
:tw
+= round(filhdr
.a_text
,PAGRND
)+ctrel
-database
; break;
case RDATA
: tw
+= cdrel
; break;
case RDATAO
:tw
+= cdorel
; break;
case RBSS
: tw
+= cbrel
; break;
case RBSSO
: tw
+= cborel
-filhdr
.a_data
; break;
case RABSO
: tw
+= round(filhdr
.a_text
,PAGRND
)-database
; break;
if (rflag
) { /* remember for subsequent link editing */
if (r2
&PCREL
) tw
-= creloc
; /* assembler already subtracted text.pos */
switch (r2
&06) {/* output relocated datum according to its length */
case LEN1
: l
= -128; u
=127; putc((char)tw
,b1
); break;
case LEN2
: l
= -32768; u
=32767; puts((short)tw
,b1
); break;
case LEN4
: l
=0x80000000; u
=0x7FFFFFFF; putl(tw
,b1
); break;
if (tw
<l
|| u
<tw
) error(0,"Displacement overflow");
symwrite(symtab
, nextsym
-symtab
, tout
);
if ((fp
= fopen(np
, "r")) == NULL
)
error(1, "cannot recopy output");
while ((c
= getc(fp
)) != EOF
)
symwrite(&cursym
, 1, sout
);
if ((sp
->nibuf
-= n
) >= 0) {
if ((sp
->size
-= n
) > 0) {
short t
; mget(&t
,2,sp
); return(t
);
char t
; mget(&t
,1,sp
); return(t
);
long t
; t
=0; mget(&t
,3,sp
); return(t
);
symget(sp
,f
) SYMBOL
*sp
; STREAM
*f
; {
error(1, "loader error; odd offset");
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
)
lseek(infil
, loc
& ~0777L, 0);
if ((n
= read(infil
, p
->buff
, sizeof(p
->buff
))) < 0)
if (s
!= -1) {sp
->size
= s
; sp
->pos
= 0;}
sp
->ptr
= (short *)(p
->buff
+ o
);
if ((sp
->nibuf
= p
->nibuf
-o
) <= 0)
if ((sp
->nibuf
-= sizeof(char)) < 0) {
dseek(sp
, ((long)(sp
->bno
+1)<<9), (long)-1);
sp
->nibuf
-= sizeof(char);
if ((sp
->size
-= sizeof(char)) <= 0) {
archdr
.ar_name
[0] = '\0';
if (cp
[0]=='-' && cp
[1]=='l') {
filname
= "/usr/lib/libxxxxxxxxxxxxxxx";
if ((infil
= open(filname
+4, 0)) >= 0) {
if (infil
== -1 && (infil
= open(filname
, 0)) < 0)
page
[0].bno
= page
[1].bno
= -1;
page
[0].nuser
= page
[1].nuser
= 0;
text
.pno
= reloc
.pno
= &fpage
;
dseek(&text
, 0L, (long)sizeof(int));
mget(&arcmag
, sizeof(arcmag
), &text
);
for (cp
= cursym
.sname
; cp
< &cursym
.sname
[8];)
for (hp
= &hshtab
[(i
&077777)%NSYM
+2]; *hp
!=0;) {
for (cp
= cursym
.sname
; cp
< &cursym
.sname
[8];)
if (++hp
>= &hshtab
[NSYM
+2])
cursym
.stype
= EXTERN
+UNDEF
;
if ((nextsym
-symtab
)>=NSYM
)
error(1, "Symbol table overflow");
if ((nextsym
-symtab
)>=nsym
) {
if (-1==sbrk(NSYM
/5 * sizeof(*symtab
))) error(1,"Memory overflow");
*hp
= lastsym
= sp
= nextsym
++;
cp8c(cursym
.sname
, sp
->sname
);
sp
->stype
= cursym
.stype
;
sp
->svalue
= cursym
.svalue
;
switch (cursym
.stype
& 017) {
cursym
.stype
= EXTERN
+ABS
;
printf("(%.14s)", archdr
.ar_name
);
for (clp
= local
; clp
<lp
; clp
++)
error(1, "Local symbol botch");
dseek(&text
, loc
, (long)sizeof(filhdr
));
mget((short *)&filhdr
, sizeof(filhdr
), &text
);
for (p
= &filhdr
,i
=8;--i
>=0;) fixl(p
++);
if (filhdr
.a_magic
!=A_MAGIC1
&& filhdr
.a_magic
!=A_MAGIC2
&&
filhdr
.a_magic
!=A_MAGIC3
&& filhdr
.a_magic
!=A_MAGIC4
)
error(1,"Bad magic number");
if (filhdr
.a_text
&01 || filhdr
.a_data
&01) {
printf("tsize=%X dsize=%X\n",filhdr
.a_text
,filhdr
.a_data
);
error(1, "Text/data size odd");
filhdr
.a_bss
= round(filhdr
.a_bss
, FW
);
if (filhdr
.a_magic
== NMAGIC
) {
cdrel
= -round(filhdr
.a_text
, PAGRND
);
cbrel
= cdrel
- filhdr
.a_data
;
} else if (filhdr
.a_magic
== OMAGIC
) {
cbrel
= cdrel
- filhdr
.a_data
;
register char *f
, *t
, *te
;
while ((*t
++ = *f
++) && t
<te
);
fwrite(&w
,sizeof(short),1,f
);
fwrite(&w
,sizeof(char),1,f
);
fwrite(&w
,sizeof(long),1,f
);