mirror of
https://github.com/golang/go
synced 2024-11-25 20:07:56 -07:00
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
This commit is contained in:
parent
a29304bfb8
commit
dac4c3eee9
@ -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");
|
||||
|
@ -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':
|
||||
|
@ -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");
|
||||
|
@ -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':
|
||||
|
@ -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");
|
||||
|
@ -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':
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
;
|
||||
}
|
||||
|
@ -60,6 +60,13 @@ pragdynexport(void)
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
pragdynlinker(void)
|
||||
{
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
pragfpround(void)
|
||||
{
|
||||
|
@ -751,6 +751,10 @@ macprag(void)
|
||||
pragdynexport();
|
||||
return;
|
||||
}
|
||||
if(s && strcmp(s->name, "dynlinker") == 0) {
|
||||
pragdynlinker();
|
||||
return;
|
||||
}
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
return;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user