summaryrefslogtreecommitdiff
path: root/src/cmd/ld
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/ld')
-rw-r--r--src/cmd/ld/data.c12
-rw-r--r--src/cmd/ld/dwarf.c112
-rw-r--r--src/cmd/ld/elf.h4
-rw-r--r--src/cmd/ld/go.c6
-rw-r--r--src/cmd/ld/ldpe.c5
-rw-r--r--src/cmd/ld/lib.c43
-rw-r--r--src/cmd/ld/lib.h4
-rw-r--r--src/cmd/ld/macho.c23
-rw-r--r--src/cmd/ld/macho.h2
-rw-r--r--src/cmd/ld/pe.c54
-rw-r--r--src/cmd/ld/pe.h2
-rw-r--r--src/cmd/ld/symtab.c78
12 files changed, 228 insertions, 117 deletions
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index 0cb2b2138..3f3faade0 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -804,6 +804,10 @@ dodata(void)
diag("%s: no size", s->name);
t = 1;
}
+ if(t >= PtrSize)
+ t = rnd(t, PtrSize);
+ else if(t > 2)
+ t = rnd(t, 4);
if(t & 1)
;
else if(t & 2)
@@ -826,6 +830,10 @@ dodata(void)
diag("unexpected symbol type %d", s->type);
}
t = s->size;
+ if(t >= PtrSize)
+ t = rnd(t, PtrSize);
+ else if(t > 2)
+ t = rnd(t, 4);
if(t & 1)
;
else if(t & 2)
@@ -899,10 +907,8 @@ address(void)
segdata.fileoff = va - segtext.vaddr + segtext.fileoff;
if(HEADTYPE == Hwindows)
segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN);
- if(HEADTYPE == Hplan9x32) {
- segdata.vaddr = va = rnd(va, 4096);
+ if(HEADTYPE == Hplan9x32)
segdata.fileoff = segtext.fileoff + segtext.filelen;
- }
for(s=segdata.sect; s != nil; s=s->next) {
s->vaddr = va;
va += s->len;
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index 98b068008..50b42183e 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -529,8 +529,10 @@ find_or_diag(DWDie *die, char* name)
{
DWDie *r;
r = find(die, name);
- if (r == nil)
+ if (r == nil) {
diag("dwarf find: %s has no %s", getattr(die, DW_AT_name)->data, name);
+ errorexit();
+ }
return r;
}
@@ -613,7 +615,7 @@ putattr(int form, int cls, vlong value, char *data)
case DW_FORM_ref_addr: // reference to a DIE in the .info section
if (data == nil) {
- diag("null dwarf reference");
+ diag("dwarf: null reference");
LPUT(0); // invalid dwarf, gdb will complain.
} else {
if (((DWDie*)data)->offs == 0)
@@ -631,7 +633,7 @@ putattr(int form, int cls, vlong value, char *data)
case DW_FORM_strp: // string
case DW_FORM_indirect: // (see Section 7.5.3)
default:
- diag("Unsupported atribute form %d / class %d", form, cls);
+ diag("dwarf: unsupported attribute form %d / class %d", form, cls);
errorexit();
}
}
@@ -823,7 +825,7 @@ decode_inuxi(uchar* p, int sz)
inuxi = inuxi8;
break;
default:
- diag("decode inuxi %d", sz);
+ diag("dwarf: decode inuxi %d", sz);
errorexit();
}
for (i = 0; i < sz; i++)
@@ -1013,7 +1015,7 @@ defgotype(Sym *gotype)
return find_or_diag(&dwtypes, "<unspecified>");
if (strncmp("type.", gotype->name, 5) != 0) {
- diag("Type name doesn't start with \".type\": %s", gotype->name);
+ diag("dwarf: type name doesn't start with \".type\": %s", gotype->name);
return find_or_diag(&dwtypes, "<unspecified>");
}
name = gotype->name + 5; // could also decode from Type.string
@@ -1164,7 +1166,7 @@ defgotype(Sym *gotype)
break;
default:
- diag("definition of unknown kind %d: %s", kind, gotype->name);
+ 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>"));
}
@@ -1346,7 +1348,7 @@ synthesizemaptypes(DWDie *die)
valtype = defptrto(valtype);
newrefattr(fld, DW_AT_type, valtype);
newmemberoffsetattr(fld, hashsize + datavo);
- newattr(dwhe, DW_AT_byte_size, DW_CLS_CONSTANT, hashsize + datsize, NULL);
+ newattr(dwhe, DW_AT_byte_size, DW_CLS_CONSTANT, hashsize + datsize, nil);
// Construct hash_subtable<hash_entry<K,V>>
dwhs = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
@@ -1357,7 +1359,7 @@ synthesizemaptypes(DWDie *die)
substitutetype(dwhs, "end", defptrto(dwhe));
substitutetype(dwhs, "entry", dwhe); // todo: []hash_entry with dynamic size
newattr(dwhs, DW_AT_byte_size, DW_CLS_CONSTANT,
- getattr(hash_subtable, DW_AT_byte_size)->value, NULL);
+ getattr(hash_subtable, DW_AT_byte_size)->value, nil);
// Construct hash<K,V>
dwh = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
@@ -1367,7 +1369,7 @@ synthesizemaptypes(DWDie *die)
copychildren(dwh, hash);
substitutetype(dwh, "st", defptrto(dwhs));
newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT,
- getattr(hash, DW_AT_byte_size)->value, NULL);
+ getattr(hash, DW_AT_byte_size)->value, nil);
newrefattr(die, DW_AT_type, defptrto(dwh));
}
@@ -1399,30 +1401,30 @@ synthesizechantypes(DWDie *die)
// sudog<T>
dws = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
mkinternaltypename("sudog",
- getattr(elemtype, DW_AT_name)->data, NULL));
+ getattr(elemtype, DW_AT_name)->data, nil));
copychildren(dws, sudog);
substitutetype(dws, "elem", elemtype);
newattr(dws, DW_AT_byte_size, DW_CLS_CONSTANT,
- sudogsize + (elemsize > 8 ? elemsize - 8 : 0), NULL);
+ sudogsize + (elemsize > 8 ? elemsize - 8 : 0), nil);
// waitq<T>
dww = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
- mkinternaltypename("waitq", getattr(elemtype, DW_AT_name)->data, NULL));
+ mkinternaltypename("waitq", getattr(elemtype, DW_AT_name)->data, nil));
copychildren(dww, waitq);
substitutetype(dww, "first", defptrto(dws));
substitutetype(dww, "last", defptrto(dws));
newattr(dww, DW_AT_byte_size, DW_CLS_CONSTANT,
- getattr(waitq, DW_AT_byte_size)->value, NULL);
+ getattr(waitq, DW_AT_byte_size)->value, nil);
// hchan<T>
dwh = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
- mkinternaltypename("hchan", getattr(elemtype, DW_AT_name)->data, NULL));
+ mkinternaltypename("hchan", getattr(elemtype, DW_AT_name)->data, nil));
copychildren(dwh, hchan);
substitutetype(dwh, "recvq", dww);
substitutetype(dwh, "sendq", dww);
substitutetype(dwh, "free", defptrto(dws));
newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT,
- getattr(hchan, DW_AT_byte_size)->value, NULL);
+ getattr(hchan, DW_AT_byte_size)->value, nil);
newrefattr(die, DW_AT_type, defptrto(dwh));
}
@@ -1434,6 +1436,7 @@ defdwsymb(Sym* sym, char *s, int t, vlong v, vlong size, int ver, Sym *gotype)
{
DWDie *dv, *dt;
+ USED(size);
if (strncmp(s, "go.string.", 10) == 0)
return;
@@ -1513,12 +1516,12 @@ decodez(char *s)
ss = s + 1; // first is 0
while((o = ((uint8)ss[0] << 8) | (uint8)ss[1]) != 0) {
if (o < 0 || o >= ftabsize) {
- diag("corrupt z entry");
+ diag("dwarf: corrupt z entry");
return 0;
}
f = ftab[o];
if (f == nil) {
- diag("corrupt z entry");
+ diag("dwarf: corrupt z entry");
return 0;
}
len += strlen(f) + 1; // for the '/'
@@ -1590,7 +1593,7 @@ addhistfile(char *zentry)
// if the histfile stack contains ..../runtime/runtime_defs.go
// use that to set gdbscript
static void
-finddebugruntimepath()
+finddebugruntimepath(void)
{
int i, l;
char *c;
@@ -1630,11 +1633,11 @@ checknesting(void)
int i;
if (includetop < 0) {
- diag("corrupt z stack");
+ diag("dwarf: corrupt z stack");
errorexit();
}
if (includetop >= nelem(includestack)) {
- diag("nesting too deep");
+ diag("dwarf: nesting too deep");
for (i = 0; i < nelem(includestack); i++)
diag("\t%s", histfile[includestack[i].file]);
errorexit();
@@ -1660,7 +1663,7 @@ inithist(Auto *a)
// We have a new history. They are guaranteed to come completely
// at the beginning of the compilation unit.
if (a->aoffset != 1) {
- diag("stray 'z' with offset %d", a->aoffset);
+ diag("dwarf: stray 'z' with offset %d", a->aoffset);
return 0;
}
@@ -1801,7 +1804,7 @@ mkvarname(char* name, int da)
// flush previous compilation unit.
static void
-flushunit(DWDie *dwinfo, vlong pc, vlong unitstart)
+flushunit(DWDie *dwinfo, vlong pc, vlong unitstart, int32 header_length)
{
vlong here;
@@ -1817,7 +1820,9 @@ flushunit(DWDie *dwinfo, vlong pc, vlong unitstart)
here = cpos();
seek(cout, unitstart, 0);
- LPUT(here - unitstart - sizeof(int32));
+ LPUT(here - unitstart - sizeof(int32)); // unit_length
+ WPUT(3); // dwarf version
+ LPUT(header_length); // header lenght starting here
cflush();
seek(cout, here, 0);
}
@@ -1829,7 +1834,7 @@ writelines(void)
Prog *q;
Sym *s;
Auto *a;
- vlong unitstart, offs;
+ vlong unitstart, headerend, offs;
vlong pc, epc, lc, llc, lline;
int currfile;
int i, lang, da, dt;
@@ -1839,7 +1844,9 @@ writelines(void)
char *n, *nn;
unitstart = -1;
- epc = pc = 0;
+ headerend = -1;
+ pc = 0;
+ epc = 0;
lc = 1;
llc = 1;
currfile = -1;
@@ -1855,7 +1862,7 @@ writelines(void)
// we're entering a new compilation unit
if (inithist(s->autom)) {
- flushunit(dwinfo, epc, unitstart);
+ flushunit(dwinfo, epc, unitstart, headerend - unitstart - 10);
unitstart = cpos();
if(debug['v'] > 1) {
@@ -1876,10 +1883,10 @@ writelines(void)
// Write .debug_line Line Number Program Header (sec 6.2.4)
// Fields marked with (*) must be changed for 64-bit dwarf
- LPUT(0); // unit_length (*), will be filled in later.
+ LPUT(0); // unit_length (*), will be filled in by flushunit.
WPUT(3); // dwarf version (appendix F)
- LPUT(11); // header_length (*), starting here.
-
+ LPUT(0); // header_length (*), filled in by flushunit.
+ // cpos == unitstart + 4 + 2 + 4
cput(1); // minimum_instruction_length
cput(1); // default_is_stmt
cput(LINE_BASE); // line_base
@@ -1890,18 +1897,17 @@ writelines(void)
cput(1); // standard_opcode_lengths[3]
cput(1); // standard_opcode_lengths[4]
cput(0); // include_directories (empty)
- cput(0); // file_names (empty) (emitted by DW_LNE's below)
- // header_length ends here.
for (i=1; i < histfilesize; i++) {
- cput(0); // start extended opcode
- uleb128put(1 + strlen(histfile[i]) + 4);
- cput(DW_LNE_define_file);
strnput(histfile[i], strlen(histfile[i]) + 4);
// 4 zeros: the string termination + 3 fields.
}
- epc = pc = s->text->pc;
+ cput(0); // terminate file_names.
+ headerend = cpos();
+
+ pc = s->text->pc;
+ epc = pc;
currfile = 1;
lc = 1;
llc = 1;
@@ -1915,7 +1921,7 @@ writelines(void)
continue;
if (unitstart < 0) {
- diag("reachable code before seeing any history: %P", s->text);
+ diag("dwarf: reachable code before seeing any history: %P", s->text);
continue;
}
@@ -1932,7 +1938,7 @@ writelines(void)
for(q = s->text; q != P; q = q->link) {
lh = searchhist(q->line);
if (lh == nil) {
- diag("corrupt history or bad absolute line: %P", q);
+ diag("dwarf: corrupt history or bad absolute line: %P", q);
continue;
}
@@ -1990,7 +1996,7 @@ writelines(void)
newrefattr(dwvar, DW_AT_type, defgotype(a->gotype));
// push dwvar down dwfunc->child to preserve order
- newattr(dwvar, DW_AT_internal_location, DW_CLS_CONSTANT, offs, NULL);
+ newattr(dwvar, DW_AT_internal_location, DW_CLS_CONSTANT, offs, nil);
dwfunc->child = dwvar->link; // take dwvar out from the top of the list
for (dws = &dwfunc->child; *dws != nil; dws = &(*dws)->link)
if (offs > getattr(*dws, DW_AT_internal_location)->value)
@@ -2004,7 +2010,7 @@ writelines(void)
dwfunc->hash = nil;
}
- flushunit(dwinfo, epc, unitstart);
+ flushunit(dwinfo, epc, unitstart, headerend - unitstart - 10);
linesize = cpos() - lineo;
}
@@ -2066,7 +2072,7 @@ writeframes(void)
// 4 is to exclude the length field.
pad = CIERESERVE + frameo + 4 - cpos();
if (pad < 0) {
- diag("CIERESERVE too small by %lld bytes.", -pad);
+ diag("dwarf: CIERESERVE too small by %lld bytes.", -pad);
errorexit();
}
strnput("", pad);
@@ -2296,6 +2302,9 @@ dwarfemitdebugsections(void)
vlong infoe;
DWDie* die;
+ if(debug['w']) // disable dwarf
+ return;
+
// For diagnostic messages.
newattr(&dwtypes, DW_AT_name, DW_CLS_STRING, strlen("dwtypes"), "dwtypes");
@@ -2340,7 +2349,11 @@ dwarfemitdebugsections(void)
infoo = cpos();
writeinfo();
- gdbscripto = arangeso = pubtypeso = pubnameso = infoe = cpos();
+ infoe = cpos();
+ pubnameso = infoe;
+ pubtypeso = infoe;
+ arangeso = infoe;
+ gdbscripto = infoe;
if (fwdcount > 0) {
if (debug['v'])
@@ -2348,11 +2361,11 @@ dwarfemitdebugsections(void)
seek(cout, infoo, 0);
writeinfo();
if (fwdcount > 0) {
- diag("unresolved references after first dwarf info pass");
+ diag("dwarf: unresolved references after first dwarf info pass");
errorexit();
}
if (infoe != cpos()) {
- diag("inconsistent second dwarf info pass");
+ diag("dwarf: inconsistent second dwarf info pass");
errorexit();
}
}
@@ -2401,6 +2414,9 @@ vlong elfstrdbg[NElfStrDbg];
void
dwarfaddshstrings(Sym *shstrtab)
{
+ if(debug['w']) // disable dwarf
+ return;
+
elfstrdbg[ElfStrDebugAbbrev] = addstring(shstrtab, ".debug_abbrev");
elfstrdbg[ElfStrDebugAranges] = addstring(shstrtab, ".debug_aranges");
elfstrdbg[ElfStrDebugFrame] = addstring(shstrtab, ".debug_frame");
@@ -2420,6 +2436,9 @@ dwarfaddelfheaders(void)
{
ElfShdr *sh;
+ if(debug['w']) // disable dwarf
+ return;
+
sh = newElfShdr(elfstrdbg[ElfStrDebugAbbrev]);
sh->type = SHT_PROGBITS;
sh->off = abbrevo;
@@ -2488,6 +2507,9 @@ dwarfaddmachoheaders(void)
vlong fakestart;
int nsect;
+ if(debug['w']) // disable dwarf
+ return;
+
// Zero vsize segments won't be loaded in memory, even so they
// have to be page aligned in the file.
fakestart = abbrevo & ~0xfff;
@@ -2562,7 +2584,9 @@ dwarfaddmachoheaders(void)
void
dwarfaddpeheaders(void)
{
- dwarfemitdebugsections();
+ if(debug['w']) // disable dwarf
+ return;
+
newPEDWARFSection(".debug_abbrev", abbrevsize);
newPEDWARFSection(".debug_line", linesize);
newPEDWARFSection(".debug_frame", framesize);
diff --git a/src/cmd/ld/elf.h b/src/cmd/ld/elf.h
index 08583cc8f..d1370d28b 100644
--- a/src/cmd/ld/elf.h
+++ b/src/cmd/ld/elf.h
@@ -978,6 +978,10 @@ ElfShdr* elfshbits(Section*);
void elfsetstring(char*, int);
void elfaddverneed(Sym*);
+EXTERN int elfstrsize;
+EXTERN char* elfstrdat;
+EXTERN int elftextsh;
+
/*
* Total amount of space to reserve at the start of the file
* for Header, PHeaders, SHeaders, and interp.
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c
index e52c5cb34..05d1cc136 100644
--- a/src/cmd/ld/go.c
+++ b/src/cmd/ld/go.c
@@ -415,8 +415,8 @@ loaddynimport(char *file, char *pkg, char *p, int n)
char *pend, *next, *name, *def, *p0, *lib, *q;
Sym *s;
+ USED(file);
pend = p + n;
- p0 = p;
for(; p<pend; p=next) {
next = strchr(p, '\n');
if(next == nil)
@@ -454,6 +454,7 @@ loaddynimport(char *file, char *pkg, char *p, int n)
if(strcmp(name, "_") == 0 && strcmp(def, "_") == 0) {
// allow #pragma dynimport _ _ "foo.so"
// to force a link of foo.so.
+ havedynamic = 1;
adddynlib(lib);
continue;
}
@@ -468,6 +469,7 @@ loaddynimport(char *file, char *pkg, char *p, int n)
s->dynimpname = def;
s->dynimpvers = q;
s->type = SDYNIMPORT;
+ havedynamic = 1;
}
}
return;
@@ -483,8 +485,8 @@ loaddynexport(char *file, char *pkg, char *p, int n)
char *pend, *next, *local, *elocal, *remote, *p0;
Sym *s;
+ USED(file);
pend = p + n;
- p0 = p;
for(; p<pend; p=next) {
next = strchr(p, '\n');
if(next == nil)
diff --git a/src/cmd/ld/ldpe.c b/src/cmd/ld/ldpe.c
index d8b0a6fc2..d6aa267c4 100644
--- a/src/cmd/ld/ldpe.c
+++ b/src/cmd/ld/ldpe.c
@@ -147,7 +147,7 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
goto bad;
obj->sect[i].size = obj->sect[i].sh.SizeOfRawData;
obj->sect[i].name = (char*)obj->sect[i].sh.Name;
- // TODO return error if found .cormeta .rsrc
+ // TODO return error if found .cormeta
}
// load string table
Bseek(f, base+obj->fh.PointerToSymbolTable+18*obj->fh.NumberOfSymbols, 0);
@@ -222,6 +222,8 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
etextp = s;
}
sect->sym = s;
+ if(strcmp(sect->name, ".rsrc") == 0)
+ setpersrc(sect->sym);
}
// load relocations
@@ -259,6 +261,7 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
rp->type = D_PCREL;
rp->add = 0;
break;
+ case IMAGE_REL_I386_DIR32NB:
case IMAGE_REL_I386_DIR32:
rp->type = D_ADDR;
// load addend from image
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index 15219ba11..04ee790a4 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -69,7 +69,7 @@ libinit(void)
// add goroot to the end of the libdir list.
libdir[nlibdir++] = smprint("%s/pkg/%s_%s", goroot, goos, goarch);
- unlink(outfile);
+ remove(outfile);
cout = create(outfile, 1, 0775);
if(cout < 0) {
diag("cannot create %s", outfile);
@@ -235,30 +235,52 @@ addlibpath(char *srcref, char *objref, char *file, char *pkg)
}
void
-loadlib(void)
+loadinternal(char *name)
{
char pname[1024];
int i, found;
found = 0;
for(i=0; i<nlibdir; i++) {
- snprint(pname, sizeof pname, "%s/runtime.a", libdir[i]);
+ snprint(pname, sizeof pname, "%s/%s.a", libdir[i], name);
if(debug['v'])
- Bprint(&bso, "searching for runtime.a in %s\n", pname);
+ Bprint(&bso, "searching for %s.a in %s\n", name, pname);
if(access(pname, AEXIST) >= 0) {
- addlibpath("internal", "internal", pname, "runtime");
+ addlibpath("internal", "internal", pname, name);
found = 1;
break;
}
}
if(!found)
- Bprint(&bso, "warning: unable to find runtime.a\n");
+ Bprint(&bso, "warning: unable to find %s.a\n", name);
+}
+
+void
+loadlib(void)
+{
+ int i;
+
+ loadinternal("runtime");
+ if(thechar == '5')
+ loadinternal("math");
for(i=0; i<libraryp; i++) {
if(debug['v'])
Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i].file, library[i].objref);
objfile(library[i].file, library[i].pkg);
}
+
+ // We've loaded all the code now.
+ // If there are no dynamic libraries needed, gcc disables dynamic linking.
+ // Because of this, glibc's dynamic ELF loader occasionally (like in version 2.13)
+ // assumes that a dynamic binary always refers to at least one dynamic library.
+ // Rather than be a source of test cases for glibc, disable dynamic linking
+ // the same way that gcc would.
+ //
+ // Exception: on OS X, programs such as Shark only work with dynamic
+ // binaries, so leave it enabled on OS X (Mach-O) binaries.
+ if(!havedynamic && HEADTYPE != Hdarwin)
+ debug['d'] = 1;
}
/*
@@ -386,9 +408,6 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
eof = Boffset(f) + len;
pn = strdup(pn);
-
- USED(c4);
- USED(magic);
c1 = Bgetc(f);
c2 = Bgetc(f);
@@ -398,7 +417,7 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
Bungetc(f);
Bungetc(f);
Bungetc(f);
-
+
magic = c1<<24 | c2<<16 | c3<<8 | c4;
if(magic == 0x7f454c46) { // \x7F E L F
ldelf(f, pkg, len, pn);
@@ -486,7 +505,6 @@ _lookup(char *symb, int v, int creat)
// not if(h < 0) h = ~h, because gcc 4.3 -O2 miscompiles it.
h &= 0xffffff;
h %= NHASH;
- c = symb[0];
for(s = hash[h]; s != S; s = s->hash)
if(memcmp(s->name, symb, l) == 0)
return s;
@@ -511,7 +529,7 @@ _lookup(char *symb, int v, int creat)
s->size = 0;
hash[h] = s;
nsymbol++;
-
+
s->allsym = allsym;
allsym = s;
return s;
@@ -538,7 +556,6 @@ copyhistfrog(char *buf, int nbuf)
p = buf;
ep = buf + nbuf;
- i = 0;
for(i=0; i<histfrogp; i++) {
p = seprint(p, ep, "%s", histfrog[i]->name+1);
if(i+1<histfrogp && (p == buf || p[-1] != '/'))
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index 8b603a04a..dfd18fbff 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -122,6 +122,7 @@ EXTERN char* outfile;
EXTERN int32 nsymbol;
EXTERN char* thestring;
EXTERN int ndynexp;
+EXTERN int havedynamic;
EXTERN Segment segtext;
EXTERN Segment segdata;
@@ -185,7 +186,7 @@ vlong addsize(Sym*, Sym*);
vlong adduint8(Sym*, uint8);
vlong adduint16(Sym*, uint16);
void asmsym(void);
-void asmelfsym64(void);
+void asmelfsym(void);
void asmplan9sym(void);
void strnput(char*, int);
void dodata(void);
@@ -200,6 +201,7 @@ void addexport(void);
void dostkcheck(void);
void undef(void);
void doweak(void);
+void setpersrc(Sym*);
int pathchar(void);
void* mal(uint32);
diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c
index 01349bb10..0b12ac17b 100644
--- a/src/cmd/ld/macho.c
+++ b/src/cmd/ld/macho.c
@@ -17,6 +17,14 @@ static MachoSeg seg[16];
static MachoDebug xdebug[16];
static int nload, mload, nseg, ndebug, nsect;
+// Amount of space left for adding load commands
+// that refer to dynamic libraries. Because these have
+// to go in the Mach-O header, we can't just pick a
+// "big enough" header size. The initial header is
+// one page, the non-dynamic library stuff takes
+// up about 1300 bytes; we overestimate that as 2k.
+static int load_budget = INITIAL_MACHO_HEADR - 2*1024;
+
void
machoinit(void)
{
@@ -267,6 +275,17 @@ domacho(void)
void
machoadddynlib(char *lib)
{
+ // Will need to store the library name rounded up
+ // and 24 bytes of header metadata. If not enough
+ // space, grab another page of initial space at the
+ // beginning of the output file.
+ load_budget -= (strlen(lib)+7)/8*8 + 24;
+ if(load_budget < 0) {
+ HEADR += 4096;
+ INITTEXT += 4096;
+ load_budget += 4096;
+ }
+
if(ndylib%32 == 0) {
dylib = realloc(dylib, (ndylib+32)*sizeof dylib[0]);
if(dylib == nil) {
@@ -463,8 +482,8 @@ asmbmacho(void)
}
a = machowrite();
- if(a > MACHORESERVE)
- diag("MACHORESERVE too small: %d > %d", a, MACHORESERVE);
+ if(a > HEADR)
+ diag("HEADR too small: %d > %d", a, HEADR);
}
vlong
diff --git a/src/cmd/ld/macho.h b/src/cmd/ld/macho.h
index 4cc7edc80..f55104150 100644
--- a/src/cmd/ld/macho.h
+++ b/src/cmd/ld/macho.h
@@ -63,7 +63,7 @@ void machoinit(void);
* for Header, PHeaders, and SHeaders.
* May waste some.
*/
-#define MACHORESERVE 3*1024
+#define INITIAL_MACHO_HEADR 4*1024
enum {
MACHO_CPU_AMD64 = (1<<24)|7,
diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c
index d523ca9c5..91e15d343 100644
--- a/src/cmd/ld/pe.c
+++ b/src/cmd/ld/pe.c
@@ -34,6 +34,8 @@ static char dosstub[] =
0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+static Sym *rsrcsym;
+
static char symnames[256];
static int nextsymoff;
@@ -459,6 +461,48 @@ addsymtable(void)
}
void
+setpersrc(Sym *sym)
+{
+ if(rsrcsym != nil)
+ diag("too many .rsrc sections");
+
+ rsrcsym = sym;
+}
+
+void
+addpersrc(void)
+{
+ IMAGE_SECTION_HEADER *h;
+ uchar *p;
+ uint32 val;
+ Reloc *r;
+
+ if(rsrcsym == nil)
+ return;
+
+ h = addpesection(".rsrc", rsrcsym->size, rsrcsym->size, 0);
+ h->Characteristics = IMAGE_SCN_MEM_READ|
+ IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA;
+ // relocation
+ for(r=rsrcsym->r; r<rsrcsym->r+rsrcsym->nr; r++) {
+ p = rsrcsym->p + r->off;
+ val = h->VirtualAddress + r->add;
+ // 32-bit little-endian
+ p[0] = val;
+ p[1] = val>>8;
+ p[2] = val>>16;
+ p[3] = val>>24;
+ }
+ ewrite(cout, rsrcsym->p, rsrcsym->size);
+ strnput("", h->SizeOfRawData - rsrcsym->size);
+ cflush();
+
+ // update data directory
+ dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h->VirtualAddress;
+ dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h->VirtualSize;
+}
+
+void
asmbpe(void)
{
IMAGE_SECTION_HEADER *t, *d;
@@ -484,15 +528,17 @@ asmbpe(void)
d->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|
IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
+ if(!debug['s'])
+ dwarfaddpeheaders();
+
addimports(nextfileoff, d);
addexports(nextfileoff);
- if(!debug['s'])
- dwarfaddpeheaders();
-
addsymtable();
-
+
+ addpersrc();
+
fh.NumberOfSections = nsect;
fh.TimeDateStamp = time(0);
fh.Characteristics = IMAGE_FILE_RELOCS_STRIPPED|
diff --git a/src/cmd/ld/pe.h b/src/cmd/ld/pe.h
index 2180fb88c..7aa938829 100644
--- a/src/cmd/ld/pe.h
+++ b/src/cmd/ld/pe.h
@@ -175,3 +175,5 @@ typedef struct {
uint32 NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[16];
} PE64_IMAGE_OPTIONAL_HEADER;
+
+void setpersrc(Sym *sym);
diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c
index da698fcc0..e3093b2aa 100644
--- a/src/cmd/ld/symtab.c
+++ b/src/cmd/ld/symtab.c
@@ -61,49 +61,35 @@ putelfstr(char *s)
}
void
-putelfsym64(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
+putelfsyment(int off, vlong addr, vlong size, int info, int shndx)
{
- int bind, type, shndx, stroff;
-
- bind = STB_GLOBAL;
- switch(t) {
- default:
- return;
- case 'T':
- type = STT_FUNC;
- shndx = elftextsh + 0;
- break;
- case 'D':
- type = STT_OBJECT;
- shndx = elftextsh + 1;
+ switch(thechar) {
+ case '6':
+ LPUT(off);
+ cput(info);
+ cput(0);
+ WPUT(shndx);
+ VPUT(addr);
+ VPUT(size);
+ symsize += ELF64SYMSIZE;
break;
- case 'B':
- type = STT_OBJECT;
- shndx = elftextsh + 2;
+ default:
+ LPUT(off);
+ LPUT(addr);
+ LPUT(size);
+ cput(info);
+ cput(0);
+ WPUT(shndx);
+ symsize += ELF32SYMSIZE;
break;
}
-
- stroff = putelfstr(s);
- LPUT(stroff); // string
- cput((bind<<4)|(type&0xF));
- cput(0);
- WPUT(shndx);
- VPUT(addr);
- VPUT(size);
}
void
-asmelfsym64(void)
+putelfsym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
{
- genasmsym(putelfsym64);
-}
+ int bind, type, shndx, off;
-void
-putelfsym32(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
-{
- int bind, type, shndx, stroff;
-
- bind = STB_GLOBAL;
switch(t) {
default:
return;
@@ -113,27 +99,27 @@ putelfsym32(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
break;
case 'D':
type = STT_OBJECT;
- shndx = elftextsh + 1;
+ if((x->type&~SSUB) == SRODATA)
+ shndx = elftextsh + 1;
+ else
+ shndx = elftextsh + 2;
break;
case 'B':
type = STT_OBJECT;
- shndx = elftextsh + 2;
+ shndx = elftextsh + 3;
break;
}
-
- stroff = putelfstr(s);
- LPUT(stroff); // string
- LPUT(addr);
- LPUT(size);
- cput((bind<<4)|(type&0xF));
- cput(0);
- WPUT(shndx);
+ bind = ver ? STB_LOCAL : STB_GLOBAL;
+ off = putelfstr(s);
+ putelfsyment(off, addr, size, (bind<<4)|(type&0xf), shndx);
}
void
-asmelfsym32(void)
+asmelfsym(void)
{
- genasmsym(putelfsym32);
+ // the first symbol entry is reserved
+ putelfsyment(0, 0, 0, (STB_LOCAL<<4)|STT_NOTYPE, 0);
+ genasmsym(putelfsym);
}
void