diff options
| author | Shenghou Ma <minux.ma@gmail.com> | 2012-05-05 01:54:16 +0800 |
|---|---|---|
| committer | Shenghou Ma <minux.ma@gmail.com> | 2012-05-05 01:54:16 +0800 |
| commit | dac4c3eee949ccc395bde808832ab7b2bba370da (patch) | |
| tree | 928d76836cf0ac156b9f6737574a363f4f6ff023 /src/cmd/ld | |
| parent | a29304bfb8c2b9afc0e0a5d6f7ffd2bfb2b51373 (diff) | |
| download | go-dac4c3eee949ccc395bde808832ab7b2bba370da.tar.xz | |
cmd/cgo, cmd/cc, cmd/ld: detect dynamic linker automatically
Some newer Linux distributions (Ubuntu ARM at least) use a new multiarch
directory organization, where dynamic linker is no longer in the hardcoded
path in our linker.
For example, Ubuntu 12.04 ARM hardfloat places its dynamic linker at
/lib/arm-linux-gnueabihf/ld-linux.so.3
Ref: http://lackof.org/taggart/hacking/multiarch/
Also, to support Debian GNU/kFreeBSD as a FreeBSD variant, we need this capability, so it's part of issue 3533.
This CL add a new pragma (#pragma dynlinker "path") to cc.
R=iant, rsc
CC=golang-dev
https://golang.org/cl/6086043
Diffstat (limited to 'src/cmd/ld')
| -rw-r--r-- | src/cmd/ld/go.c | 64 |
1 files changed, 62 insertions, 2 deletions
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c index 3271be1f59..78f76bf121 100644 --- a/src/cmd/ld/go.c +++ b/src/cmd/ld/go.c @@ -69,6 +69,7 @@ ilookup(char *name) static void loadpkgdata(char*, char*, char*, int); static void loaddynimport(char*, char*, char*, int); static void loaddynexport(char*, char*, char*, int); +static void loaddynlinker(char*, char*, char*, int); static int parsemethod(char**, char*, char**); static int parsepkgdata(char*, char*, char**, char*, char**, char**, char**); @@ -204,7 +205,7 @@ ldpkg(Biobuf *f, char *pkg, int64 len, char *filename, int whence) if(p0 != nil) { p0 = strchr(p0+1, '\n'); if(p0 == nil) { - fprint(2, "%s: found $$ // dynexporg but no newline in %s\n", argv0, filename); + fprint(2, "%s: found $$ // dynexport but no newline in %s\n", argv0, filename); if(debug['u']) errorexit(); return; @@ -213,13 +214,34 @@ ldpkg(Biobuf *f, char *pkg, int64 len, char *filename, int whence) if(p1 == nil) p1 = strstr(p0, "\n!\n"); if(p1 == nil) { - fprint(2, "%s: cannot find end of // dynexporg section in %s\n", argv0, filename); + fprint(2, "%s: cannot find end of // dynexport section in %s\n", argv0, filename); if(debug['u']) errorexit(); return; } loaddynexport(filename, pkg, p0 + 1, p1 - (p0+1)); } + + p0 = strstr(p1, "\n$$ // dynlinker"); + if(p0 != nil) { + p0 = strchr(p0+1, '\n'); + if(p0 == nil) { + fprint(2, "%s: found $$ // dynlinker but no newline in %s\n", argv0, filename); + if(debug['u']) + errorexit(); + return; + } + p1 = strstr(p0, "\n$$"); + if(p1 == nil) + p1 = strstr(p0, "\n!\n"); + if(p1 == nil) { + fprint(2, "%s: cannot find end of // dynlinker section in %s\n", argv0, filename); + if(debug['u']) + errorexit(); + return; + } + loaddynlinker(filename, pkg, p0 + 1, p1 - (p0+1)); + } } static void @@ -551,6 +573,44 @@ err: nerrors++; } +static void +loaddynlinker(char *file, char *pkg, char *p, int n) +{ + char *pend, *next, *dynlinker, *p0; + + USED(file); + pend = p + n; + for(; p<pend; p=next) { + next = strchr(p, '\n'); + if(next == nil) + next = ""; + else + *next++ = '\0'; + p0 = p; + if(strncmp(p, "dynlinker ", 10) != 0) + goto err; + p += 10; + dynlinker = p; + + if(*dynlinker == '\0') + goto err; + if(!debug['I']) { // not overrided by cmdline + if(interpreter != nil && strcmp(interpreter, dynlinker) != 0) { + fprint(2, "%s: conflict dynlinker: %s and %s\n", argv0, interpreter, dynlinker); + nerrors++; + return; + } + free(interpreter); + interpreter = strdup(dynlinker); + } + } + return; + +err: + fprint(2, "%s: invalid dynlinker line: %s\n", argv0, p0); + nerrors++; +} + static int markdepth; static void |
