summaryrefslogtreecommitdiff
path: root/src/cmd/6l/span.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/6l/span.c')
-rw-r--r--src/cmd/6l/span.c42
1 files changed, 27 insertions, 15 deletions
diff --git a/src/cmd/6l/span.c b/src/cmd/6l/span.c
index 460a34f2f..74f11d635 100644
--- a/src/cmd/6l/span.c
+++ b/src/cmd/6l/span.c
@@ -358,6 +358,18 @@ prefixof(Adr *a)
case D_INDIR+D_GS:
return 0x65;
}
+ switch(a->index) {
+ case D_CS:
+ return 0x2e;
+ case D_DS:
+ return 0x3e;
+ case D_ES:
+ return 0x26;
+ case D_FS:
+ return 0x64;
+ case D_GS:
+ return 0x65;
+ }
return 0;
}
@@ -735,15 +747,20 @@ vaddr(Adr *a, Reloc *r)
diag("need reloc for %D", a);
errorexit();
}
- if(flag_shared)
- r->type = D_PCREL;
- else
- r->type = D_ADDR;
r->siz = 4; // TODO: 8 for external symbols
r->off = -1; // caller must fill in
r->sym = s;
r->add = v;
v = 0;
+ if(flag_shared) {
+ if(s->type == STLSBSS) {
+ r->xadd = r->add - r->siz;
+ r->type = D_TLS;
+ r->xsym = s;
+ } else
+ r->type = D_PCREL;
+ } else
+ r->type = D_ADDR;
}
return v;
}
@@ -760,7 +777,7 @@ asmandsz(Adr *a, int r, int rex, int m64)
v = a->offset;
t = a->type;
rel.siz = 0;
- if(a->index != D_NONE) {
+ if(a->index != D_NONE && a->index != D_FS && a->index != D_GS) {
if(t < D_INDIR) {
switch(t) {
default:
@@ -888,18 +905,11 @@ putrelv:
r = addrel(cursym);
r->off = curp->pc + andptr - and;
- r->add = 0;
- r->xadd = 0;
+ r->add = a->offset-tlsoffset;
+ r->xadd = r->add;
r->siz = 4;
r->type = D_TLS;
- if(a->offset == tlsoffset+0)
- s = lookup("runtime.g", 0);
- else
- s = lookup("runtime.m", 0);
- s->type = STLSBSS;
- s->reachable = 1;
- s->size = PtrSize;
- s->hide = 1;
+ s = lookup("runtime.tlsgm", 0);
r->sym = s;
r->xsym = s;
v = 0;
@@ -1227,6 +1237,8 @@ found:
break;
}
+ if(z >= nelem(o->op))
+ sysfatal("asmins bad table %P", p);
op = o->op[z];
if(op == 0x0f) {
*andptr++ = op;