158 lines
2 KiB
C
158 lines
2 KiB
C
![]() |
#include "l.h"
|
||
|
|
||
|
enum{
|
||
|
ABSD = 0,
|
||
|
ABSU = 1,
|
||
|
RELD = 2,
|
||
|
RELU = 3,
|
||
|
};
|
||
|
|
||
|
int modemap[4] = { 0, 1, -1, 2, };
|
||
|
|
||
|
typedef struct Reloc Reloc;
|
||
|
|
||
|
struct Reloc
|
||
|
{
|
||
|
int n;
|
||
|
int t;
|
||
|
uchar *m;
|
||
|
ulong *a;
|
||
|
};
|
||
|
|
||
|
Reloc rels;
|
||
|
|
||
|
static void
|
||
|
grow(Reloc *r)
|
||
|
{
|
||
|
int t;
|
||
|
uchar *m, *nm;
|
||
|
ulong *a, *na;
|
||
|
|
||
|
t = r->t;
|
||
|
r->t += 64;
|
||
|
m = r->m;
|
||
|
a = r->a;
|
||
|
r->m = nm = malloc(r->t*sizeof(uchar));
|
||
|
r->a = na = malloc(r->t*sizeof(ulong));
|
||
|
memmove(nm, m, t*sizeof(uchar));
|
||
|
memmove(na, a, t*sizeof(ulong));
|
||
|
free(m);
|
||
|
free(a);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
dynreloc(Sym *s, long v, int abs)
|
||
|
{
|
||
|
int i, k, n;
|
||
|
uchar *m;
|
||
|
ulong *a;
|
||
|
Reloc *r;
|
||
|
|
||
|
if(v&3)
|
||
|
diag("bad relocation address");
|
||
|
v >>= 2;
|
||
|
if(s != S && s->type == SUNDEF)
|
||
|
k = abs ? ABSU : RELU;
|
||
|
else
|
||
|
k = abs ? ABSD : RELD;
|
||
|
/* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, a, a, k); */
|
||
|
k = modemap[k];
|
||
|
r = &rels;
|
||
|
n = r->n;
|
||
|
if(n >= r->t)
|
||
|
grow(r);
|
||
|
m = r->m;
|
||
|
a = r->a;
|
||
|
for(i = n; i > 0; i--){
|
||
|
if(v < a[i-1]){ /* happens occasionally for data */
|
||
|
m[i] = m[i-1];
|
||
|
a[i] = a[i-1];
|
||
|
}
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
m[i] = k;
|
||
|
a[i] = v;
|
||
|
r->n++;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
sput(char *s)
|
||
|
{
|
||
|
char *p;
|
||
|
|
||
|
p = s;
|
||
|
while(*s)
|
||
|
cput(*s++);
|
||
|
cput(0);
|
||
|
return s-p+1;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
asmdyn(void)
|
||
|
{
|
||
|
int i, n, t, c;
|
||
|
Sym *s;
|
||
|
ulong la, ra, *a;
|
||
|
vlong off;
|
||
|
uchar *m;
|
||
|
Reloc *r;
|
||
|
|
||
|
cflush();
|
||
|
off = seek(cout, 0, 1);
|
||
|
lput(0);
|
||
|
t = 0;
|
||
|
lput(imports);
|
||
|
t += 4;
|
||
|
for(i = 0; i < NHASH; i++)
|
||
|
for(s = hash[i]; s != S; s = s->link)
|
||
|
if(s->type == SUNDEF){
|
||
|
lput(s->sig);
|
||
|
t += 4;
|
||
|
t += sput(s->name);
|
||
|
}
|
||
|
|
||
|
la = 0;
|
||
|
r = &rels;
|
||
|
n = r->n;
|
||
|
m = r->m;
|
||
|
a = r->a;
|
||
|
lput(n);
|
||
|
t += 4;
|
||
|
for(i = 0; i < n; i++){
|
||
|
ra = *a-la;
|
||
|
if(*a < la)
|
||
|
diag("bad relocation order");
|
||
|
if(ra < 256)
|
||
|
c = 0;
|
||
|
else if(ra < 65536)
|
||
|
c = 1;
|
||
|
else
|
||
|
c = 2;
|
||
|
cput((c<<6)|*m++);
|
||
|
t++;
|
||
|
if(c == 0){
|
||
|
cput(ra);
|
||
|
t++;
|
||
|
}
|
||
|
else if(c == 1){
|
||
|
wput(ra);
|
||
|
t += 2;
|
||
|
}
|
||
|
else{
|
||
|
lput(ra);
|
||
|
t += 4;
|
||
|
}
|
||
|
la = *a++;
|
||
|
}
|
||
|
|
||
|
cflush();
|
||
|
seek(cout, off, 0);
|
||
|
lput(t);
|
||
|
|
||
|
if(debug['v']){
|
||
|
Bprint(&bso, "import table entries = %d\n", imports);
|
||
|
Bprint(&bso, "export table entries = %d\n", exports);
|
||
|
}
|
||
|
}
|