Commit 40d356e9 authored by Russ Cox's avatar Russ Cox

cmd/ld: generate relocated DWARF in hostobj mode

While we're here, downgrade DWARF to version 2.
We're not using any version 3 features, and OS X gdb
only supports version 2.

Fixes #3436.

R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/7891044
parent ddddd70c
...@@ -41,9 +41,13 @@ static vlong arangeso; ...@@ -41,9 +41,13 @@ static vlong arangeso;
static vlong arangessize; static vlong arangessize;
static vlong gdbscripto; static vlong gdbscripto;
static vlong gdbscriptsize; static vlong gdbscriptsize;
static vlong inforeloco;
static vlong inforelocsize;
static char gdbscript[1024]; static char gdbscript[1024];
static Sym *dsym;
/* /*
* Basic I/O * Basic I/O
*/ */
...@@ -485,26 +489,43 @@ mkindex(DWDie *die) ...@@ -485,26 +489,43 @@ mkindex(DWDie *die)
die->hash = mal(HASHSIZE * sizeof(DWDie*)); die->hash = mal(HASHSIZE * sizeof(DWDie*));
} }
static DWDie*
walktypedef(DWDie *die)
{
DWAttr *attr;
// Resolve typedef if present.
if (die->abbrev == DW_ABRV_TYPEDECL) {
for (attr = die->attr; attr; attr = attr->link) {
if (attr->atr == DW_AT_type && attr->cls == DW_CLS_REFERENCE && attr->data != nil) {
return (DWDie*)attr->data;
}
}
}
return die;
}
// Find child by AT_name using hashtable if available or linear scan // Find child by AT_name using hashtable if available or linear scan
// if not. // if not.
static DWDie* static DWDie*
find(DWDie *die, char* name) find(DWDie *die, char* name)
{ {
DWDie *a, *b; DWDie *a, *b, *die2;
int h; int h;
top:
if (die->hash == nil) { if (die->hash == nil) {
for (a = die->child; a != nil; a = a->link) for (a = die->child; a != nil; a = a->link)
if (strcmp(name, getattr(a, DW_AT_name)->data) == 0) if (strcmp(name, getattr(a, DW_AT_name)->data) == 0)
return a; return a;
return nil; goto notfound;
} }
h = hashstr(name); h = hashstr(name);
a = die->hash[h]; a = die->hash[h];
if (a == nil) if (a == nil)
return nil; goto notfound;
if (strcmp(name, getattr(a, DW_AT_name)->data) == 0) if (strcmp(name, getattr(a, DW_AT_name)->data) == 0)
...@@ -522,6 +543,14 @@ find(DWDie *die, char* name) ...@@ -522,6 +543,14 @@ find(DWDie *die, char* name)
a = b; a = b;
b = b->hlink; b = b->hlink;
} }
notfound:
die2 = walktypedef(die);
if(die2 != die) {
die = die2;
goto top;
}
return nil; return nil;
} }
...@@ -531,7 +560,7 @@ find_or_diag(DWDie *die, char* name) ...@@ -531,7 +560,7 @@ find_or_diag(DWDie *die, char* name)
DWDie *r; DWDie *r;
r = find(die, name); r = find(die, name);
if (r == nil) { if (r == nil) {
diag("dwarf find: %s has no %s", getattr(die, DW_AT_name)->data, name); diag("dwarf find: %s %p has no %s", getattr(die, DW_AT_name)->data, die, name);
errorexit(); errorexit();
} }
return r; return r;
...@@ -548,14 +577,33 @@ newrefattr(DWDie *die, uint8 attr, DWDie* ref) ...@@ -548,14 +577,33 @@ newrefattr(DWDie *die, uint8 attr, DWDie* ref)
static int fwdcount; static int fwdcount;
static void static void
putattr(int form, int cls, vlong value, char *data) putattr(int abbrev, int form, int cls, vlong value, char *data)
{ {
Reloc *r;
switch(form) { switch(form) {
case DW_FORM_addr: // address case DW_FORM_addr: // address
addrput(value); addrput(value);
break; break;
case DW_FORM_block1: // block case DW_FORM_block1: // block
if(cls == DW_CLS_ADDRESS) {
cput(1+PtrSize);
cput(DW_OP_addr);
if(linkmode == LinkExternal) {
r = addrel(dsym);
r->sym = (Sym*)data;
r->xsym = r->sym;
r->off = cpos() - infoo;
r->siz = PtrSize;
r->type = D_ADDR;
r->add = value - r->sym->value;
r->xadd = r->add;
value = r->add;
}
addrput(value);
break;
}
value &= 0xff; value &= 0xff;
cput(value); cput(value);
while(value--) while(value--)
...@@ -615,12 +663,22 @@ putattr(int form, int cls, vlong value, char *data) ...@@ -615,12 +663,22 @@ putattr(int form, int cls, vlong value, char *data)
break; break;
case DW_FORM_ref_addr: // reference to a DIE in the .info section case DW_FORM_ref_addr: // reference to a DIE in the .info section
// In DWARF 2 (which is what we claim to generate),
// the ref_addr is the same size as a normal address.
// In DWARF 3 it is always 32 bits, unless emitting a large
// (> 4 GB of debug info aka "64-bit") unit, which we don't implement.
if (data == nil) { if (data == nil) {
diag("dwarf: null reference"); diag("dwarf: null reference in %d", abbrev);
LPUT(0); // invalid dwarf, gdb will complain. if(PtrSize == 8)
VPUT(0); // invalid dwarf, gdb will complain.
else
VPUT(0); // invalid dwarf, gdb will complain.
} else { } else {
if (((DWDie*)data)->offs == 0) if (((DWDie*)data)->offs == 0)
fwdcount++; fwdcount++;
if(PtrSize == 8)
VPUT(((DWDie*)data)->offs);
else
LPUT(((DWDie*)data)->offs); LPUT(((DWDie*)data)->offs);
} }
break; break;
...@@ -654,12 +712,12 @@ putattrs(int abbrev, DWAttr* attr) ...@@ -654,12 +712,12 @@ putattrs(int abbrev, DWAttr* attr)
for(af = abbrevs[abbrev].attr; af->attr; af++) for(af = abbrevs[abbrev].attr; af->attr; af++)
if (attrs[af->attr]) if (attrs[af->attr])
putattr(af->form, putattr(abbrev, af->form,
attrs[af->attr]->cls, attrs[af->attr]->cls,
attrs[af->attr]->value, attrs[af->attr]->value,
attrs[af->attr]->data); attrs[af->attr]->data);
else else
putattr(af->form, 0, 0, 0); putattr(abbrev, af->form, 0, 0, 0);
} }
static void putdie(DWDie* die); static void putdie(DWDie* die);
...@@ -729,16 +787,9 @@ newmemberoffsetattr(DWDie *die, int32 offs) ...@@ -729,16 +787,9 @@ newmemberoffsetattr(DWDie *die, int32 offs)
// GDB doesn't like DW_FORM_addr for DW_AT_location, so emit a // GDB doesn't like DW_FORM_addr for DW_AT_location, so emit a
// location expression that evals to a const. // location expression that evals to a const.
static void static void
newabslocexprattr(DWDie *die, vlong addr) newabslocexprattr(DWDie *die, vlong addr, Sym *sym)
{ {
char block[10]; newattr(die, DW_AT_location, DW_CLS_ADDRESS, addr, (char*)sym);
int i;
i = 0;
block[i++] = DW_OP_constu;
i += uleb128enc(addr, block+i);
newattr(die, DW_AT_location, DW_CLS_BLOCK, i, mal(i));
memmove(die->attr->data, block, i);
} }
...@@ -766,6 +817,31 @@ lookup_or_diag(char *n) ...@@ -766,6 +817,31 @@ lookup_or_diag(char *n)
return s; return s;
} }
static void
dotypedef(DWDie *parent, char *name, DWDie *def)
{
DWDie *die;
// Only emit typedefs for real names.
if(strncmp(name, "map[", 4) == 0)
return;
if(strncmp(name, "struct {", 8) == 0)
return;
if(strncmp(name, "chan ", 5) == 0)
return;
if(*name == '[' || *name == '*')
return;
if(def == nil)
diag("dwarf: bad def in dotypedef");
// The typedef entry must be created after the def,
// so that future lookups will find the typedef instead
// of the real definition. This hooks the typedef into any
// circular definition loops, so that gdb can understand them.
die = newdie(parent, DW_ABRV_TYPEDECL, name);
newrefattr(die, DW_AT_type, def);
}
// Define gotype, for composite ones recurse into constituents. // Define gotype, for composite ones recurse into constituents.
static DWDie* static DWDie*
defgotype(Sym *gotype) defgotype(Sym *gotype)
...@@ -840,6 +916,7 @@ defgotype(Sym *gotype) ...@@ -840,6 +916,7 @@ defgotype(Sym *gotype)
case KindArray: case KindArray:
die = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, name); die = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, name);
dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0); newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
s = decodetype_arrayelem(gotype); s = decodetype_arrayelem(gotype);
newrefattr(die, DW_AT_type, defgotype(s)); newrefattr(die, DW_AT_type, defgotype(s));
...@@ -857,6 +934,7 @@ defgotype(Sym *gotype) ...@@ -857,6 +934,7 @@ defgotype(Sym *gotype)
case KindFunc: case KindFunc:
die = newdie(&dwtypes, DW_ABRV_FUNCTYPE, name); die = newdie(&dwtypes, DW_ABRV_FUNCTYPE, name);
dotypedef(&dwtypes, name, die);
newrefattr(die, DW_AT_type, find_or_diag(&dwtypes, "void")); newrefattr(die, DW_AT_type, find_or_diag(&dwtypes, "void"));
nfields = decodetype_funcincount(gotype); nfields = decodetype_funcincount(gotype);
for (i = 0; i < nfields; i++) { for (i = 0; i < nfields; i++) {
...@@ -876,6 +954,7 @@ defgotype(Sym *gotype) ...@@ -876,6 +954,7 @@ defgotype(Sym *gotype)
case KindInterface: case KindInterface:
die = newdie(&dwtypes, DW_ABRV_IFACETYPE, name); die = newdie(&dwtypes, DW_ABRV_IFACETYPE, name);
dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0); newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
nfields = decodetype_ifacemethodcount(gotype); nfields = decodetype_ifacemethodcount(gotype);
if (nfields == 0) if (nfields == 0)
...@@ -895,12 +974,14 @@ defgotype(Sym *gotype) ...@@ -895,12 +974,14 @@ defgotype(Sym *gotype)
case KindPtr: case KindPtr:
die = newdie(&dwtypes, DW_ABRV_PTRTYPE, name); die = newdie(&dwtypes, DW_ABRV_PTRTYPE, name);
dotypedef(&dwtypes, name, die);
s = decodetype_ptrelem(gotype); s = decodetype_ptrelem(gotype);
newrefattr(die, DW_AT_type, defgotype(s)); newrefattr(die, DW_AT_type, defgotype(s));
break; break;
case KindSlice: case KindSlice:
die = newdie(&dwtypes, DW_ABRV_SLICETYPE, name); die = newdie(&dwtypes, DW_ABRV_SLICETYPE, name);
dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0); newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
s = decodetype_arrayelem(gotype); s = decodetype_arrayelem(gotype);
newrefattr(die, DW_AT_internal_elem_type, defgotype(s)); newrefattr(die, DW_AT_internal_elem_type, defgotype(s));
...@@ -913,6 +994,7 @@ defgotype(Sym *gotype) ...@@ -913,6 +994,7 @@ defgotype(Sym *gotype)
case KindStruct: case KindStruct:
die = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, name); die = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, name);
dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0); newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
nfields = decodetype_structfieldcount(gotype); nfields = decodetype_structfieldcount(gotype);
for (i = 0; i < nfields; i++) { for (i = 0; i < nfields; i++) {
...@@ -998,7 +1080,7 @@ synthesizestringtypes(DWDie* die) ...@@ -998,7 +1080,7 @@ synthesizestringtypes(DWDie* die)
{ {
DWDie *prototype; DWDie *prototype;
prototype = defgotype(lookup_or_diag("type.runtime._string")); prototype = walktypedef(defgotype(lookup_or_diag("type.runtime._string")));
if (prototype == nil) if (prototype == nil)
return; return;
...@@ -1014,7 +1096,7 @@ synthesizeslicetypes(DWDie *die) ...@@ -1014,7 +1096,7 @@ synthesizeslicetypes(DWDie *die)
{ {
DWDie *prototype, *elem; DWDie *prototype, *elem;
prototype = defgotype(lookup_or_diag("type.runtime.slice")); prototype = walktypedef(defgotype(lookup_or_diag("type.runtime.slice")));
if (prototype == nil) if (prototype == nil)
return; return;
...@@ -1057,9 +1139,9 @@ synthesizemaptypes(DWDie *die) ...@@ -1057,9 +1139,9 @@ synthesizemaptypes(DWDie *die)
int hashsize, keysize, valsize, datsize, valsize_in_hash, datavo; int hashsize, keysize, valsize, datsize, valsize_in_hash, datavo;
DWAttr *a; DWAttr *a;
hash = defgotype(lookup_or_diag("type.runtime.hmap")); hash = walktypedef(defgotype(lookup_or_diag("type.runtime.hmap")));
hash_subtable = defgotype(lookup_or_diag("type.runtime.hash_subtable")); hash_subtable = walktypedef(defgotype(lookup_or_diag("type.runtime.hash_subtable")));
hash_entry = defgotype(lookup_or_diag("type.runtime.hash_entry")); hash_entry = walktypedef(defgotype(lookup_or_diag("type.runtime.hash_entry")));
if (hash == nil || hash_subtable == nil || hash_entry == nil) if (hash == nil || hash_subtable == nil || hash_entry == nil)
return; return;
...@@ -1149,9 +1231,9 @@ synthesizechantypes(DWDie *die) ...@@ -1149,9 +1231,9 @@ synthesizechantypes(DWDie *die)
DWAttr *a; DWAttr *a;
int elemsize, sudogsize; int elemsize, sudogsize;
sudog = defgotype(lookup_or_diag("type.runtime.sudog")); sudog = walktypedef(defgotype(lookup_or_diag("type.runtime.sudog")));
waitq = defgotype(lookup_or_diag("type.runtime.waitq")); waitq = walktypedef(defgotype(lookup_or_diag("type.runtime.waitq")));
hchan = defgotype(lookup_or_diag("type.runtime.hchan")); hchan = walktypedef(defgotype(lookup_or_diag("type.runtime.hchan")));
if (sudog == nil || waitq == nil || hchan == nil) if (sudog == nil || waitq == nil || hchan == nil)
return; return;
...@@ -1220,7 +1302,7 @@ defdwsymb(Sym* sym, char *s, int t, vlong v, vlong size, int ver, Sym *gotype) ...@@ -1220,7 +1302,7 @@ defdwsymb(Sym* sym, char *s, int t, vlong v, vlong size, int ver, Sym *gotype)
case 'D': case 'D':
case 'B': case 'B':
dv = newdie(&dwglobals, DW_ABRV_VARIABLE, s); dv = newdie(&dwglobals, DW_ABRV_VARIABLE, s);
newabslocexprattr(dv, v); newabslocexprattr(dv, v, sym);
if (ver == 0) if (ver == 0)
newattr(dv, DW_AT_external, DW_CLS_FLAG, 1, 0); newattr(dv, DW_AT_external, DW_CLS_FLAG, 1, 0);
// fallthrough // fallthrough
...@@ -1581,12 +1663,12 @@ mkvarname(char* name, int da) ...@@ -1581,12 +1663,12 @@ mkvarname(char* name, int da)
// flush previous compilation unit. // flush previous compilation unit.
static void static void
flushunit(DWDie *dwinfo, vlong pc, vlong unitstart, int32 header_length) flushunit(DWDie *dwinfo, vlong pc, Sym *pcsym, vlong unitstart, int32 header_length)
{ {
vlong here; vlong here;
if (dwinfo != nil && pc != 0) { if (dwinfo != nil && pc != 0) {
newattr(dwinfo, DW_AT_high_pc, DW_CLS_ADDRESS, pc+1, 0); newattr(dwinfo, DW_AT_high_pc, DW_CLS_ADDRESS, pc+1, (char*)pcsym);
} }
if (unitstart >= 0) { if (unitstart >= 0) {
...@@ -1597,7 +1679,7 @@ flushunit(DWDie *dwinfo, vlong pc, vlong unitstart, int32 header_length) ...@@ -1597,7 +1679,7 @@ flushunit(DWDie *dwinfo, vlong pc, vlong unitstart, int32 header_length)
here = cpos(); here = cpos();
cseek(unitstart); cseek(unitstart);
LPUT(here - unitstart - sizeof(int32)); // unit_length LPUT(here - unitstart - sizeof(int32)); // unit_length
WPUT(3); // dwarf version WPUT(2); // dwarf version
LPUT(header_length); // header length starting here LPUT(header_length); // header length starting here
cseek(here); cseek(here);
} }
...@@ -1607,7 +1689,7 @@ static void ...@@ -1607,7 +1689,7 @@ static void
writelines(void) writelines(void)
{ {
Prog *q; Prog *q;
Sym *s; Sym *s, *epcs;
Auto *a; Auto *a;
vlong unitstart, headerend, offs; vlong unitstart, headerend, offs;
vlong pc, epc, lc, llc, lline; vlong pc, epc, lc, llc, lline;
...@@ -1622,6 +1704,7 @@ writelines(void) ...@@ -1622,6 +1704,7 @@ writelines(void)
headerend = -1; headerend = -1;
pc = 0; pc = 0;
epc = 0; epc = 0;
epcs = S;
lc = 1; lc = 1;
llc = 1; llc = 1;
currfile = -1; currfile = -1;
...@@ -1637,7 +1720,7 @@ writelines(void) ...@@ -1637,7 +1720,7 @@ writelines(void)
// we're entering a new compilation unit // we're entering a new compilation unit
if (inithist(s->autom)) { if (inithist(s->autom)) {
flushunit(dwinfo, epc, unitstart, headerend - unitstart - 10); flushunit(dwinfo, epc, epcs, unitstart, headerend - unitstart - 10);
unitstart = cpos(); unitstart = cpos();
if(debug['v'] > 1) { if(debug['v'] > 1) {
...@@ -1654,12 +1737,12 @@ writelines(void) ...@@ -1654,12 +1737,12 @@ writelines(void)
dwinfo = newdie(&dwroot, DW_ABRV_COMPUNIT, estrdup(histfile[1])); dwinfo = newdie(&dwroot, DW_ABRV_COMPUNIT, estrdup(histfile[1]));
newattr(dwinfo, DW_AT_language, DW_CLS_CONSTANT,lang, 0); newattr(dwinfo, DW_AT_language, DW_CLS_CONSTANT,lang, 0);
newattr(dwinfo, DW_AT_stmt_list, DW_CLS_PTR, unitstart - lineo, 0); newattr(dwinfo, DW_AT_stmt_list, DW_CLS_PTR, unitstart - lineo, 0);
newattr(dwinfo, DW_AT_low_pc, DW_CLS_ADDRESS, s->text->pc, 0); newattr(dwinfo, DW_AT_low_pc, DW_CLS_ADDRESS, s->text->pc, (char*)s);
// Write .debug_line Line Number Program Header (sec 6.2.4) // Write .debug_line Line Number Program Header (sec 6.2.4)
// Fields marked with (*) must be changed for 64-bit dwarf // Fields marked with (*) must be changed for 64-bit dwarf
LPUT(0); // unit_length (*), will be filled in by flushunit. LPUT(0); // unit_length (*), will be filled in by flushunit.
WPUT(3); // dwarf version (appendix F) WPUT(2); // dwarf version (appendix F)
LPUT(0); // header_length (*), filled in by flushunit. LPUT(0); // header_length (*), filled in by flushunit.
// cpos == unitstart + 4 + 2 + 4 // cpos == unitstart + 4 + 2 + 4
cput(1); // minimum_instruction_length cput(1); // minimum_instruction_length
...@@ -1683,6 +1766,7 @@ writelines(void) ...@@ -1683,6 +1766,7 @@ writelines(void)
pc = s->text->pc; pc = s->text->pc;
epc = pc; epc = pc;
epcs = s;
currfile = 1; currfile = 1;
lc = 1; lc = 1;
llc = 1; llc = 1;
...@@ -1701,9 +1785,9 @@ writelines(void) ...@@ -1701,9 +1785,9 @@ writelines(void)
} }
dwfunc = newdie(dwinfo, DW_ABRV_FUNCTION, s->name); dwfunc = newdie(dwinfo, DW_ABRV_FUNCTION, s->name);
newattr(dwfunc, DW_AT_low_pc, DW_CLS_ADDRESS, s->value, 0); newattr(dwfunc, DW_AT_low_pc, DW_CLS_ADDRESS, s->value, (char*)s);
epc = s->value + s->size; epc = s->value + s->size;
newattr(dwfunc, DW_AT_high_pc, DW_CLS_ADDRESS, epc, 0); newattr(dwfunc, DW_AT_high_pc, DW_CLS_ADDRESS, epc, (char*)s);
if (s->version == 0) if (s->version == 0)
newattr(dwfunc, DW_AT_external, DW_CLS_FLAG, 1, 0); newattr(dwfunc, DW_AT_external, DW_CLS_FLAG, 1, 0);
...@@ -1785,7 +1869,7 @@ writelines(void) ...@@ -1785,7 +1869,7 @@ writelines(void)
dwfunc->hash = nil; dwfunc->hash = nil;
} }
flushunit(dwinfo, epc, unitstart, headerend - unitstart - 10); flushunit(dwinfo, epc, epcs, unitstart, headerend - unitstart - 10);
linesize = cpos() - lineo; linesize = cpos() - lineo;
} }
...@@ -1909,6 +1993,9 @@ writeinfo(void) ...@@ -1909,6 +1993,9 @@ writeinfo(void)
vlong unitstart, here; vlong unitstart, here;
fwdcount = 0; fwdcount = 0;
if (dsym == S)
dsym = lookup(".dwarfinfo", 0);
dsym->nr = 0;
for (compunit = dwroot.child; compunit; compunit = compunit->link) { for (compunit = dwroot.child; compunit; compunit = compunit->link) {
unitstart = cpos(); unitstart = cpos();
...@@ -1917,7 +2004,7 @@ writeinfo(void) ...@@ -1917,7 +2004,7 @@ writeinfo(void)
// Fields marked with (*) must be changed for 64-bit dwarf // Fields marked with (*) must be changed for 64-bit dwarf
// This must match COMPUNITHEADERSIZE above. // This must match COMPUNITHEADERSIZE above.
LPUT(0); // unit_length (*), will be filled in later. LPUT(0); // unit_length (*), will be filled in later.
WPUT(3); // dwarf version (appendix F) WPUT(2); // dwarf version (appendix F)
LPUT(0); // debug_abbrev_offset (*) LPUT(0); // debug_abbrev_offset (*)
cput(PtrSize); // address_size cput(PtrSize); // address_size
...@@ -2057,6 +2144,27 @@ align(vlong size) ...@@ -2057,6 +2144,27 @@ align(vlong size)
strnput("", rnd(size, PEFILEALIGN) - size); strnput("", rnd(size, PEFILEALIGN) - size);
} }
static vlong
writeinforeloc(void)
{
int i;
vlong start;
Reloc *r;
start = cpos();
for(r = dsym->r; r < dsym->r+dsym->nr; r++) {
if(iself)
i = elfreloc1(r, r->off);
else if(HEADTYPE == Hdarwin)
i = machoreloc1(r, r->off);
else
i = -1;
if(i < 0)
diag("unsupported obj reloc %d/%d to %s", r->type, r->siz, r->sym->name);
}
return start;
}
/* /*
* This is the main entry point for generating dwarf. After emitting * This is the main entry point for generating dwarf. After emitting
* the mandatory debug_abbrev section, it calls writelines() to set up * the mandatory debug_abbrev section, it calls writelines() to set up
...@@ -2157,6 +2265,10 @@ dwarfemitdebugsections(void) ...@@ -2157,6 +2265,10 @@ dwarfemitdebugsections(void)
gdbscripto = writegdbscript(); gdbscripto = writegdbscript();
gdbscriptsize = cpos() - gdbscripto; gdbscriptsize = cpos() - gdbscripto;
align(gdbscriptsize); align(gdbscriptsize);
inforeloco = writeinforeloc();
inforelocsize = cpos() - inforeloco;
align(inforelocsize);
} }
/* /*
...@@ -2316,6 +2428,8 @@ dwarfaddmachoheaders(void) ...@@ -2316,6 +2428,8 @@ dwarfaddmachoheaders(void)
msect = newMachoSect(ms, "__debug_info", "__DWARF"); msect = newMachoSect(ms, "__debug_info", "__DWARF");
msect->off = infoo; msect->off = infoo;
msect->size = infosize; msect->size = infosize;
msect->reloc = inforeloco;
msect->nreloc = inforelocsize / 8;
ms->filesize += msect->size; ms->filesize += msect->size;
if (pubnamessize > 0) { if (pubnamessize > 0) {
......
...@@ -93,6 +93,7 @@ enum ...@@ -93,6 +93,7 @@ enum
DW_CLS_FLAG, DW_CLS_FLAG,
DW_CLS_PTR, // lineptr, loclistptr, macptr, rangelistptr DW_CLS_PTR, // lineptr, loclistptr, macptr, rangelistptr
DW_CLS_REFERENCE, DW_CLS_REFERENCE,
DW_CLS_ADDRLOC,
DW_CLS_STRING DW_CLS_STRING
}; };
......
...@@ -287,6 +287,7 @@ void ...@@ -287,6 +287,7 @@ void
loadlib(void) loadlib(void)
{ {
int i, w, x; int i, w, x;
Sym *s;
loadinternal("runtime"); loadinternal("runtime");
if(thechar == '5') if(thechar == '5')
...@@ -301,11 +302,20 @@ loadlib(void) ...@@ -301,11 +302,20 @@ loadlib(void)
objfile(library[i].file, library[i].pkg); objfile(library[i].file, library[i].pkg);
} }
if(linkmode == LinkExternal && !iscgo)
linkmode = LinkInternal;
// If we got this far in automatic mode, there were no // If we got this far in automatic mode, there were no
// cgo uses that suggest we need external mode. // cgo uses that suggest we need external mode.
// Switch to internal. // Switch to internal.
if(linkmode == LinkAuto) if(linkmode == LinkAuto) {
linkmode = LinkInternal; linkmode = LinkInternal;
// Drop all the cgo_import_static declarations.
// Turns out we won't be needing them.
for(s = allsym; s != S; s = s->allsym)
if(s->type == SHOSTOBJ)
s->type = 0;
}
// Now that we know the link mode, trim the dynexp list. // Now that we know the link mode, trim the dynexp list.
x = CgoExportDynamic; x = CgoExportDynamic;
...@@ -497,9 +507,11 @@ int mhostobj; ...@@ -497,9 +507,11 @@ int mhostobj;
// These packages can use internal linking mode. // These packages can use internal linking mode.
// Others trigger external mode. // Others trigger external mode.
const char *internalpkg[] = { const char *internalpkg[] = {
"crypto/x509",
"net", "net",
"os/user", "os/user",
"runtime/cgo" "runtime/cgo",
"runtime/race"
}; };
void void
...@@ -618,7 +630,7 @@ hostlink(void) ...@@ -618,7 +630,7 @@ hostlink(void)
break; break;
} }
if(!debug['s']) if(!debug['s'])
argv[argc++] = "-ggdb"; argv[argc++] = "-gdwarf-2";
if(HEADTYPE == Hdarwin) if(HEADTYPE == Hdarwin)
argv[argc++] = "-Wl,-no_pie,-pagezero_size,4000000"; argv[argc++] = "-Wl,-no_pie,-pagezero_size,4000000";
argv[argc++] = "-o"; argv[argc++] = "-o";
......
...@@ -150,7 +150,7 @@ machowrite(void) ...@@ -150,7 +150,7 @@ machowrite(void)
LPUT(0xfeedface); LPUT(0xfeedface);
LPUT(hdr.cpu); LPUT(hdr.cpu);
LPUT(hdr.subcpu); LPUT(hdr.subcpu);
if(isobj) if(linkmode == LinkExternal)
LPUT(1); /* file type - mach object */ LPUT(1); /* file type - mach object */
else else
LPUT(2); /* file type - mach executable */ LPUT(2); /* file type - mach executable */
...@@ -248,7 +248,7 @@ domacho(void) ...@@ -248,7 +248,7 @@ domacho(void)
s->type = SMACHOSYMTAB; s->type = SMACHOSYMTAB;
s->reachable = 1; s->reachable = 1;
if(!isobj) { if(linkmode != LinkExternal) {
s = lookup(".plt", 0); // will be __symbol_stub s = lookup(".plt", 0); // will be __symbol_stub
s->type = SMACHOPLT; s->type = SMACHOPLT;
s->reachable = 1; s->reachable = 1;
...@@ -367,7 +367,7 @@ asmbmacho(void) ...@@ -367,7 +367,7 @@ asmbmacho(void)
} }
ms = nil; ms = nil;
if(isobj) { if(linkmode == LinkExternal) {
/* segment for entire file */ /* segment for entire file */
ms = newMachoSeg("", 40); ms = newMachoSeg("", 40);
ms->fileoffset = segtext.fileoff; ms->fileoffset = segtext.fileoff;
...@@ -375,14 +375,14 @@ asmbmacho(void) ...@@ -375,14 +375,14 @@ asmbmacho(void)
} }
/* segment for zero page */ /* segment for zero page */
if(!isobj) { if(linkmode != LinkExternal) {
ms = newMachoSeg("__PAGEZERO", 0); ms = newMachoSeg("__PAGEZERO", 0);
ms->vsize = va; ms->vsize = va;
} }
/* text */ /* text */
v = rnd(HEADR+segtext.len, INITRND); v = rnd(HEADR+segtext.len, INITRND);
if(!isobj) { if(linkmode != LinkExternal) {
ms = newMachoSeg("__TEXT", 20); ms = newMachoSeg("__TEXT", 20);
ms->vaddr = va; ms->vaddr = va;
ms->vsize = v; ms->vsize = v;
...@@ -396,7 +396,7 @@ asmbmacho(void) ...@@ -396,7 +396,7 @@ asmbmacho(void)
machoshbits(ms, sect, "__TEXT"); machoshbits(ms, sect, "__TEXT");
/* data */ /* data */
if(!isobj) { if(linkmode != LinkExternal) {
w = segdata.len; w = segdata.len;
ms = newMachoSeg("__DATA", 20); ms = newMachoSeg("__DATA", 20);
ms->vaddr = va+v; ms->vaddr = va+v;
...@@ -410,7 +410,7 @@ asmbmacho(void) ...@@ -410,7 +410,7 @@ asmbmacho(void)
for(sect=segdata.sect; sect!=nil; sect=sect->next) for(sect=segdata.sect; sect!=nil; sect=sect->next)
machoshbits(ms, sect, "__DATA"); machoshbits(ms, sect, "__DATA");
if(!isobj) { if(linkmode != LinkExternal) {
switch(thechar) { switch(thechar) {
default: default:
diag("unknown macho architecture"); diag("unknown macho architecture");
...@@ -440,7 +440,7 @@ asmbmacho(void) ...@@ -440,7 +440,7 @@ asmbmacho(void)
s3 = lookup(".linkedit.got", 0); s3 = lookup(".linkedit.got", 0);
s4 = lookup(".machosymstr", 0); s4 = lookup(".machosymstr", 0);
if(!isobj) { if(linkmode != LinkExternal) {
ms = newMachoSeg("__LINKEDIT", 0); ms = newMachoSeg("__LINKEDIT", 0);
ms->vaddr = va+v+rnd(segdata.len, INITRND); ms->vaddr = va+v+rnd(segdata.len, INITRND);
ms->vsize = s1->size + s2->size + s3->size + s4->size; ms->vsize = s1->size + s2->size + s3->size + s4->size;
...@@ -458,7 +458,7 @@ asmbmacho(void) ...@@ -458,7 +458,7 @@ asmbmacho(void)
machodysymtab(); machodysymtab();
if(!isobj) { if(linkmode != LinkExternal) {
ml = newMachoLoad(14, 6); /* LC_LOAD_DYLINKER */ ml = newMachoLoad(14, 6); /* LC_LOAD_DYLINKER */
ml->data[0] = 12; /* offset to string */ ml->data[0] = 12; /* offset to string */
strcpy((char*)&ml->data[1], "/usr/lib/dyld"); strcpy((char*)&ml->data[1], "/usr/lib/dyld");
...@@ -475,7 +475,7 @@ asmbmacho(void) ...@@ -475,7 +475,7 @@ asmbmacho(void)
} }
// TODO: dwarf headers go in ms too // TODO: dwarf headers go in ms too
if(!debug['s'] && !isobj) if(!debug['s'] && linkmode != LinkExternal)
dwarfaddmachoheaders(); dwarfaddmachoheaders();
a = machowrite(); a = machowrite();
...@@ -581,6 +581,9 @@ machosymtab(void) ...@@ -581,6 +581,9 @@ machosymtab(void)
for(i=0; i<nsortsym; i++) { for(i=0; i<nsortsym; i++) {
s = sortsym[i]; s = sortsym[i];
adduint32(symtab, symstr->size); adduint32(symtab, symstr->size);
// Only add _ to C symbols. Go symbols have dot in the name.
if(strstr(s->extname, ".") == nil)
adduint8(symstr, '_'); adduint8(symstr, '_');
addstring(symstr, s->extname); addstring(symstr, s->extname);
if(s->type == SDYNIMPORT || s->type == SHOSTOBJ) { if(s->type == SDYNIMPORT || s->type == SHOSTOBJ) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment