]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/cgo, cmd/cc, cmd/ld: detect dynamic linker automatically
authorShenghou Ma <minux.ma@gmail.com>
Fri, 4 May 2012 17:54:16 +0000 (01:54 +0800)
committerShenghou Ma <minux.ma@gmail.com>
Fri, 4 May 2012 17:54:16 +0000 (01:54 +0800)
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

12 files changed:
src/cmd/5c/swt.c
src/cmd/5l/obj.c
src/cmd/6c/swt.c
src/cmd/6l/obj.c
src/cmd/8c/swt.c
src/cmd/8l/obj.c
src/cmd/cc/cc.h
src/cmd/cc/dpchk.c
src/cmd/cc/lexbody
src/cmd/cc/macbody
src/cmd/cgo/out.go
src/cmd/ld/go.c

index f8fbb13545c4c6cbb208a12a1d639965b93447dd..dea28cf6fd72c5794bf392dfa71414d2bc0000f9 100644 (file)
@@ -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");
index 7dc5b899b6257fcbea9bdd094ed9b636f76f33a8..b57ef6edfb598f75a85881ae2a014be10a1d6458 100644 (file)
@@ -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':
index 272cce2595bdcd9d2cf61089b85c7a70d14b13a7..2c5b3e604cfdace520b1339d8157f9eeb6aac157 100644 (file)
@@ -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");
index 692cab7b8177edec6f7746e2885904f6c91b0f72..64d1730842daed03dcfc899cacb704debd37e150 100644 (file)
@@ -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':
index 5a6f22e0bab4763b1b7c680c03c64a484870b36b..18611ea1e836b74ce62a50df5828b4fffcc9877f 100644 (file)
@@ -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");
index af4bc844fb2f5c3ff75543b9d546182046917de9..823d0a22dfca53cf8df43bae58c5cd9900beef8b 100644 (file)
@@ -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':
index 2ee03ae1f1290c93c5c889fdf848c77061867e67..3a0147e9fbecbe6a74a79773ce60fbf5a86ecbea 100644 (file)
@@ -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
index c579e20d9805e5818eb676931573968043696935..ea2e81deebd1aa17fad2ea7fccbd4b64dfaed6b9 100644 (file)
@@ -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')
+               ;
+}
index d339cf9a29df2a04ec2bb99adf78a999c3e706eb..51d2e9396a8bf47730c17d7878c28417b2251adf 100644 (file)
@@ -60,6 +60,13 @@ pragdynexport(void)
                ;
 }
 
+void
+pragdynlinker(void)
+{
+       while(getnsc() != '\n')
+               ;
+}
+
 void
 pragfpround(void)
 {
index 874e82d25566a94cf52331678446b5944db429fc..e9b4ba9fb0ee7a2e1326a74a1ffd2f4c64808e80 100644 (file)
@@ -751,6 +751,10 @@ macprag(void)
                pragdynexport();
                return;
        }
+       if(s && strcmp(s->name, "dynlinker") == 0) {
+               pragdynlinker();
+               return;
+       }
        while(getnsc() != '\n')
                ;
        return;
index acd1e0b438c63ea787270e20ea209a5e6133f89b..290b37ac5c0dbb9131aae2f9b40342b95cd4f30b 100644 (file)
@@ -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)
index 3271be1f5970d4dd4b65186f905fbd90c9a60715..78f76bf1216384963c744f40780abfe7bf1e0fed 100644 (file)
@@ -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