summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShenghou Ma <minux.ma@gmail.com>2012-05-05 01:54:16 +0800
committerShenghou Ma <minux.ma@gmail.com>2012-05-05 01:54:16 +0800
commita64243770d5a68d5e4aeacfeb3b5d259c75cf734 (patch)
tree333badd98783c6efb64dbefae2d7d2904f704a3f
parentb3e5edd1c0ecb3109b67d305377557d74d33a8ad (diff)
downloadgo-a64243770d5a68d5e4aeacfeb3b5d259c75cf734.tar.gz
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
-rw-r--r--src/cmd/5c/swt.c4
-rw-r--r--src/cmd/5l/obj.c1
-rw-r--r--src/cmd/6c/swt.c4
-rw-r--r--src/cmd/6l/obj.c1
-rw-r--r--src/cmd/8c/swt.c4
-rw-r--r--src/cmd/8l/obj.c1
-rw-r--r--src/cmd/cc/cc.h2
-rw-r--r--src/cmd/cc/dpchk.c17
-rw-r--r--src/cmd/cc/lexbody7
-rw-r--r--src/cmd/cc/macbody4
-rw-r--r--src/cmd/cgo/out.go6
-rw-r--r--src/cmd/ld/go.c64
12 files changed, 113 insertions, 2 deletions
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; i<ndynexp; i++)
Bprint(&outbuf, "dynexport %s %s\n", dynexp[i].local, dynexp[i].remote);
+ Bprint(&outbuf, "\n$$ // dynlinker\n");
+ if(dynlinker != nil) {
+ Bprint(&outbuf, "dynlinker %s\n", dynlinker);
+ }
Bprint(&outbuf, "\n$$\n\n");
}
Bprint(&outbuf, "!\n");
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index 7dc5b899b..b57ef6edf 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -106,6 +106,7 @@ main(int argc, char *argv[])
INITENTRY = EARGF(usage());
break;
case 'I':
+ debug['I'] = 1; // denote cmdline interpreter override
interpreter = EARGF(usage());
break;
case 'L':
diff --git a/src/cmd/6c/swt.c b/src/cmd/6c/swt.c
index 272cce259..2c5b3e604 100644
--- a/src/cmd/6c/swt.c
+++ b/src/cmd/6c/swt.c
@@ -259,6 +259,10 @@ outcode(void)
Bprint(&b, "\n$$ // dynexport\n");
for(i=0; i<ndynexp; i++)
Bprint(&b, "dynexport %s %s\n", dynexp[i].local, dynexp[i].remote);
+ Bprint(&b, "\n$$ // dynlinker\n");
+ if(dynlinker != nil) {
+ Bprint(&b, "dynlinker %s\n", dynlinker);
+ }
Bprint(&b, "\n$$\n\n");
}
Bprint(&b, "!\n");
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index 692cab7b8..64d173084 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -114,6 +114,7 @@ main(int argc, char *argv[])
HEADTYPE = headtype(EARGF(usage()));
break;
case 'I':
+ debug['I'] = 1; // denote cmdline interpreter override
interpreter = EARGF(usage());
break;
case 'L':
diff --git a/src/cmd/8c/swt.c b/src/cmd/8c/swt.c
index 5a6f22e0b..18611ea1e 100644
--- a/src/cmd/8c/swt.c
+++ b/src/cmd/8c/swt.c
@@ -263,6 +263,10 @@ outcode(void)
Bprint(&b, "\n$$ // dynexport\n");
for(i=0; i<ndynexp; i++)
Bprint(&b, "dynexport %s %s\n", dynexp[i].local, dynexp[i].remote);
+ Bprint(&b, "\n$$ // dynlinker\n");
+ if(dynlinker != nil) {
+ Bprint(&b, "dynlinker %s\n", dynlinker);
+ }
Bprint(&b, "\n$$\n\n");
}
Bprint(&b, "!\n");
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index af4bc844f..823d0a22d 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -119,6 +119,7 @@ main(int argc, char *argv[])
HEADTYPE = headtype(EARGF(usage()));
break;
case 'I':
+ debug['I'] = 1; // denote cmdline interpreter override
interpreter = EARGF(usage());
break;
case 'L':
diff --git a/src/cmd/cc/cc.h b/src/cmd/cc/cc.h
index 2ee03ae1f..3a0147e9f 100644
--- a/src/cmd/cc/cc.h
+++ b/src/cmd/cc/cc.h
@@ -774,6 +774,8 @@ void pragtextflag(void);
void pragincomplete(void);
void pragdynimport(void);
void pragdynexport(void);
+void pragdynlinker(void);
+EXTERN char *dynlinker;
/*
* calls to machine depend part
diff --git a/src/cmd/cc/dpchk.c b/src/cmd/cc/dpchk.c
index c579e20d9..ea2e81dee 100644
--- a/src/cmd/cc/dpchk.c
+++ b/src/cmd/cc/dpchk.c
@@ -725,3 +725,20 @@ out:
while(getnsc() != '\n')
;
}
+
+void
+pragdynlinker(void)
+{
+ dynlinker = getquoted();
+ if(dynlinker == nil)
+ goto err;
+
+ goto out;
+
+err:
+ yyerror("usage: #pragma dynlinker \"path\"");
+
+out:
+ while(getnsc() != '\n')
+ ;
+}
diff --git a/src/cmd/cc/lexbody b/src/cmd/cc/lexbody
index d339cf9a2..51d2e9396 100644
--- a/src/cmd/cc/lexbody
+++ b/src/cmd/cc/lexbody
@@ -61,6 +61,13 @@ pragdynexport(void)
}
void
+pragdynlinker(void)
+{
+ while(getnsc() != '\n')
+ ;
+}
+
+void
pragfpround(void)
{
while(getnsc() != '\n')
diff --git a/src/cmd/cc/macbody b/src/cmd/cc/macbody
index 874e82d25..e9b4ba9fb 100644
--- a/src/cmd/cc/macbody
+++ b/src/cmd/cc/macbody
@@ -751,6 +751,10 @@ macprag(void)
pragdynexport();
return;
}
+ if(s && strcmp(s->name, "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<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