aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/ld/symtab.c
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2013-01-04 17:03:57 -0500
committerRuss Cox <rsc@golang.org>2013-01-04 17:03:57 -0500
commit4e2aa9bff0eb76f98bb3b238c7f56bea6330f70d (patch)
tree41167a6068d324f4cc6df70088d8d4ce9e1c7c7f /src/cmd/ld/symtab.c
parentf1e4ee3f49fd19d72fa3bbcbce4aab5c2fbef2ed (diff)
downloadgo-4e2aa9bff0eb76f98bb3b238c7f56bea6330f70d.tar.xz
cmd/ld: use native-endian symbol values in symbol table
The Plan 9 symbol table format defines big-endian symbol values for portability, but we want to be able to generate an ELF object file and let the host linker link it, as part of the solution to issue 4069. The symbol table itself, since it is loaded into memory at run time, must be filled in by the final host linker, using relocation directives to set the symbol values. On a little-endian machine, the linker will only fill in little-endian values during relocation, so we are forced to use little-endian symbol values. To preserve most of the original portability of the symbol table format, we make the table itself say whether it uses big- or little-endian values. If the table begins with the magic sequence fe ff ff ff 00 00 then the actual table begins after those six bytes and contains little-endian symbol values. Otherwise, the table is in the original format and contains big-endian symbol values. The magic sequence looks like an "end of table" entry (the fifth byte is zero), so legacy readers will see a little-endian table as an empty table. All the gc architectures are little-endian today, so the practical effect of this CL is to make all the generated tables little-endian, but if a big-endian system comes along, ld will not generate the magic sequence, and the various readers will fall back to the original big-endian interpretation. R=ken2 CC=golang-dev https://golang.org/cl/7066043
Diffstat (limited to 'src/cmd/ld/symtab.c')
-rw-r--r--src/cmd/ld/symtab.c65
1 files changed, 55 insertions, 10 deletions
diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c
index a27b181edc..92627f5986 100644
--- a/src/cmd/ld/symtab.c
+++ b/src/cmd/ld/symtab.c
@@ -199,7 +199,7 @@ static void
slputb(int32 v)
{
uchar *p;
-
+
symgrow(symt, symt->size+4);
p = symt->p + symt->size;
*p++ = v>>24;
@@ -209,6 +209,22 @@ slputb(int32 v)
symt->size += 4;
}
+static void
+slputl(int32 v)
+{
+ uchar *p;
+
+ symgrow(symt, symt->size+4);
+ p = symt->p + symt->size;
+ *p++ = v;
+ *p++ = v>>8;
+ *p++ = v>>16;
+ *p = v>>24;
+ symt->size += 4;
+}
+
+static void (*slput)(int32);
+
void
wputl(ushort w)
{
@@ -269,15 +285,24 @@ putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ)
// l = 8;
if(s != nil) {
rel = addrel(symt);
- rel->siz = l + Rbig;
+ rel->siz = l;
rel->sym = s;
rel->type = D_ADDR;
rel->off = symt->size;
v = 0;
- }
- if(l == 8)
- slputb(v>>32);
- slputb(v);
+ }
+
+ if(l == 8) {
+ if(slput == slputl) {
+ slputl(v);
+ slputl(v>>32);
+ } else {
+ slputb(v>>32);
+ slputb(v);
+ }
+ } else
+ slput(v);
+
if(ver)
t += 'a' - 'A';
scput(t+0x80); /* 0x80 is variable length */
@@ -306,8 +331,8 @@ putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ)
rel->off = symt->size;
}
if(l == 8)
- slputb(0);
- slputb(0);
+ slput(0);
+ slput(0);
if(debug['n']) {
if(t == 'z' || t == 'Z') {
@@ -356,7 +381,7 @@ symtab(void)
xdefine("end", SBSS, 0);
xdefine("epclntab", SRODATA, 0);
xdefine("esymtab", SRODATA, 0);
-
+
// pseudo-symbols to mark locations of type, string, and go string data.
s = lookup("type.*", 0);
s->type = STYPE;
@@ -372,7 +397,7 @@ symtab(void)
symt->type = SSYMTAB;
symt->size = 0;
symt->reachable = 1;
-
+
// assign specific types so that they sort together.
// within a type they sort by size, so the .* symbols
// just defined above will be first.
@@ -396,5 +421,25 @@ symtab(void)
if(debug['s'])
return;
+
+ switch(thechar) {
+ default:
+ diag("unknown architecture %c", thechar);
+ errorexit();
+ case '5':
+ case '6':
+ case '8':
+ // magic entry to denote little-endian symbol table
+ slputl(0xfffffffe);
+ scput(0);
+ scput(0);
+ slput = slputl;
+ break;
+ case 'v':
+ // big-endian (in case one comes along)
+ slput = slputb;
+ break;
+ }
+
genasmsym(putsymb);
}