plan9fox/sys/src/cmd/7l/mod.c
2019-04-08 14:05:27 +02:00

203 lines
3.7 KiB
C

#include "l.h"
void
readundefs(char *f, int t)
{
int i, n;
Sym *s;
Biobuf *b;
char *l, buf[256], *fields[64];
if(f == nil)
return;
b = Bopen(f, OREAD);
if(b == nil){
diag("could not open %s: %r", f);
errorexit();
}
while((l = Brdline(b, '\n')) != nil){
n = Blinelen(b);
if(n >= sizeof(buf)){
diag("%s: line too long", f);
errorexit();
}
memmove(buf, l, n);
buf[n-1] = '\0';
n = getfields(buf, fields, nelem(fields), 1, " \t\r\n");
if(n == nelem(fields)){
diag("%s: bad format", f);
errorexit();
}
for(i = 0; i < n; i++){
s = lookup(fields[i], 0);
s->type = SXREF;
s->subtype = t;
if(t == SIMPORT)
nimports++;
else
nexports++;
}
}
Bterm(b);
}
void
undefsym(Sym *s)
{
int n;
n = imports;
if(s->value != 0)
diag("value != 0 on SXREF");
if(n >= 1<<Rindex)
diag("import index %d out of range", n);
s->value = n<<Roffset;
s->type = SUNDEF;
imports++;
}
void
zerosig(char *sp)
{
Sym *s;
s = lookup(sp, 0);
s->sig = 0;
}
void
import(void)
{
int i;
Sym *s;
for(i = 0; i < NHASH; i++)
for(s = hash[i]; s != S; s = s->link)
if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){
undefsym(s);
Bprint(&bso, "IMPORT: %s sig=%lux v=%lld\n", s->name, s->sig, (vlong)s->value);
}
}
void
ckoff(Sym *s, long v)
{
if(v < 0 || v >= 1<<Roffset)
diag("relocation offset %ld for %s out of range", v, s->name);
}
static Prog*
newdata(Sym *s, int o, int w, int t)
{
Prog *p;
p = prg();
p->link = datap;
datap = p;
p->as = ADATA;
p->reg = w;
p->from.type = D_OREG;
p->from.name = t;
p->from.sym = s;
p->from.offset = o;
p->to.type = D_CONST;
p->to.name = D_NONE;
return p;
}
void
export(void)
{
int i, j, n, off, nb, sv, ne;
Sym *s, *et, *str, **esyms;
Prog *p;
char buf[NSNAME], *t;
n = 0;
for(i = 0; i < NHASH; i++)
for(s = hash[i]; s != S; s = s->link)
if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
n++;
esyms = malloc(n*sizeof(Sym*));
ne = n;
n = 0;
for(i = 0; i < NHASH; i++)
for(s = hash[i]; s != S; s = s->link)
if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
esyms[n++] = s;
for(i = 0; i < ne-1; i++)
for(j = i+1; j < ne; j++)
if(strcmp(esyms[i]->name, esyms[j]->name) > 0){
s = esyms[i];
esyms[i] = esyms[j];
esyms[j] = s;
}
nb = 0;
off = 0;
et = lookup(EXPTAB, 0);
if(et->type != 0 && et->type != SXREF)
diag("%s already defined", EXPTAB);
et->type = SDATA;
str = lookup(".string", 0);
if(str->type == 0)
str->type = SDATA;
sv = str->value;
for(i = 0; i < ne; i++){
s = esyms[i];
Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type);
/* signature */
p = newdata(et, off, sizeof(long), D_EXTERN);
off += sizeof(long);
p->to.offset = s->sig;
/* address */
p = newdata(et, off, sizeof(long), D_EXTERN);
off += sizeof(long);
p->to.name = D_EXTERN;
p->to.sym = s;
/* string */
t = s->name;
n = strlen(t)+1;
for(;;){
buf[nb++] = *t;
sv++;
if(nb >= NSNAME){
p = newdata(str, sv-NSNAME, NSNAME, D_STATIC);
p->to.type = D_SCONST;
p->to.sval = malloc(NSNAME);
memmove(p->to.sval, buf, NSNAME);
nb = 0;
}
if(*t++ == 0)
break;
}
/* name */
p = newdata(et, off, sizeof(long), D_EXTERN);
off += sizeof(long);
p->to.name = D_STATIC;
p->to.sym = str;
p->to.offset = sv-n;
}
if(nb > 0){
p = newdata(str, sv-nb, nb, D_STATIC);
p->to.type = D_SCONST;
p->to.sval = malloc(NSNAME);
memmove(p->to.sval, buf, nb);
}
for(i = 0; i < 3; i++){
newdata(et, off, sizeof(long), D_EXTERN);
off += sizeof(long);
}
et->value = off;
if(sv == 0)
sv = 1;
str->value = sv;
exports = ne;
free(esyms);
}