aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/ld/lib.c
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2010-12-08 13:56:43 -0500
committerRuss Cox <rsc@golang.org>2010-12-08 13:56:43 -0500
commitf5690004c2f5a5e478b66c2390d7ddba96cd7291 (patch)
tree32d33548e9b7a1a35248a315af8cec95c7e9fa22 /src/cmd/ld/lib.c
parent9042c2ce6840a7679739e6ec6ff59b57db30c459 (diff)
downloadgo-f5690004c2f5a5e478b66c2390d7ddba96cd7291.tar.xz
6l, 8l: support for linking ELF and Mach-O .o files
More support for references to dynamic symbols, including full GOT and PLT for ELF objects. For Mach-O everything ends up in the GOT: dealing with the real lazy PLT is too hard for now so we punt. R=iant, iant2 CC=golang-dev https://golang.org/cl/3491042
Diffstat (limited to 'src/cmd/ld/lib.c')
-rw-r--r--src/cmd/ld/lib.c92
1 files changed, 74 insertions, 18 deletions
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index e666515c04..0aefb3e92b 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -374,32 +374,38 @@ out:
void
ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
{
- static int files;
- static char **filen;
- char **nfilen, *line;
- int i, n, c1, c2, c3;
+ char *line;
+ int n, c1, c2, c3, c4;
+ uint32 magic;
vlong import0, import1, eof;
char src[1024];
eof = Boffset(f) + len;
src[0] = '\0';
- // don't load individual object more than once.
- // happens with import of .6 files because of loop in xresolv.
- // doesn't happen with .a because SYMDEF is consulted
- // first to decide whether each individual object file is needed.
- for(i=0; i<files; i++)
- if(strcmp(filen[i], pn) == 0)
- return;
+ pn = strdup(pn);
+
+ USED(c4);
+ USED(magic);
- if((files&15) == 0){
- nfilen = malloc((files+16)*sizeof(char*));
- memmove(nfilen, filen, files*sizeof(char*));
- free(filen);
- filen = nfilen;
+ c1 = Bgetc(f);
+ c2 = Bgetc(f);
+ c3 = Bgetc(f);
+ c4 = Bgetc(f);
+ Bungetc(f);
+ 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);
+ return;
+ }
+ if((magic&~1) == 0xfeedface || (magic&~0x01000000) == 0xcefaedfe) {
+ ldmacho(f, pkg, len, pn);
+ return;
}
- pn = strdup(pn);
- filen[files++] = pn;
/* check the header */
line = Brdline(f, '\n');
@@ -471,6 +477,9 @@ lookup(char *symb, int v)
if(debug['v'] > 1)
Bprint(&bso, "lookup %s\n", symb);
+ s->dynid = -1;
+ s->plt = -1;
+ s->got = -1;
s->name = mal(l + 1);
memmove(s->name, symb, l);
@@ -766,11 +775,19 @@ mal(uint32 n)
n = (n+7)&~7;
if(n > NHUNK) {
v = malloc(n);
+ if(v == nil) {
+ diag("out of memory");
+ errorexit();
+ }
memset(v, 0, n);
return v;
}
if(n > nhunk) {
hunk = malloc(NHUNK);
+ if(hunk == nil) {
+ diag("out of memory");
+ errorexit();
+ }
nhunk = NHUNK;
}
@@ -1013,3 +1030,42 @@ mkfwd(void)
}
}
}
+
+uint16
+le16(uchar *b)
+{
+ return b[0] | b[1]<<8;
+}
+
+uint32
+le32(uchar *b)
+{
+ return b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24;
+}
+
+uint64
+le64(uchar *b)
+{
+ return le32(b) | (uint64)le32(b+4)<<32;
+}
+
+uint16
+be16(uchar *b)
+{
+ return b[0]<<8 | b[1];
+}
+
+uint32
+be32(uchar *b)
+{
+ return b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
+}
+
+uint64
+be64(uchar *b)
+{
+ return (uvlong)be32(b)<<32 | be32(b+4);
+}
+
+Endian be = { be16, be32, be64 };
+Endian le = { le16, le32, le64 };