summaryrefslogtreecommitdiff
path: root/src/cmd/ld
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/ld')
-rw-r--r--src/cmd/ld/data.c357
-rw-r--r--src/cmd/ld/decodesym.c38
-rw-r--r--src/cmd/ld/doc.go6
-rw-r--r--src/cmd/ld/dwarf.c156
-rw-r--r--src/cmd/ld/elf.c3
-rw-r--r--src/cmd/ld/ldelf.c8
-rw-r--r--src/cmd/ld/ldmacho.c4
-rw-r--r--src/cmd/ld/ldpe.c32
-rw-r--r--src/cmd/ld/lib.c91
-rw-r--r--src/cmd/ld/lib.h14
-rw-r--r--src/cmd/ld/macho.c3
-rw-r--r--src/cmd/ld/pass.c104
-rw-r--r--src/cmd/ld/pcln.c6
-rw-r--r--src/cmd/ld/pobj.c22
-rw-r--r--src/cmd/ld/symtab.c55
-rw-r--r--src/cmd/ld/textflag.h13
16 files changed, 564 insertions, 348 deletions
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index 55d020710..61847546a 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -35,7 +35,7 @@
#include "../ld/elf.h"
#include "../ld/macho.h"
#include "../ld/pe.h"
-#include "../../pkg/runtime/mgc0.h"
+#include "../../runtime/mgc0.h"
void dynreloc(void);
@@ -145,7 +145,7 @@ relocsym(LSym *s)
diag("%s: invalid relocation %d+%d not in [%d,%d)", s->name, off, siz, 0, s->np);
continue;
}
- if(r->sym != S && (r->sym->type & SMASK == 0 || r->sym->type & SMASK == SXREF)) {
+ if(r->sym != S && ((r->sym->type & (SMASK | SHIDDEN)) == 0 || (r->sym->type & SMASK) == SXREF)) {
diag("%s: not defined", r->sym->name);
continue;
}
@@ -160,6 +160,10 @@ relocsym(LSym *s)
if(r->sym != S && r->sym->type != STLSBSS && !r->sym->reachable)
diag("unreachable sym in relocation: %s %s", s->name, r->sym->name);
+ // Android emulates runtime.tlsg as a regular variable.
+ if (r->type == R_TLS && strcmp(goos, "android") == 0)
+ r->type = R_ADDR;
+
switch(r->type) {
default:
o = 0;
@@ -186,8 +190,8 @@ relocsym(LSym *s)
case R_TLS_LE:
if(linkmode == LinkExternal && iself && HEADTYPE != Hopenbsd) {
r->done = 0;
- r->sym = ctxt->gmsym;
- r->xsym = ctxt->gmsym;
+ r->sym = ctxt->tlsg;
+ r->xsym = ctxt->tlsg;
r->xadd = r->add;
o = 0;
if(thechar != '6')
@@ -200,8 +204,8 @@ relocsym(LSym *s)
case R_TLS_IE:
if(linkmode == LinkExternal && iself && HEADTYPE != Hopenbsd) {
r->done = 0;
- r->sym = ctxt->gmsym;
- r->xsym = ctxt->gmsym;
+ r->sym = ctxt->tlsg;
+ r->xsym = ctxt->tlsg;
r->xadd = r->add;
o = 0;
if(thechar != '6')
@@ -277,9 +281,13 @@ relocsym(LSym *s)
if(thechar == '6')
o = 0;
} else if(HEADTYPE == Hdarwin) {
- if(rs->type != SHOSTOBJ)
- o += symaddr(rs) - rs->sect->vaddr;
- o -= r->off; // WTF?
+ if(r->type == R_CALL) {
+ if(rs->type != SHOSTOBJ)
+ o += symaddr(rs) - rs->sect->vaddr;
+ o -= r->off; // relative to section offset, not symbol
+ } else {
+ o += r->siz;
+ }
} else {
diag("unhandled pcrel relocation for %s", headstring);
}
@@ -421,10 +429,10 @@ dynreloc(void)
}
static void
-blk(LSym *start, int32 addr, int32 size)
+blk(LSym *start, int64 addr, int64 size)
{
LSym *sym;
- int32 eaddr;
+ int64 eaddr;
uchar *p, *ep;
for(sym = start; sym != nil; sym = sym->next)
@@ -463,10 +471,10 @@ blk(LSym *start, int32 addr, int32 size)
}
void
-codeblk(int32 addr, int32 size)
+codeblk(int64 addr, int64 size)
{
LSym *sym;
- int32 eaddr, n;
+ int64 eaddr, n;
uchar *q;
if(debug['a'])
@@ -523,10 +531,10 @@ codeblk(int32 addr, int32 size)
}
void
-datblk(int32 addr, int32 size)
+datblk(int64 addr, int64 size)
{
LSym *sym;
- int32 i, eaddr;
+ int64 i, eaddr;
uchar *p, *ep;
char *typ, *rsname;
Reloc *r;
@@ -612,22 +620,26 @@ addstrdata(char *name, char *value)
{
LSym *s, *sp;
char *p;
+ uchar reachable;
p = smprint("%s.str", name);
sp = linklookup(ctxt, p, 0);
free(p);
addstring(sp, value);
+ sp->type = SRODATA;
s = linklookup(ctxt, name, 0);
s->size = 0;
s->dupok = 1;
+ reachable = s->reachable;
addaddr(ctxt, s, sp);
- adduint32(ctxt, s, strlen(value));
- if(PtrSize == 8)
- adduint32(ctxt, s, 0); // round struct to pointer width
+ adduintxx(ctxt, s, strlen(value), PtrSize);
- // in case reachability has already been computed
- sp->reachable = s->reachable;
+ // addstring, addaddr, etc., mark the symbols as reachable.
+ // In this case that is not necessarily true, so stick to what
+ // we know before entering this function.
+ s->reachable = reachable;
+ sp->reachable = reachable;
}
vlong
@@ -702,31 +714,176 @@ maxalign(LSym *s, int type)
return max;
}
+// Helper object for building GC type programs.
+typedef struct ProgGen ProgGen;
+struct ProgGen
+{
+ LSym* s;
+ int32 datasize;
+ uint8 data[256/PointersPerByte];
+ vlong pos;
+};
+
static void
-gcaddsym(LSym *gc, LSym *s, vlong off)
+proggeninit(ProgGen *g, LSym *s)
{
- vlong a;
- LSym *gotype;
+ g->s = s;
+ g->datasize = 0;
+ g->pos = 0;
+ memset(g->data, 0, sizeof(g->data));
+}
- if(s->size < PtrSize)
+static void
+proggenemit(ProgGen *g, uint8 v)
+{
+ adduint8(ctxt, g->s, v);
+}
+
+// Writes insData block from g->data.
+static void
+proggendataflush(ProgGen *g)
+{
+ int32 i, s;
+
+ if(g->datasize == 0)
return;
- if(strcmp(s->name, ".string") == 0)
+ proggenemit(g, insData);
+ proggenemit(g, g->datasize);
+ s = (g->datasize + PointersPerByte - 1)/PointersPerByte;
+ for(i = 0; i < s; i++)
+ proggenemit(g, g->data[i]);
+ g->datasize = 0;
+ memset(g->data, 0, sizeof(g->data));
+}
+
+static void
+proggendata(ProgGen *g, uint8 d)
+{
+ g->data[g->datasize/PointersPerByte] |= d << ((g->datasize%PointersPerByte)*BitsPerPointer);
+ g->datasize++;
+ if(g->datasize == 255)
+ proggendataflush(g);
+}
+
+// Skip v bytes due to alignment, etc.
+static void
+proggenskip(ProgGen *g, vlong off, vlong v)
+{
+ vlong i;
+
+ for(i = off; i < off+v; i++) {
+ if((i%PtrSize) == 0)
+ proggendata(g, BitsScalar);
+ }
+}
+
+// Emit insArray instruction.
+static void
+proggenarray(ProgGen *g, vlong len)
+{
+ int32 i;
+
+ proggendataflush(g);
+ proggenemit(g, insArray);
+ for(i = 0; i < PtrSize; i++, len >>= 8)
+ proggenemit(g, len);
+}
+
+static void
+proggenarrayend(ProgGen *g)
+{
+ proggendataflush(g);
+ proggenemit(g, insArrayEnd);
+}
+
+static void
+proggenfini(ProgGen *g, vlong size)
+{
+ proggenskip(g, g->pos, size - g->pos);
+ proggendataflush(g);
+ proggenemit(g, insEnd);
+}
+
+
+// This function generates GC pointer info for global variables.
+static void
+proggenaddsym(ProgGen *g, LSym *s)
+{
+ LSym *gcprog;
+ uint8 *mask;
+ vlong i, size;
+
+ if(s->size == 0)
return;
- gotype = s->gotype;
- if(gotype != nil) {
- //print("gcaddsym: %s %d %s\n", s->name, s->size, gotype->name);
- adduintxx(ctxt, gc, GC_CALL, PtrSize);
- adduintxx(ctxt, gc, off, PtrSize);
- addpcrelplus(ctxt, gc, decodetype_gc(gotype), 3*PtrSize+4);
- if(PtrSize == 8)
- adduintxx(ctxt, gc, 0, 4);
- } else {
- //print("gcaddsym: %s %d <unknown type>\n", s->name, s->size);
- for(a = -off&(PtrSize-1); a+PtrSize<=s->size; a+=PtrSize) {
- adduintxx(ctxt, gc, GC_APTR, PtrSize);
- adduintxx(ctxt, gc, off+a, PtrSize);
+ // Skip alignment hole from the previous symbol.
+ proggenskip(g, g->pos, s->value - g->pos);
+ g->pos += s->value - g->pos;
+
+ // The test for names beginning with . here is meant
+ // to keep .dynamic and .dynsym from turning up as
+ // conservative symbols. They should be marked SELFSECT
+ // and not SDATA, but sometimes that doesn't happen.
+ // Leave debugging the SDATA issue for the Go rewrite.
+
+ if(s->gotype == nil && s->size >= PtrSize && s->name[0] != '.') {
+ // conservative scan
+ diag("missing Go type information for global symbol: %s size %d", s->name, (int)s->size);
+ if((s->size%PtrSize) || (g->pos%PtrSize))
+ diag("proggenaddsym: unaligned conservative symbol %s: size=%lld pos=%lld",
+ s->name, s->size, g->pos);
+ size = (s->size+PtrSize-1)/PtrSize*PtrSize;
+ if(size < 32*PtrSize) {
+ // Emit small symbols as data.
+ for(i = 0; i < size/PtrSize; i++)
+ proggendata(g, BitsPointer);
+ } else {
+ // Emit large symbols as array.
+ proggenarray(g, size/PtrSize);
+ proggendata(g, BitsPointer);
+ proggenarrayend(g);
+ }
+ g->pos = s->value + size;
+ } else if(s->gotype == nil || decodetype_noptr(s->gotype) || s->size < PtrSize || s->name[0] == '.') {
+ // no scan
+ if(s->size < 32*PtrSize) {
+ // Emit small symbols as data.
+ // This case also handles unaligned and tiny symbols, so tread carefully.
+ for(i = s->value; i < s->value+s->size; i++) {
+ if((i%PtrSize) == 0)
+ proggendata(g, BitsScalar);
+ }
+ } else {
+ // Emit large symbols as array.
+ if((s->size%PtrSize) || (g->pos%PtrSize))
+ diag("proggenaddsym: unaligned noscan symbol %s: size=%lld pos=%lld",
+ s->name, s->size, g->pos);
+ proggenarray(g, s->size/PtrSize);
+ proggendata(g, BitsScalar);
+ proggenarrayend(g);
}
+ g->pos = s->value + s->size;
+ } else if(decodetype_usegcprog(s->gotype)) {
+ // gc program, copy directly
+ proggendataflush(g);
+ gcprog = decodetype_gcprog(s->gotype);
+ size = decodetype_size(s->gotype);
+ if((size%PtrSize) || (g->pos%PtrSize))
+ diag("proggenaddsym: unaligned gcprog symbol %s: size=%lld pos=%lld",
+ s->name, s->size, g->pos);
+ for(i = 0; i < gcprog->np-1; i++)
+ proggenemit(g, gcprog->p[i]);
+ g->pos = s->value + size;
+ } else {
+ // gc mask, it's small so emit as data
+ mask = decodetype_gcmask(s->gotype);
+ size = decodetype_size(s->gotype);
+ if((size%PtrSize) || (g->pos%PtrSize))
+ diag("proggenaddsym: unaligned gcmask symbol %s: size=%lld pos=%lld",
+ s->name, s->size, g->pos);
+ for(i = 0; i < size; i += PtrSize)
+ proggendata(g, (mask[i/PtrSize/2]>>((i/PtrSize%2)*4+2))&BitsMask);
+ g->pos = s->value + size;
}
}
@@ -751,19 +908,13 @@ dodata(void)
Section *sect;
Segment *segro;
LSym *s, *last, **l;
- LSym *gcdata1, *gcbss1;
+ LSym *gcdata, *gcbss;
+ ProgGen gen;
if(debug['v'])
Bprint(&bso, "%5.2f dodata\n", cputime());
Bflush(&bso);
- gcdata1 = linklookup(ctxt, "gcdata", 0);
- gcbss1 = linklookup(ctxt, "gcbss", 0);
-
- // size of .data and .bss section. the zero value is later replaced by the actual size of the section.
- adduintxx(ctxt, gcdata1, 0, PtrSize);
- adduintxx(ctxt, gcbss1, 0, PtrSize);
-
last = nil;
datap = nil;
@@ -847,8 +998,8 @@ dodata(void)
sect->align = maxalign(s, SINITARR-1);
datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
- linklookup(ctxt, "noptrdata", 0)->sect = sect;
- linklookup(ctxt, "enoptrdata", 0)->sect = sect;
+ linklookup(ctxt, "runtime.noptrdata", 0)->sect = sect;
+ linklookup(ctxt, "runtime.enoptrdata", 0)->sect = sect;
for(; s != nil && s->type < SINITARR; s = s->next) {
datsize = aligndatsize(datsize, s);
s->sect = sect;
@@ -878,8 +1029,10 @@ dodata(void)
sect->align = maxalign(s, SBSS-1);
datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
- linklookup(ctxt, "data", 0)->sect = sect;
- linklookup(ctxt, "edata", 0)->sect = sect;
+ linklookup(ctxt, "runtime.data", 0)->sect = sect;
+ linklookup(ctxt, "runtime.edata", 0)->sect = sect;
+ gcdata = linklookup(ctxt, "runtime.gcdata", 0);
+ proggeninit(&gen, gcdata);
for(; s != nil && s->type < SBSS; s = s->next) {
if(s->type == SINITARR) {
ctxt->cursym = s;
@@ -889,40 +1042,38 @@ dodata(void)
s->type = SDATA;
datsize = aligndatsize(datsize, s);
s->value = datsize - sect->vaddr;
- gcaddsym(gcdata1, s, datsize - sect->vaddr); // gc
+ proggenaddsym(&gen, s); // gc
growdatsize(&datsize, s);
}
sect->len = datsize - sect->vaddr;
-
- adduintxx(ctxt, gcdata1, GC_END, PtrSize);
- setuintxx(ctxt, gcdata1, 0, sect->len, PtrSize);
+ proggenfini(&gen, sect->len); // gc
/* bss */
sect = addsection(&segdata, ".bss", 06);
sect->align = maxalign(s, SNOPTRBSS-1);
datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
- linklookup(ctxt, "bss", 0)->sect = sect;
- linklookup(ctxt, "ebss", 0)->sect = sect;
+ linklookup(ctxt, "runtime.bss", 0)->sect = sect;
+ linklookup(ctxt, "runtime.ebss", 0)->sect = sect;
+ gcbss = linklookup(ctxt, "runtime.gcbss", 0);
+ proggeninit(&gen, gcbss);
for(; s != nil && s->type < SNOPTRBSS; s = s->next) {
s->sect = sect;
datsize = aligndatsize(datsize, s);
s->value = datsize - sect->vaddr;
- gcaddsym(gcbss1, s, datsize - sect->vaddr); // gc
+ proggenaddsym(&gen, s); // gc
growdatsize(&datsize, s);
}
sect->len = datsize - sect->vaddr;
-
- adduintxx(ctxt, gcbss1, GC_END, PtrSize);
- setuintxx(ctxt, gcbss1, 0, sect->len, PtrSize);
+ proggenfini(&gen, sect->len); // gc
/* pointer-free bss */
sect = addsection(&segdata, ".noptrbss", 06);
sect->align = maxalign(s, SNOPTRBSS);
datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
- linklookup(ctxt, "noptrbss", 0)->sect = sect;
- linklookup(ctxt, "enoptrbss", 0)->sect = sect;
+ linklookup(ctxt, "runtime.noptrbss", 0)->sect = sect;
+ linklookup(ctxt, "runtime.enoptrbss", 0)->sect = sect;
for(; s != nil && s->type == SNOPTRBSS; s = s->next) {
datsize = aligndatsize(datsize, s);
s->sect = sect;
@@ -930,7 +1081,7 @@ dodata(void)
growdatsize(&datsize, s);
}
sect->len = datsize - sect->vaddr;
- linklookup(ctxt, "end", 0)->sect = sect;
+ linklookup(ctxt, "runtime.end", 0)->sect = sect;
// 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
if(datsize != (uint32)datsize) {
@@ -951,9 +1102,9 @@ dodata(void)
sect->len = datsize;
} else {
// Might be internal linking but still using cgo.
- // In that case, the only possible STLSBSS symbol is tlsgm.
+ // In that case, the only possible STLSBSS symbol is runtime.tlsg.
// Give it offset 0, because it's the only thing here.
- if(s != nil && s->type == STLSBSS && strcmp(s->name, "runtime.tlsgm") == 0) {
+ if(s != nil && s->type == STLSBSS && strcmp(s->name, "runtime.tlsg") == 0) {
s->value = 0;
s = s->next;
}
@@ -1001,8 +1152,8 @@ dodata(void)
sect->align = maxalign(s, STYPELINK-1);
datsize = rnd(datsize, sect->align);
sect->vaddr = 0;
- linklookup(ctxt, "rodata", 0)->sect = sect;
- linklookup(ctxt, "erodata", 0)->sect = sect;
+ linklookup(ctxt, "runtime.rodata", 0)->sect = sect;
+ linklookup(ctxt, "runtime.erodata", 0)->sect = sect;
for(; s != nil && s->type < STYPELINK; s = s->next) {
datsize = aligndatsize(datsize, s);
s->sect = sect;
@@ -1017,8 +1168,8 @@ dodata(void)
sect->align = maxalign(s, STYPELINK);
datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
- linklookup(ctxt, "typelink", 0)->sect = sect;
- linklookup(ctxt, "etypelink", 0)->sect = sect;
+ linklookup(ctxt, "runtime.typelink", 0)->sect = sect;
+ linklookup(ctxt, "runtime.etypelink", 0)->sect = sect;
for(; s != nil && s->type == STYPELINK; s = s->next) {
datsize = aligndatsize(datsize, s);
s->sect = sect;
@@ -1033,8 +1184,8 @@ dodata(void)
sect->align = maxalign(s, SPCLNTAB-1);
datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
- linklookup(ctxt, "symtab", 0)->sect = sect;
- linklookup(ctxt, "esymtab", 0)->sect = sect;
+ linklookup(ctxt, "runtime.symtab", 0)->sect = sect;
+ linklookup(ctxt, "runtime.esymtab", 0)->sect = sect;
for(; s != nil && s->type < SPCLNTAB; s = s->next) {
datsize = aligndatsize(datsize, s);
s->sect = sect;
@@ -1049,8 +1200,8 @@ dodata(void)
sect->align = maxalign(s, SELFROSECT-1);
datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
- linklookup(ctxt, "pclntab", 0)->sect = sect;
- linklookup(ctxt, "epclntab", 0)->sect = sect;
+ linklookup(ctxt, "runtime.pclntab", 0)->sect = sect;
+ linklookup(ctxt, "runtime.epclntab", 0)->sect = sect;
for(; s != nil && s->type < SELFROSECT; s = s->next) {
datsize = aligndatsize(datsize, s);
s->sect = sect;
@@ -1103,8 +1254,8 @@ textaddress(void)
// and then letting threads copy down, but probably not worth it.
sect = segtext.sect;
sect->align = funcalign;
- linklookup(ctxt, "text", 0)->sect = sect;
- linklookup(ctxt, "etext", 0)->sect = sect;
+ linklookup(ctxt, "runtime.text", 0)->sect = sect;
+ linklookup(ctxt, "runtime.etext", 0)->sect = sect;
va = INITTEXT;
sect->vaddr = va;
for(sym = ctxt->textp; sym != nil; sym = sym->next) {
@@ -1215,32 +1366,32 @@ address(void)
sub->value += sym->value;
}
- xdefine("text", STEXT, text->vaddr);
- xdefine("etext", STEXT, text->vaddr + text->len);
- xdefine("rodata", SRODATA, rodata->vaddr);
- xdefine("erodata", SRODATA, rodata->vaddr + rodata->len);
- xdefine("typelink", SRODATA, typelink->vaddr);
- xdefine("etypelink", SRODATA, typelink->vaddr + typelink->len);
-
- sym = linklookup(ctxt, "gcdata", 0);
- xdefine("egcdata", SRODATA, symaddr(sym) + sym->size);
- linklookup(ctxt, "egcdata", 0)->sect = sym->sect;
-
- sym = linklookup(ctxt, "gcbss", 0);
- xdefine("egcbss", SRODATA, symaddr(sym) + sym->size);
- linklookup(ctxt, "egcbss", 0)->sect = sym->sect;
-
- xdefine("symtab", SRODATA, symtab->vaddr);
- xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len);
- xdefine("pclntab", SRODATA, pclntab->vaddr);
- xdefine("epclntab", SRODATA, pclntab->vaddr + pclntab->len);
- xdefine("noptrdata", SNOPTRDATA, noptr->vaddr);
- xdefine("enoptrdata", SNOPTRDATA, noptr->vaddr + noptr->len);
- xdefine("bss", SBSS, bss->vaddr);
- xdefine("ebss", SBSS, bss->vaddr + bss->len);
- xdefine("data", SDATA, data->vaddr);
- xdefine("edata", SDATA, data->vaddr + data->len);
- xdefine("noptrbss", SNOPTRBSS, noptrbss->vaddr);
- xdefine("enoptrbss", SNOPTRBSS, noptrbss->vaddr + noptrbss->len);
- xdefine("end", SBSS, segdata.vaddr + segdata.len);
+ xdefine("runtime.text", STEXT, text->vaddr);
+ xdefine("runtime.etext", STEXT, text->vaddr + text->len);
+ xdefine("runtime.rodata", SRODATA, rodata->vaddr);
+ xdefine("runtime.erodata", SRODATA, rodata->vaddr + rodata->len);
+ xdefine("runtime.typelink", SRODATA, typelink->vaddr);
+ xdefine("runtime.etypelink", SRODATA, typelink->vaddr + typelink->len);
+
+ sym = linklookup(ctxt, "runtime.gcdata", 0);
+ xdefine("runtime.egcdata", SRODATA, symaddr(sym) + sym->size);
+ linklookup(ctxt, "runtime.egcdata", 0)->sect = sym->sect;
+
+ sym = linklookup(ctxt, "runtime.gcbss", 0);
+ xdefine("runtime.egcbss", SRODATA, symaddr(sym) + sym->size);
+ linklookup(ctxt, "runtime.egcbss", 0)->sect = sym->sect;
+
+ xdefine("runtime.symtab", SRODATA, symtab->vaddr);
+ xdefine("runtime.esymtab", SRODATA, symtab->vaddr + symtab->len);
+ xdefine("runtime.pclntab", SRODATA, pclntab->vaddr);
+ xdefine("runtime.epclntab", SRODATA, pclntab->vaddr + pclntab->len);
+ xdefine("runtime.noptrdata", SNOPTRDATA, noptr->vaddr);
+ xdefine("runtime.enoptrdata", SNOPTRDATA, noptr->vaddr + noptr->len);
+ xdefine("runtime.bss", SBSS, bss->vaddr);
+ xdefine("runtime.ebss", SBSS, bss->vaddr + bss->len);
+ xdefine("runtime.data", SDATA, data->vaddr);
+ xdefine("runtime.edata", SDATA, data->vaddr + data->len);
+ xdefine("runtime.noptrbss", SNOPTRBSS, noptrbss->vaddr);
+ xdefine("runtime.enoptrbss", SNOPTRBSS, noptrbss->vaddr + noptrbss->len);
+ xdefine("runtime.end", SBSS, segdata.vaddr + segdata.len);
}
diff --git a/src/cmd/ld/decodesym.c b/src/cmd/ld/decodesym.c
index da48d3786..037263dce 100644
--- a/src/cmd/ld/decodesym.c
+++ b/src/cmd/ld/decodesym.c
@@ -4,10 +4,10 @@
#include "l.h"
#include "lib.h"
-#include "../../pkg/runtime/typekind.h"
+#include "../../runtime/typekind.h"
// Decoding the type.* symbols. This has to be in sync with
-// ../../pkg/runtime/type.go, or more specificaly, with what
+// ../../runtime/type.go, or more specificaly, with what
// ../gc/reflect.c stuffs in these.
static Reloc*
@@ -70,14 +70,28 @@ decode_inuxi(uchar* p, int sz)
static int
commonsize(void)
{
- return 7*PtrSize + 8;
+ return 8*PtrSize + 8;
}
// Type.commonType.kind
uint8
decodetype_kind(LSym *s)
{
- return s->p[1*PtrSize + 7] & ~KindNoPointers; // 0x13 / 0x1f
+ return s->p[1*PtrSize + 7] & KindMask; // 0x13 / 0x1f
+}
+
+// Type.commonType.kind
+uint8
+decodetype_noptr(LSym *s)
+{
+ return s->p[1*PtrSize + 7] & KindNoPointers; // 0x13 / 0x1f
+}
+
+// Type.commonType.kind
+uint8
+decodetype_usegcprog(LSym *s)
+{
+ return s->p[1*PtrSize + 7] & KindGCProg; // 0x13 / 0x1f
}
// Type.commonType.size
@@ -89,9 +103,18 @@ decodetype_size(LSym *s)
// Type.commonType.gc
LSym*
-decodetype_gc(LSym *s)
+decodetype_gcprog(LSym *s)
{
- return decode_reloc_sym(s, 1*PtrSize + 8 + 1*PtrSize);
+ return decode_reloc_sym(s, 1*PtrSize + 8 + 2*PtrSize);
+}
+
+uint8*
+decodetype_gcmask(LSym *s)
+{
+ LSym *mask;
+
+ mask = decode_reloc_sym(s, 1*PtrSize + 8 + 1*PtrSize);
+ return mask->p;
}
// Type.ArrayType.elem and Type.SliceType.Elem
@@ -104,7 +127,7 @@ decodetype_arrayelem(LSym *s)
vlong
decodetype_arraylen(LSym *s)
{
- return decode_inuxi(s->p + commonsize()+PtrSize, PtrSize);
+ return decode_inuxi(s->p + commonsize()+2*PtrSize, PtrSize);
}
// Type.PtrType.elem
@@ -120,6 +143,7 @@ decodetype_mapkey(LSym *s)
{
return decode_reloc_sym(s, commonsize()); // 0x1c / 0x30
}
+
LSym*
decodetype_mapvalue(LSym *s)
{
diff --git a/src/cmd/ld/doc.go b/src/cmd/ld/doc.go
index 8135bd549..5b5833db5 100644
--- a/src/cmd/ld/doc.go
+++ b/src/cmd/ld/doc.go
@@ -63,9 +63,9 @@ Options new in this version:
-w
Omit the DWARF symbol table.
-X symbol value
- Set the value of an otherwise uninitialized string variable.
- The symbol name should be of the form importpath.name,
- as displayed in the symbol table printed by "go tool nm".
+ Set the value of a string variable. The symbol name
+ should be of the form importpath.name, as displayed
+ in the symbol table printed by "go tool nm".
-race
Link with race detection libraries.
-B value
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index cc77b45cd..a3ba52325 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -19,7 +19,7 @@
#include "../ld/elf.h"
#include "../ld/macho.h"
#include "../ld/pe.h"
-#include "../../pkg/runtime/typekind.h"
+#include "../../runtime/typekind.h"
/*
* Offsets and sizes of the debug_* sections in the cout file.
@@ -141,16 +141,22 @@ sleb128put(vlong v)
* only a handful of them. The DWARF spec places no restriction on
* the ordering of attributes in the Abbrevs and DIEs, and we will
* always write them out in the order of declaration in the abbrev.
- * This implementation relies on tag, attr < 127, so they serialize as
- * a char. Higher numbered user-defined tags or attributes can be used
- * for storing internal data but won't be serialized.
*/
typedef struct DWAttrForm DWAttrForm;
struct DWAttrForm {
- uint8 attr;
+ uint16 attr;
uint8 form;
};
+// Go-specific type attributes.
+enum {
+ DW_AT_go_kind = 0x2900,
+ DW_AT_go_key = 0x2901,
+ DW_AT_go_elem = 0x2902,
+
+ DW_AT_internal_location = 253, // params and locals; not emitted
+};
+
// Index into the abbrevs table below.
// Keep in sync with ispubname() and ispubtype() below.
// ispubtype considers >= NULLTYPE public
@@ -260,7 +266,7 @@ static struct DWAbbrev {
DW_TAG_subrange_type, DW_CHILDREN_no,
// No name!
DW_AT_type, DW_FORM_ref_addr,
- DW_AT_upper_bound, DW_FORM_data1,
+ DW_AT_count, DW_FORM_udata,
0, 0
},
@@ -277,6 +283,7 @@ static struct DWAbbrev {
DW_AT_name, DW_FORM_string,
DW_AT_encoding, DW_FORM_data1,
DW_AT_byte_size, DW_FORM_data1,
+ DW_AT_go_kind, DW_FORM_data1,
0, 0
},
/* ARRAYTYPE */
@@ -286,6 +293,7 @@ static struct DWAbbrev {
DW_AT_name, DW_FORM_string,
DW_AT_type, DW_FORM_ref_addr,
DW_AT_byte_size, DW_FORM_udata,
+ DW_AT_go_kind, DW_FORM_data1,
0, 0
},
@@ -294,6 +302,8 @@ static struct DWAbbrev {
DW_TAG_typedef, DW_CHILDREN_no,
DW_AT_name, DW_FORM_string,
DW_AT_type, DW_FORM_ref_addr,
+ DW_AT_go_kind, DW_FORM_data1,
+ DW_AT_go_elem, DW_FORM_ref_addr,
0, 0
},
@@ -302,6 +312,7 @@ static struct DWAbbrev {
DW_TAG_subroutine_type, DW_CHILDREN_yes,
DW_AT_name, DW_FORM_string,
// DW_AT_type, DW_FORM_ref_addr,
+ DW_AT_go_kind, DW_FORM_data1,
0, 0
},
@@ -310,6 +321,7 @@ static struct DWAbbrev {
DW_TAG_typedef, DW_CHILDREN_yes,
DW_AT_name, DW_FORM_string,
DW_AT_type, DW_FORM_ref_addr,
+ DW_AT_go_kind, DW_FORM_data1,
0, 0
},
@@ -318,6 +330,9 @@ static struct DWAbbrev {
DW_TAG_typedef, DW_CHILDREN_no,
DW_AT_name, DW_FORM_string,
DW_AT_type, DW_FORM_ref_addr,
+ DW_AT_go_kind, DW_FORM_data1,
+ DW_AT_go_key, DW_FORM_ref_addr,
+ DW_AT_go_elem, DW_FORM_ref_addr,
0, 0
},
@@ -326,6 +341,7 @@ static struct DWAbbrev {
DW_TAG_pointer_type, DW_CHILDREN_no,
DW_AT_name, DW_FORM_string,
DW_AT_type, DW_FORM_ref_addr,
+ DW_AT_go_kind, DW_FORM_data1,
0, 0
},
/* BARE_PTRTYPE */
@@ -340,6 +356,8 @@ static struct DWAbbrev {
DW_TAG_structure_type, DW_CHILDREN_yes,
DW_AT_name, DW_FORM_string,
DW_AT_byte_size, DW_FORM_udata,
+ DW_AT_go_kind, DW_FORM_data1,
+ DW_AT_go_elem, DW_FORM_ref_addr,
0, 0
},
@@ -348,6 +366,7 @@ static struct DWAbbrev {
DW_TAG_structure_type, DW_CHILDREN_yes,
DW_AT_name, DW_FORM_string,
DW_AT_byte_size, DW_FORM_udata,
+ DW_AT_go_kind, DW_FORM_data1,
0, 0
},
@@ -356,6 +375,7 @@ static struct DWAbbrev {
DW_TAG_structure_type, DW_CHILDREN_yes,
DW_AT_name, DW_FORM_string,
DW_AT_byte_size, DW_FORM_udata,
+ DW_AT_go_kind, DW_FORM_data1,
0, 0
},
@@ -371,7 +391,8 @@ static struct DWAbbrev {
static void
writeabbrev(void)
{
- int i, n;
+ int i, j;
+ DWAttrForm *f;
abbrevo = cpos();
for (i = 1; i < DW_NABRV; i++) {
@@ -379,11 +400,13 @@ writeabbrev(void)
uleb128put(i);
uleb128put(abbrevs[i].tag);
cput(abbrevs[i].children);
- // 0 is not a valid attr or form, and DWAbbrev.attr is
- // 0-terminated, so we can treat it as a string
- n = strlen((char*)abbrevs[i].attr) / 2;
- strnput((char*)abbrevs[i].attr,
- (n+1) * sizeof(DWAttrForm));
+ for(j=0; j<nelem(abbrevs[i].attr); j++) {
+ f = &abbrevs[i].attr[j];
+ uleb128put(f->attr);
+ uleb128put(f->form);
+ if(f->attr == 0)
+ break;
+ }
}
cput(0);
abbrevsize = cpos() - abbrevo;
@@ -417,7 +440,7 @@ hashstr(char* s)
typedef struct DWAttr DWAttr;
struct DWAttr {
DWAttr *link;
- uint8 atr; // DW_AT_
+ uint16 atr; // DW_AT_
uint8 cls; // DW_CLS_
vlong value;
char *data;
@@ -445,7 +468,7 @@ static DWDie dwtypes;
static DWDie dwglobals;
static DWAttr*
-newattr(DWDie *die, uint8 attr, int cls, vlong value, char *data)
+newattr(DWDie *die, uint16 attr, int cls, vlong value, char *data)
{
DWAttr *a;
@@ -463,7 +486,7 @@ newattr(DWDie *die, uint8 attr, int cls, vlong value, char *data)
// name. getattr moves the desired one to the front so
// frequently searched ones are found faster.
static DWAttr*
-getattr(DWDie *die, uint8 attr)
+getattr(DWDie *die, uint16 attr)
{
DWAttr *a, *b;
@@ -622,7 +645,7 @@ adddwarfrel(LSym* sec, LSym* sym, vlong offsetbase, int siz, vlong addend)
}
static DWAttr*
-newrefattr(DWDie *die, uint8 attr, DWDie* ref)
+newrefattr(DWDie *die, uint16 attr, DWDie* ref)
{
if (ref == nil)
return nil;
@@ -762,22 +785,22 @@ putattr(int abbrev, int form, int cls, vlong value, char *data)
static void
putattrs(int abbrev, DWAttr* attr)
{
- DWAttr *attrs[DW_AT_recursive + 1];
DWAttrForm* af;
-
- memset(attrs, 0, sizeof attrs);
- for( ; attr; attr = attr->link)
- if (attr->atr < nelem(attrs))
- attrs[attr->atr] = attr;
-
- for(af = abbrevs[abbrev].attr; af->attr; af++)
- if (attrs[af->attr])
- putattr(abbrev, af->form,
- attrs[af->attr]->cls,
- attrs[af->attr]->value,
- attrs[af->attr]->data);
- else
- putattr(abbrev, af->form, 0, 0, nil);
+ DWAttr *ap;
+
+ for(af = abbrevs[abbrev].attr; af->attr; af++) {
+ for(ap=attr; ap; ap=ap->link) {
+ if(ap->atr == af->attr) {
+ putattr(abbrev, af->form,
+ ap->cls,
+ ap->value,
+ ap->data);
+ goto done;
+ }
+ }
+ putattr(abbrev, af->form, 0, 0, nil);
+ done:;
+ }
}
static void putdie(DWDie* die);
@@ -835,11 +858,8 @@ newmemberoffsetattr(DWDie *die, int32 offs)
int i;
i = 0;
- if (offs != 0) {
- block[i++] = DW_OP_consts;
- i += sleb128enc(offs, block+i);
- block[i++] = DW_OP_plus;
- }
+ block[i++] = DW_OP_plus_uconst;
+ i += uleb128enc(offs, block+i);
newattr(die, DW_AT_data_member_location, DW_CLS_BLOCK, i, mal(i));
memmove(die->attr->data, block, i);
}
@@ -852,15 +872,6 @@ newabslocexprattr(DWDie *die, vlong addr, LSym *sym)
newattr(die, DW_AT_location, DW_CLS_ADDRESS, addr, (char*)sym);
}
-
-// Fake attributes for slices, maps and channel
-enum {
- DW_AT_internal_elem_type = 250, // channels and slices
- DW_AT_internal_key_type = 251, // maps
- DW_AT_internal_val_type = 252, // maps
- DW_AT_internal_location = 253, // params and locals
-};
-
static DWDie* defptrto(DWDie *dwtype); // below
// Lookup predefined types
@@ -981,7 +992,8 @@ defgotype(LSym *gotype)
s = decodetype_arrayelem(gotype);
newrefattr(die, DW_AT_type, defgotype(s));
fld = newdie(die, DW_ABRV_ARRAYRANGE, "range");
- newattr(fld, DW_AT_upper_bound, DW_CLS_CONSTANT, decodetype_arraylen(gotype), 0);
+ // use actual length not upper bound; correct for 0-length arrays.
+ newattr(fld, DW_AT_count, DW_CLS_CONSTANT, decodetype_arraylen(gotype), 0);
newrefattr(fld, DW_AT_type, find_or_diag(&dwtypes, "uintptr"));
break;
@@ -989,7 +1001,7 @@ defgotype(LSym *gotype)
die = newdie(&dwtypes, DW_ABRV_CHANTYPE, name);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
s = decodetype_chanelem(gotype);
- newrefattr(die, DW_AT_internal_elem_type, defgotype(s));
+ newrefattr(die, DW_AT_go_elem, defgotype(s));
break;
case KindFunc:
@@ -1027,9 +1039,9 @@ defgotype(LSym *gotype)
case KindMap:
die = newdie(&dwtypes, DW_ABRV_MAPTYPE, name);
s = decodetype_mapkey(gotype);
- newrefattr(die, DW_AT_internal_key_type, defgotype(s));
+ newrefattr(die, DW_AT_go_key, defgotype(s));
s = decodetype_mapvalue(gotype);
- newrefattr(die, DW_AT_internal_val_type, defgotype(s));
+ newrefattr(die, DW_AT_go_elem, defgotype(s));
break;
case KindPtr:
@@ -1044,7 +1056,7 @@ defgotype(LSym *gotype)
dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
s = decodetype_arrayelem(gotype);
- newrefattr(die, DW_AT_internal_elem_type, defgotype(s));
+ newrefattr(die, DW_AT_go_elem, defgotype(s));
break;
case KindString:
@@ -1076,7 +1088,9 @@ defgotype(LSym *gotype)
diag("dwarf: definition of unknown kind %d: %s", kind, gotype->name);
die = newdie(&dwtypes, DW_ABRV_TYPEDECL, name);
newrefattr(die, DW_AT_type, find_or_diag(&dwtypes, "<unspecified>"));
- }
+ }
+
+ newattr(die, DW_AT_go_kind, DW_CLS_CONSTANT, kind, 0);
return die;
}
@@ -1171,7 +1185,7 @@ synthesizeslicetypes(DWDie *die)
if (die->abbrev != DW_ABRV_SLICETYPE)
continue;
copychildren(die, prototype);
- elem = (DWDie*) getattr(die, DW_AT_internal_elem_type)->data;
+ elem = (DWDie*) getattr(die, DW_AT_go_elem)->data;
substitutetype(die, "array", defptrto(elem));
}
}
@@ -1208,7 +1222,7 @@ synthesizemaptypes(DWDie *die)
DWAttr *a;
hash = walktypedef(defgotype(lookup_or_diag("type.runtime.hmap")));
- bucket = walktypedef(defgotype(lookup_or_diag("type.runtime.bucket")));
+ bucket = walktypedef(defgotype(lookup_or_diag("type.runtime.bmap")));
if (hash == nil)
return;
@@ -1217,8 +1231,8 @@ synthesizemaptypes(DWDie *die)
if (die->abbrev != DW_ABRV_MAPTYPE)
continue;
- keytype = walktypedef((DWDie*) getattr(die, DW_AT_internal_key_type)->data);
- valtype = walktypedef((DWDie*) getattr(die, DW_AT_internal_val_type)->data);
+ keytype = walktypedef((DWDie*) getattr(die, DW_AT_go_key)->data);
+ valtype = walktypedef((DWDie*) getattr(die, DW_AT_go_elem)->data);
// compute size info like hashmap.c does.
a = getattr(keytype, DW_AT_byte_size);
@@ -1243,7 +1257,7 @@ synthesizemaptypes(DWDie *die)
newattr(dwhk, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize * keysize, 0);
newrefattr(dwhk, DW_AT_type, indirect_key ? defptrto(keytype) : keytype);
fld = newdie(dwhk, DW_ABRV_ARRAYRANGE, "size");
- newattr(fld, DW_AT_upper_bound, DW_CLS_CONSTANT, BucketSize, 0);
+ newattr(fld, DW_AT_count, DW_CLS_CONSTANT, BucketSize, 0);
newrefattr(fld, DW_AT_type, find_or_diag(&dwtypes, "uintptr"));
// Construct type to represent an array of BucketSize values
@@ -1253,7 +1267,7 @@ synthesizemaptypes(DWDie *die)
newattr(dwhv, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize * valsize, 0);
newrefattr(dwhv, DW_AT_type, indirect_val ? defptrto(valtype) : valtype);
fld = newdie(dwhv, DW_ABRV_ARRAYRANGE, "size");
- newattr(fld, DW_AT_upper_bound, DW_CLS_CONSTANT, BucketSize, 0);
+ newattr(fld, DW_AT_count, DW_CLS_CONSTANT, BucketSize, 0);
newrefattr(fld, DW_AT_type, find_or_diag(&dwtypes, "uintptr"));
// Construct bucket<K,V>
@@ -1309,7 +1323,7 @@ synthesizechantypes(DWDie *die)
for (; die != nil; die = die->link) {
if (die->abbrev != DW_ABRV_CHANTYPE)
continue;
- elemtype = (DWDie*) getattr(die, DW_AT_internal_elem_type)->data;
+ elemtype = (DWDie*) getattr(die, DW_AT_go_elem)->data;
a = getattr(elemtype, DW_AT_byte_size);
elemsize = a ? a->value : PtrSize;
@@ -1696,6 +1710,9 @@ enum
static void
putpccfadelta(vlong deltapc, vlong cfa)
{
+ cput(DW_CFA_def_cfa_offset_sf);
+ sleb128put(cfa / DATAALIGNMENTFACTOR);
+
if (deltapc < 0x40) {
cput(DW_CFA_advance_loc + deltapc);
} else if (deltapc < 0x100) {
@@ -1708,9 +1725,6 @@ putpccfadelta(vlong deltapc, vlong cfa)
cput(DW_CFA_advance_loc4);
LPUT(deltapc);
}
-
- cput(DW_CFA_def_cfa_offset_sf);
- sleb128put(cfa / DATAALIGNMENTFACTOR);
}
static void
@@ -1719,6 +1733,7 @@ writeframes(void)
LSym *s;
vlong fdeo, fdesize, pad;
Pciter pcsp;
+ uint32 nextpc;
if(framesec == S)
framesec = linklookup(ctxt, ".dwarfframe", 0);
@@ -1761,8 +1776,17 @@ writeframes(void)
addrput(0); // initial location
addrput(0); // address range
- for(pciterinit(ctxt, &pcsp, &s->pcln->pcsp); !pcsp.done; pciternext(&pcsp))
- putpccfadelta(pcsp.nextpc - pcsp.pc, PtrSize + pcsp.value);
+ for(pciterinit(ctxt, &pcsp, &s->pcln->pcsp); !pcsp.done; pciternext(&pcsp)) {
+ nextpc = pcsp.nextpc;
+ // pciterinit goes up to the end of the function,
+ // but DWARF expects us to stop just before the end.
+ if(nextpc == s->size) {
+ nextpc--;
+ if(nextpc < pcsp.pc)
+ continue;
+ }
+ putpccfadelta(nextpc - pcsp.pc, PtrSize + pcsp.value);
+ }
fdesize = cpos() - fdeo - 4; // exclude the length field.
pad = rnd(fdesize, PtrSize) - fdesize;
@@ -2028,13 +2052,15 @@ dwarfemitdebugsections(void)
newdie(&dwtypes, DW_ABRV_NULLTYPE, "<unspecified>");
newdie(&dwtypes, DW_ABRV_NULLTYPE, "void");
newdie(&dwtypes, DW_ABRV_BARE_PTRTYPE, "unsafe.Pointer");
+
die = newdie(&dwtypes, DW_ABRV_BASETYPE, "uintptr"); // needed for array size
newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_unsigned, 0);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, PtrSize, 0);
+ newattr(die, DW_AT_go_kind, DW_CLS_CONSTANT, KindUintptr, 0);
// Needed by the prettyprinter code for interface inspection.
- defgotype(lookup_or_diag("type.runtime.rtype"));
- defgotype(lookup_or_diag("type.runtime.interfaceType"));
+ defgotype(lookup_or_diag("type.runtime._type"));
+ defgotype(lookup_or_diag("type.runtime.interfacetype"));
defgotype(lookup_or_diag("type.runtime.itab"));
genasmsym(defdwsymb);
diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c
index 0555cf46a..3196961f3 100644
--- a/src/cmd/ld/elf.c
+++ b/src/cmd/ld/elf.c
@@ -776,7 +776,8 @@ elfshbits(Section *sect)
if(sect->rwx & 2)
sh->flags |= SHF_WRITE;
if(strcmp(sect->name, ".tbss") == 0) {
- sh->flags |= SHF_TLS;
+ if(strcmp(goos, "android") != 0)
+ sh->flags |= SHF_TLS; // no TLS on android
sh->type = SHT_NOBITS;
}
if(linkmode != LinkExternal)
diff --git a/src/cmd/ld/ldelf.c b/src/cmd/ld/ldelf.c
index 1d7c4c13e..b5d081949 100644
--- a/src/cmd/ld/ldelf.c
+++ b/src/cmd/ld/ldelf.c
@@ -539,7 +539,7 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
s->type = SRODATA;
break;
case ElfSectFlagAlloc + ElfSectFlagWrite:
- s->type = SDATA;
+ s->type = SNOPTRDATA;
break;
case ElfSectFlagAlloc + ElfSectFlagExec:
s->type = STEXT;
@@ -572,7 +572,7 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
if(s->size < sym.size)
s->size = sym.size;
if(s->type == 0 || s->type == SXREF)
- s->type = SBSS;
+ s->type = SNOPTRBSS;
continue;
}
if(sym.shndx >= obj->nsect || sym.shndx == 0)
@@ -582,6 +582,8 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
continue;
sect = obj->sect+sym.shndx;
if(sect->sym == nil) {
+ if(strncmp(sym.name, ".Linfo_string", 13) == 0) // clang does this
+ continue;
diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type);
continue;
}
@@ -817,7 +819,7 @@ readsym(ElfObj *obj, int i, ElfSym *sym, int needSym)
}
break;
case ElfSymBindLocal:
- if(!(thechar == '5' && (strcmp(sym->name, "$a") == 0 || strcmp(sym->name, "$d") == 0))) // binutils for arm generate these mapping symbols, ignore these
+ if(!(thechar == '5' && (strncmp(sym->name, "$a", 2) == 0 || strncmp(sym->name, "$d", 2) == 0))) // binutils for arm generate these mapping symbols, ignore these
if(needSym) {
// local names and hidden visiblity global names are unique
// and should only reference by its index, not name, so we
diff --git a/src/cmd/ld/ldmacho.c b/src/cmd/ld/ldmacho.c
index 413dedabd..71cfa63de 100644
--- a/src/cmd/ld/ldmacho.c
+++ b/src/cmd/ld/ldmacho.c
@@ -589,10 +589,10 @@ ldmacho(Biobuf *f, char *pkg, int64 len, char *pn)
s->type = SRODATA;
} else {
if (strcmp(sect->name, "__bss") == 0) {
- s->type = SBSS;
+ s->type = SNOPTRBSS;
s->np = 0;
} else
- s->type = SDATA;
+ s->type = SNOPTRDATA;
}
sect->sym = s;
}
diff --git a/src/cmd/ld/ldpe.c b/src/cmd/ld/ldpe.c
index f6eda900d..4f5e51f2f 100644
--- a/src/cmd/ld/ldpe.c
+++ b/src/cmd/ld/ldpe.c
@@ -128,6 +128,7 @@ struct PeObj {
};
static int map(PeObj *obj, PeSect *sect);
+static int issect(PeSym *s);
static int readsym(PeObj *obj, int i, PeSym **sym);
void
@@ -179,6 +180,15 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
Bseek(f, base+obj->fh.PointerToSymbolTable+sizeof(symbuf)*obj->fh.NumberOfSymbols, 0);
if(Bread(f, obj->snames, l) != l)
goto bad;
+ // rewrite section names if they start with /
+ for(i=0; i < obj->fh.NumberOfSections; i++) {
+ if(obj->sect[i].name == nil)
+ continue;
+ if(obj->sect[i].name[0] != '/')
+ continue;
+ l = atoi(obj->sect[i].name + 1);
+ obj->sect[i].name = (char*)&obj->snames[l];
+ }
// read symbols
obj->pesym = mal(obj->fh.NumberOfSymbols*sizeof obj->pesym[0]);
obj->npesym = obj->fh.NumberOfSymbols;
@@ -230,10 +240,10 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
s->type = SRODATA;
break;
case IMAGE_SCN_CNT_UNINITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE: //.bss
- s->type = SBSS;
+ s->type = SNOPTRBSS;
break;
case IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE: //.data
- s->type = SDATA;
+ s->type = SNOPTRDATA;
break;
case IMAGE_SCN_CNT_CODE|IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ: //.text
s->type = STEXT;
@@ -309,8 +319,8 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
// ld -r could generate multiple section symbols for the
// same section but with different values, we have to take
// that into account
- if (obj->pesym[symindex].name[0] == '.')
- rp->add += obj->pesym[symindex].value;
+ if(issect(&obj->pesym[symindex]))
+ rp->add += obj->pesym[symindex].value;
}
qsort(r, rsect->sh.NumberOfRelocations, sizeof r[0], rbyoff);
@@ -318,12 +328,12 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
s->r = r;
s->nr = rsect->sh.NumberOfRelocations;
}
-
+
// enter sub-symbols into symbol table.
for(i=0; i<obj->npesym; i++) {
if(obj->pesym[i].name == 0)
continue;
- if(obj->pesym[i].name[0] == '.') //skip section
+ if(issect(&obj->pesym[i]))
continue;
if(obj->pesym[i].sectnum > 0) {
sect = &obj->sect[obj->pesym[i].sectnum-1];
@@ -338,7 +348,7 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
if(s->type == SDYNIMPORT)
s->plt = -2; // flag for dynimport in PE object files.
if (s->type == SXREF && sym->value > 0) {// global data
- s->type = SDATA;
+ s->type = SNOPTRDATA;
s->size = sym->value;
}
continue;
@@ -422,6 +432,12 @@ map(PeObj *obj, PeSect *sect)
}
static int
+issect(PeSym *s)
+{
+ return s->sclass == IMAGE_SYM_CLASS_STATIC && s->type == 0 && s->name[0] == '.';
+}
+
+static int
readsym(PeObj *obj, int i, PeSym **y)
{
LSym *s;
@@ -436,7 +452,7 @@ readsym(PeObj *obj, int i, PeSym **y)
sym = &obj->pesym[i];
*y = sym;
- if(sym->name[0] == '.') // .section
+ if(issect(sym))
name = obj->sect[sym->sectnum-1].sym->name;
else {
name = sym->name;
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index da6194e4f..f889aba8a 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -33,8 +33,8 @@
#include "lib.h"
#include "../ld/elf.h"
#include "../ld/dwarf.h"
-#include "../../pkg/runtime/stack.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/stack.h"
+#include "../../runtime/funcdata.h"
#include <ar.h>
#if !(defined(_WIN32) || defined(PLAN9))
@@ -144,6 +144,10 @@ libinit(void)
void
errorexit(void)
{
+ if(cout >= 0) {
+ // For rmtemp run at atexit time on Windows.
+ close(cout);
+ }
if(nerrors) {
if(cout >= 0)
mayberemoveoutfile();
@@ -177,7 +181,7 @@ void
loadlib(void)
{
int i, w, x;
- LSym *s, *gmsym;
+ LSym *s, *tlsg;
char* cgostrsym;
if(flag_shared) {
@@ -217,8 +221,12 @@ loadlib(void)
// Provided by the code that imports the package.
// Since we are simulating the import, we have to provide this string.
cgostrsym = "go.string.\"runtime/cgo\"";
- if(linkrlookup(ctxt, cgostrsym, 0) == nil)
+ if(linkrlookup(ctxt, cgostrsym, 0) == nil) {
+ s = linklookup(ctxt, cgostrsym, 0);
+ s->type = SRODATA;
+ s->reachable = 1;
addstrdata(cgostrsym, "runtime/cgo");
+ }
}
if(linkmode == LinkAuto) {
@@ -226,6 +234,10 @@ loadlib(void)
linkmode = LinkExternal;
else
linkmode = LinkInternal;
+
+ // Force external linking for android.
+ if(strcmp(goos, "android") == 0)
+ linkmode = LinkExternal;
}
if(linkmode == LinkInternal) {
@@ -244,12 +256,12 @@ loadlib(void)
}
}
- gmsym = linklookup(ctxt, "runtime.tlsgm", 0);
- gmsym->type = STLSBSS;
- gmsym->size = 2*PtrSize;
- gmsym->hide = 1;
- gmsym->reachable = 1;
- ctxt->gmsym = gmsym;
+ tlsg = linklookup(ctxt, "runtime.tlsg", 0);
+ tlsg->type = STLSBSS;
+ tlsg->size = PtrSize;
+ tlsg->hide = 1;
+ tlsg->reachable = 1;
+ ctxt->tlsg = tlsg;
// Now that we know the link mode, trim the dynexp list.
x = CgoExportDynamic;
@@ -895,7 +907,7 @@ unmal(void *v, uint32 n)
* escaping are %, ., and ", but we escape all control characters too.
*
* If you edit this, edit ../gc/subr.c:/^pathtoprefix too.
- * If you edit this, edit ../../pkg/debug/goobj/read.go:/importPathToPrefix too.
+ * If you edit this, edit ../../debug/goobj/read.go:/importPathToPrefix too.
*/
static char*
pathtoprefix(char *s)
@@ -1345,10 +1357,10 @@ genasmsym(void (*put)(LSym*, char*, int, vlong, vlong, int, LSym*))
// These symbols won't show up in the first loop below because we
// skip STEXT symbols. Normal STEXT symbols are emitted by walking textp.
- s = linklookup(ctxt, "text", 0);
+ s = linklookup(ctxt, "runtime.text", 0);
if(s->type == STEXT)
put(s, s->name, 'T', s->value, s->size, s->version, 0);
- s = linklookup(ctxt, "etext", 0);
+ s = linklookup(ctxt, "runtime.etext", 0);
if(s->type == STEXT)
put(s, s->name, 'T', s->value, s->size, s->version, 0);
@@ -1550,3 +1562,56 @@ diag(char *fmt, ...)
errorexit();
}
}
+
+void
+checkgo(void)
+{
+ LSym *s;
+ Reloc *r;
+ int i;
+ int changed;
+
+ if(!debug['C'])
+ return;
+
+ // TODO(rsc,khr): Eventually we want to get to no Go-called C functions at all,
+ // which would simplify this logic quite a bit.
+
+ // Mark every Go-called C function with cfunc=2, recursively.
+ do {
+ changed = 0;
+ for(s = ctxt->textp; s != nil; s = s->next) {
+ if(s->cfunc == 0 || (s->cfunc == 2 && s->nosplit)) {
+ for(i=0; i<s->nr; i++) {
+ r = &s->r[i];
+ if(r->sym == nil)
+ continue;
+ if((r->type == R_CALL || r->type == R_CALLARM) && r->sym->type == STEXT) {
+ if(r->sym->cfunc == 1) {
+ changed = 1;
+ r->sym->cfunc = 2;
+ }
+ }
+ }
+ }
+ }
+ }while(changed);
+
+ // Complain about Go-called C functions that can split the stack
+ // (that can be preempted for garbage collection or trigger a stack copy).
+ for(s = ctxt->textp; s != nil; s = s->next) {
+ if(s->cfunc == 0 || (s->cfunc == 2 && s->nosplit)) {
+ for(i=0; i<s->nr; i++) {
+ r = &s->r[i];
+ if(r->sym == nil)
+ continue;
+ if((r->type == R_CALL || r->type == R_CALLARM) && r->sym->type == STEXT) {
+ if(s->cfunc == 0 && r->sym->cfunc == 2 && !r->sym->nosplit)
+ print("Go %s calls C %s\n", s->name, r->sym->name);
+ else if(s->cfunc == 2 && s->nosplit && !r->sym->nosplit)
+ print("Go calls C %s calls %s\n", s->name, r->sym->name);
+ }
+ }
+ }
+ }
+}
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index 7267c6371..067ffa0bc 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -33,6 +33,10 @@
// A section further describes the pieces of that block for
// use in debuggers and such.
+enum {
+ MAXIO = 8192,
+};
+
typedef struct Segment Segment;
typedef struct Section Section;
@@ -179,12 +183,13 @@ uint16 be16(uchar *b);
uint32 be32(uchar *b);
uint64 be64(uchar *b);
void callgraph(void);
+void checkgo(void);
void cflush(void);
-void codeblk(int32 addr, int32 size);
+void codeblk(int64 addr, int64 size);
vlong cpos(void);
void cseek(vlong p);
void cwrite(void *buf, int n);
-void datblk(int32 addr, int32 size);
+void datblk(int64 addr, int64 size);
int datcmp(LSym *s1, LSym *s2);
vlong datoff(vlong addr);
void deadcode(void);
@@ -196,9 +201,12 @@ int decodetype_funcincount(LSym *s);
LSym* decodetype_funcintype(LSym *s, int i);
int decodetype_funcoutcount(LSym *s);
LSym* decodetype_funcouttype(LSym *s, int i);
-LSym* decodetype_gc(LSym *s);
+LSym* decodetype_gcprog(LSym *s);
+uint8* decodetype_gcmask(LSym *s);
vlong decodetype_ifacemethodcount(LSym *s);
uint8 decodetype_kind(LSym *s);
+uint8 decodetype_noptr(LSym *s);
+uint8 decodetype_usegcprog(LSym *s);
LSym* decodetype_mapkey(LSym *s);
LSym* decodetype_mapvalue(LSym *s);
LSym* decodetype_ptrelem(LSym *s);
diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c
index 61306bb7c..fe7e10e46 100644
--- a/src/cmd/ld/macho.c
+++ b/src/cmd/ld/macho.c
@@ -590,8 +590,7 @@ machosymtab(void)
if(strstr(s->extname, "·") == nil) {
addstring(symstr, s->extname);
} else {
- p = s->extname;
- while (*p++ != '\0') {
+ for(p = s->extname; *p; p++) {
if((uchar)*p == 0xc2 && (uchar)*(p+1) == 0xb7) {
adduint8(ctxt, symstr, '.');
p++;
diff --git a/src/cmd/ld/pass.c b/src/cmd/ld/pass.c
deleted file mode 100644
index 788b7c75a..000000000
--- a/src/cmd/ld/pass.c
+++ /dev/null
@@ -1,104 +0,0 @@
-// Inferno utils/6l/pass.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6l/pass.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// Code and data passes.
-
-#include "l.h"
-#include "../ld/lib.h"
-#include "../../pkg/runtime/stack.h"
-
-void
-follow(void)
-{
- LSym *s;
-
- if(debug['v'])
- Bprint(&bso, "%5.2f follow\n", cputime());
- Bflush(&bso);
-
- for(s = ctxt->textp; s != nil; s = s->next)
- ctxt->arch->follow(ctxt, s);
-}
-
-void
-patch(void)
-{
- LSym *s;
-
- if(debug['v'])
- Bprint(&bso, "%5.2f mkfwd\n", cputime());
- Bflush(&bso);
- for(s = ctxt->textp; s != nil; s = s->next)
- mkfwd(s);
- if(debug['v'])
- Bprint(&bso, "%5.2f patch\n", cputime());
- Bflush(&bso);
-
- if(flag_shared) {
- s = linklookup(ctxt, "init_array", 0);
- s->type = SINITARR;
- s->reachable = 1;
- s->hide = 1;
- addaddr(ctxt, s, linklookup(ctxt, INITENTRY, 0));
- }
-
- for(s = ctxt->textp; s != nil; s = s->next)
- linkpatch(ctxt, s);
-}
-
-void
-dostkoff(void)
-{
- LSym *s;
-
- for(s = ctxt->textp; s != nil; s = s->next)
- ctxt->arch->addstacksplit(ctxt, s);
-}
-
-void
-span(void)
-{
- LSym *s;
-
- if(debug['v'])
- Bprint(&bso, "%5.2f span\n", cputime());
-
- for(s = ctxt->textp; s != nil; s = s->next)
- ctxt->arch->assemble(ctxt, s);
-}
-
-void
-pcln(void)
-{
- LSym *s;
-
- for(s = ctxt->textp; s != nil; s = s->next)
- linkpcln(ctxt, s);
-}
diff --git a/src/cmd/ld/pcln.c b/src/cmd/ld/pcln.c
index 4c2ffa78e..69671c0fc 100644
--- a/src/cmd/ld/pcln.c
+++ b/src/cmd/ld/pcln.c
@@ -4,7 +4,7 @@
#include "l.h"
#include "lib.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/funcdata.h"
static void
addvarint(Pcdata *d, uint32 val)
@@ -90,7 +90,7 @@ renumberfiles(Link *ctxt, LSym **files, int nfiles, Pcdata *d)
}
dv = val - newval;
newval = val;
- v = (uint32)(dv<<1) ^ (uint32)(int32)(dv>>31);
+ v = ((uint32)dv<<1) ^ (uint32)(int32)(dv>>31);
addvarint(&out, v);
// pc delta
@@ -119,7 +119,7 @@ pclntab(void)
static Pcln zpcln;
funcdata_bytes = 0;
- ftab = linklookup(ctxt, "pclntab", 0);
+ ftab = linklookup(ctxt, "runtime.pclntab", 0);
ftab->type = SPCLNTAB;
ftab->reachable = 1;
diff --git a/src/cmd/ld/pobj.c b/src/cmd/ld/pobj.c
index 819c37954..63460df30 100644
--- a/src/cmd/ld/pobj.c
+++ b/src/cmd/ld/pobj.c
@@ -45,6 +45,8 @@ char* paramspace = "FP";
void
main(int argc, char *argv[])
{
+ int i;
+
linkarchinit();
ctxt = linknew(thelinkarch);
ctxt->thechar = thechar;
@@ -63,7 +65,13 @@ main(int argc, char *argv[])
INITRND = -1;
INITENTRY = 0;
linkmode = LinkAuto;
- nuxiinit();
+
+ // For testing behavior of go command when tools crash.
+ // Undocumented, not in standard flag parser to avoid
+ // exposing in usage message.
+ for(i=1; i<argc; i++)
+ if(strcmp(argv[i], "-crash_for_testing") == 0)
+ *(volatile int*)0 = 0;
if(thechar == '5' && ctxt->goarm == 5)
debug['F'] = 1;
@@ -72,6 +80,7 @@ main(int argc, char *argv[])
if(thechar == '6')
flagcount("8", "assume 64-bit addresses", &debug['8']);
flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo);
+ flagcount("C", "check Go calls to C code", &debug['C']);
flagint64("D", "addr: data address", &INITDAT);
flagstr("E", "sym: entry symbol", &INITENTRY);
if(thechar == '5')
@@ -96,11 +105,11 @@ main(int argc, char *argv[])
flagcount("a", "disassemble output", &debug['a']);
flagcount("c", "dump call graph", &debug['c']);
flagcount("d", "disable dynamic executable", &debug['d']);
- flagstr("extld", "linker to run in external mode", &extld);
- flagstr("extldflags", "flags for external linker", &extldflags);
+ flagstr("extld", "ld: linker to run in external mode", &extld);
+ flagstr("extldflags", "ldflags: flags for external linker", &extldflags);
flagcount("f", "ignore version mismatch", &debug['f']);
flagcount("g", "disable go package data checks", &debug['g']);
- flagstr("installsuffix", "pkg directory suffix", &flag_installsuffix);
+ flagstr("installsuffix", "suffix: pkg directory suffix", &flag_installsuffix);
flagstr("k", "sym: set field tracking symbol", &tracksym);
flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode);
flagcount("n", "dump symbol table", &debug['n']);
@@ -110,7 +119,7 @@ main(int argc, char *argv[])
flagcount("s", "disable symbol table", &debug['s']);
if(thechar == '5' || thechar == '6')
flagcount("shared", "generate shared object (implies -linkmode external)", &flag_shared);
- flagstr("tmpdir", "leave temporary files in this directory", &tmpdir);
+ flagstr("tmpdir", "dir: leave temporary files in this directory", &tmpdir);
flagcount("u", "reject unsafe packages", &debug['u']);
flagcount("v", "print link trace", &debug['v']);
flagcount("w", "disable DWARF generation", &debug['w']);
@@ -139,7 +148,7 @@ main(int argc, char *argv[])
if(HEADTYPE == -1)
HEADTYPE = headtype(goos);
ctxt->headtype = HEADTYPE;
- if (headstring == nil)
+ if(headstring == nil)
headstring = headstr(HEADTYPE);
archinit();
@@ -163,6 +172,7 @@ main(int argc, char *argv[])
mark(linklookup(ctxt, "runtime.read_tls_fallback", 0));
}
+ checkgo();
deadcode();
callgraph();
paramspace = "SP"; /* (FP) now (SP) on output */
diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c
index 6d321c0bb..156270c8f 100644
--- a/src/cmd/ld/symtab.c
+++ b/src/cmd/ld/symtab.c
@@ -198,13 +198,18 @@ asmelfsym(void)
genasmsym(putelfsym);
if(linkmode == LinkExternal && HEADTYPE != Hopenbsd) {
- s = linklookup(ctxt, "runtime.tlsgm", 0);
+ s = linklookup(ctxt, "runtime.tlsg", 0);
if(s->sect == nil) {
ctxt->cursym = nil;
diag("missing section for %s", s->name);
errorexit();
}
- putelfsyment(putelfstr(s->name), 0, 2*PtrSize, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0);
+ if (strcmp(goos, "android") == 0) {
+ // Android emulates runtime.tlsg as a regular variable.
+ putelfsyment(putelfstr(s->name), 0, s->size, (STB_LOCAL<<4)|STT_OBJECT, s->sect->elfsect->shnum, 0);
+ } else {
+ putelfsyment(putelfstr(s->name), 0, s->size, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0);
+ }
s->elfsym = numelfsym++;
}
@@ -341,36 +346,36 @@ symtab(void)
// Define these so that they'll get put into the symbol table.
// data.c:/^address will provide the actual values.
- xdefine("text", STEXT, 0);
- xdefine("etext", STEXT, 0);
- xdefine("typelink", SRODATA, 0);
- xdefine("etypelink", SRODATA, 0);
- xdefine("rodata", SRODATA, 0);
- xdefine("erodata", SRODATA, 0);
- xdefine("noptrdata", SNOPTRDATA, 0);
- xdefine("enoptrdata", SNOPTRDATA, 0);
- xdefine("data", SDATA, 0);
- xdefine("edata", SDATA, 0);
- xdefine("bss", SBSS, 0);
- xdefine("ebss", SBSS, 0);
- xdefine("noptrbss", SNOPTRBSS, 0);
- xdefine("enoptrbss", SNOPTRBSS, 0);
- xdefine("end", SBSS, 0);
- xdefine("epclntab", SRODATA, 0);
- xdefine("esymtab", SRODATA, 0);
+ xdefine("runtime.text", STEXT, 0);
+ xdefine("runtime.etext", STEXT, 0);
+ xdefine("runtime.typelink", SRODATA, 0);
+ xdefine("runtime.etypelink", SRODATA, 0);
+ xdefine("runtime.rodata", SRODATA, 0);
+ xdefine("runtime.erodata", SRODATA, 0);
+ xdefine("runtime.noptrdata", SNOPTRDATA, 0);
+ xdefine("runtime.enoptrdata", SNOPTRDATA, 0);
+ xdefine("runtime.data", SDATA, 0);
+ xdefine("runtime.edata", SDATA, 0);
+ xdefine("runtime.bss", SBSS, 0);
+ xdefine("runtime.ebss", SBSS, 0);
+ xdefine("runtime.noptrbss", SNOPTRBSS, 0);
+ xdefine("runtime.enoptrbss", SNOPTRBSS, 0);
+ xdefine("runtime.end", SBSS, 0);
+ xdefine("runtime.epclntab", SRODATA, 0);
+ xdefine("runtime.esymtab", SRODATA, 0);
// garbage collection symbols
- s = linklookup(ctxt, "gcdata", 0);
+ s = linklookup(ctxt, "runtime.gcdata", 0);
s->type = SRODATA;
s->size = 0;
s->reachable = 1;
- xdefine("egcdata", SRODATA, 0);
+ xdefine("runtime.egcdata", SRODATA, 0);
- s = linklookup(ctxt, "gcbss", 0);
+ s = linklookup(ctxt, "runtime.gcbss", 0);
s->type = SRODATA;
s->size = 0;
s->reachable = 1;
- xdefine("egcbss", SRODATA, 0);
+ xdefine("runtime.egcbss", SRODATA, 0);
// pseudo-symbols to mark locations of type, string, and go string data.
s = linklookup(ctxt, "type.*", 0);
@@ -391,9 +396,9 @@ symtab(void)
s->reachable = 1;
symgofunc = s;
- symtypelink = linklookup(ctxt, "typelink", 0);
+ symtypelink = linklookup(ctxt, "runtime.typelink", 0);
- symt = linklookup(ctxt, "symtab", 0);
+ symt = linklookup(ctxt, "runtime.symtab", 0);
symt->type = SSYMTAB;
symt->size = 0;
symt->reachable = 1;
diff --git a/src/cmd/ld/textflag.h b/src/cmd/ld/textflag.h
index 2a76e76c2..0ee8b5f1c 100644
--- a/src/cmd/ld/textflag.h
+++ b/src/cmd/ld/textflag.h
@@ -21,3 +21,16 @@
#define WRAPPER 32
// This function uses its incoming context register.
#define NEEDCTXT 64
+
+/*c2go
+enum
+{
+ NOPROF = 1,
+ DUPOK = 2,
+ NOSPLIT = 4,
+ RODATA = 8,
+ NOPTR = 16,
+ WRAPPER = 32,
+ NEEDCTXT = 64,
+};
+*/