From a64243770d5a68d5e4aeacfeb3b5d259c75cf734 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Sat, 5 May 2012 01:54:16 +0800 Subject: 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 http://codereview.appspot.com/6086043 --- src/cmd/5c/swt.c | 4 ++++ src/cmd/5l/obj.c | 1 + src/cmd/6c/swt.c | 4 ++++ src/cmd/6l/obj.c | 1 + src/cmd/8c/swt.c | 4 ++++ src/cmd/8l/obj.c | 1 + src/cmd/cc/cc.h | 2 ++ src/cmd/cc/dpchk.c | 17 +++++++++++++++ src/cmd/cc/lexbody | 7 ++++++ src/cmd/cc/macbody | 4 ++++ src/cmd/cgo/out.go | 6 +++++ src/cmd/ld/go.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 12 files changed, 113 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cmd/5c/swt.c b/src/cmd/5c/swt.c index f8fbb1354..dea28cf6f 100644 --- a/src/cmd/5c/swt.c +++ b/src/cmd/5c/swt.c @@ -405,6 +405,10 @@ outcode(void) Bprint(&outbuf, "\n$$ // dynexport\n"); for(i=0; iname, "dynlinker") == 0) { + pragdynlinker(); + return; + } while(getnsc() != '\n') ; return; diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index acd1e0b43..290b37ac5 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -128,6 +128,12 @@ func dynimport(obj string) { } if f, err := elf.Open(obj); err == nil { + if sec := f.Section(".interp"); sec != nil { + if data, err := sec.Data(); err == nil && len(data) > 1 { + // skip trailing \0 in data + fmt.Fprintf(stdout, "#pragma dynlinker %q\n", string(data[:len(data)-1])) + } + } sym, err := f.ImportedSymbols() if err != nil { fatalf("cannot load imported symbols from ELF file %s: %v", obj, err) diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c index 3271be1f5..78f76bf12 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