aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/ld
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2013-03-01 00:27:57 -0500
committerRuss Cox <rsc@golang.org>2013-03-01 00:27:57 -0500
commit7556ccc7b1763d94b64b04fd7d1ada368397e647 (patch)
tree3b29f06d9933d8e8f450f69fe6f93495aa369176 /src/cmd/ld
parent94955f9b4076aafd54fc756b9d11065e2bba5b05 (diff)
downloadgo-7556ccc7b1763d94b64b04fd7d1ada368397e647.tar.xz
cmd/cgo, cmd/ld: new cgo object file section
Switch to new pragma names, but leave old ones available for now. Merge the three cgo-related sections in the .6 files into a single cgo section. R=golang-dev, iant, ality CC=golang-dev https://golang.org/cl/7424048
Diffstat (limited to 'src/cmd/ld')
-rw-r--r--src/cmd/ld/go.c285
-rw-r--r--src/cmd/ld/lib.h1
-rw-r--r--src/cmd/ld/symtab.c9
3 files changed, 112 insertions, 183 deletions
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c
index c5b9aa5384..b2527b13ef 100644
--- a/src/cmd/ld/go.c
+++ b/src/cmd/ld/go.c
@@ -67,9 +67,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 void loadcgo(char*, char*, char*, int);
static int parsemethod(char**, char*, char**);
static int parsepkgdata(char*, char*, char**, char*, char**, char**, char**);
@@ -178,12 +176,12 @@ ldpkg(Biobuf *f, char *pkg, int64 len, char *filename, int whence)
loadpkgdata(filename, pkg, p0, p1 - p0);
- // look for dynimport section
- p0 = strstr(p1, "\n$$ // dynimport");
+ // look for cgo section
+ p0 = strstr(p1, "\n$$ // cgo");
if(p0 != nil) {
p0 = strchr(p0+1, '\n');
if(p0 == nil) {
- fprint(2, "%s: found $$ // dynimport but no newline in %s\n", argv0, filename);
+ fprint(2, "%s: found $$ // cgo but no newline in %s\n", argv0, filename);
if(debug['u'])
errorexit();
return;
@@ -192,55 +190,12 @@ 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 // dynimport section in %s\n", argv0, filename);
+ fprint(2, "%s: cannot find end of // cgo section in %s\n", argv0, filename);
if(debug['u'])
errorexit();
return;
}
- loaddynimport(filename, pkg, p0 + 1, p1 - (p0+1));
- }
-
- // look for dynexp section
- p0 = strstr(p1, "\n$$ // dynexport");
- if(p0 != nil) {
- p0 = strchr(p0+1, '\n');
- if(p0 == nil) {
- fprint(2, "%s: found $$ // dynexport 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 // 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));
+ loadcgo(filename, pkg, p0 + 1, p1 - (p0+1));
}
}
@@ -456,165 +411,129 @@ useline:
}
static void
-loaddynimport(char *file, char *pkg, char *p, int n)
+loadcgo(char *file, char *pkg, char *p, int n)
{
- char *pend, *next, *name, *def, *p0, *lib, *q;
+ char *pend, *next, *p0, *q;
+ char *f[10], *local, *remote, *lib;
+ int nf;
Sym *s;
USED(file);
pend = p + n;
+ p0 = nil;
for(; p<pend; p=next) {
next = strchr(p, '\n');
if(next == nil)
next = "";
else
*next++ = '\0';
- p0 = p;
- if(strncmp(p, "dynimport ", 10) != 0)
- goto err;
- p += 10;
- name = p;
- p = strchr(name, ' ');
- if(p == nil)
- goto err;
- while(*p == ' ')
- p++;
- def = p;
- p = strchr(def, ' ');
- if(p == nil)
- goto err;
- while(*p == ' ')
- p++;
- lib = p;
- // successful parse: now can edit the line
- *strchr(name, ' ') = 0;
- *strchr(def, ' ') = 0;
+ free(p0);
+ p0 = strdup(p); // save for error message
+ nf = tokenize(p, f, nelem(f));
- if(debug['d']) {
- fprint(2, "%s: %s: cannot use dynamic imports with -d flag\n", argv0, file);
- nerrors++;
- return;
+ if(strcmp(f[0], "cgo_import_dynamic") == 0) {
+ if(nf < 2 || nf > 4)
+ goto err;
+
+ local = f[1];
+ remote = local;
+ if(nf > 2)
+ remote = f[2];
+ lib = "";
+ if(nf > 3)
+ lib = f[3];
+
+ if(debug['d']) {
+ fprint(2, "%s: %s: cannot use dynamic imports with -d flag\n", argv0, file);
+ nerrors++;
+ return;
+ }
+
+ if(strcmp(local, "_") == 0 && strcmp(remote, "_") == 0) {
+ // allow #pragma dynimport _ _ "foo.so"
+ // to force a link of foo.so.
+ havedynamic = 1;
+ adddynlib(lib);
+ continue;
+ }
+
+ local = expandpkg(local, pkg);
+ q = strchr(remote, '#');
+ if(q)
+ *q++ = '\0';
+ s = lookup(local, 0);
+ if(local != f[1])
+ free(local);
+ if(s->type == 0 || s->type == SXREF) {
+ s->dynimplib = lib;
+ s->dynimpname = remote;
+ s->dynimpvers = q;
+ s->type = SDYNIMPORT;
+ havedynamic = 1;
+ }
+ continue;
}
- if(strcmp(name, "_") == 0 && strcmp(def, "_") == 0) {
- // allow #pragma dynimport _ _ "foo.so"
- // to force a link of foo.so.
- havedynamic = 1;
- adddynlib(lib);
+ if(strcmp(f[0], "cgo_import_static") == 0) {
+ if(nf != 2)
+ goto err;
+ if(isobj) {
+ local = f[1];
+ s = lookup(local, 0);
+ s->type = SHOSTOBJ;
+ s->size = 0;
+ }
continue;
}
- name = expandpkg(name, pkg);
- q = strchr(def, '#');
- if(q)
- *q++ = '\0';
- s = lookup(name, 0);
- free(name);
- if(s->type == 0 || s->type == SXREF) {
- s->dynimplib = lib;
- s->dynimpname = def;
- s->dynimpvers = q;
- s->type = SDYNIMPORT;
- havedynamic = 1;
- }
- }
- return;
-
-err:
- fprint(2, "%s: %s: invalid dynimport line: %s\n", argv0, file, p0);
- nerrors++;
-}
-
-static void
-loaddynexport(char *file, char *pkg, char *p, int n)
-{
- char *pend, *next, *local, *elocal, *remote, *p0;
- Sym *s;
-
- 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, "dynexport ", 10) != 0)
- goto err;
- p += 10;
- local = p;
- p = strchr(local, ' ');
- if(p == nil)
- goto err;
- while(*p == ' ')
- p++;
- remote = p;
-
- // successful parse: now can edit the line
- *strchr(local, ' ') = 0;
+ if(strcmp(f[0], "cgo_export") == 0) {
+ if(nf < 2 || nf > 3)
+ goto err;
+ local = f[1];
+ if(nf > 2)
+ remote = f[2];
+ else
+ remote = local;
+ local = expandpkg(local, pkg);
+ s = lookup(local, 0);
+ if(s->dynimplib != nil) {
+ fprint(2, "%s: symbol is both imported and exported: %s\n", argv0, local);
+ nerrors++;
+ }
+ s->dynimpname = remote;
+ s->dynexport = 1;
- elocal = expandpkg(local, pkg);
+ if(ndynexp%32 == 0)
+ dynexp = realloc(dynexp, (ndynexp+32)*sizeof dynexp[0]);
+ dynexp[ndynexp++] = s;
- s = lookup(elocal, 0);
- if(s->dynimplib != nil) {
- fprint(2, "%s: symbol is both dynimport and dynexport %s\n", argv0, local);
- nerrors++;
+ if(local != f[1])
+ free(local);
+ continue;
}
- s->dynimpname = remote;
- s->dynexport = 1;
-
- if(ndynexp%32 == 0)
- dynexp = realloc(dynexp, (ndynexp+32)*sizeof dynexp[0]);
- dynexp[ndynexp++] = s;
-
- if (elocal != local)
- free(elocal);
- }
- return;
-
-err:
- fprint(2, "%s: invalid dynexport line: %s\n", argv0, p0);
- nerrors++;
-}
-
-static void
-loaddynlinker(char *file, char *pkg, char *p, int n)
-{
- char *pend, *next, *dynlinker, *p0;
-
- USED(file);
- USED(pkg);
- 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;
+
+ if(strcmp(f[0], "cgo_dynamic_linker") == 0) {
+ if(nf != 2)
+ goto err;
+
+ if(!debug['I']) { // not overridden by command line
+ if(interpreter != nil && strcmp(interpreter, f[1]) != 0) {
+ fprint(2, "%s: conflict dynlinker: %s and %s\n", argv0, interpreter, f[1]);
+ nerrors++;
+ return;
+ }
+ free(interpreter);
+ interpreter = strdup(f[1]);
}
- free(interpreter);
- interpreter = strdup(dynlinker);
+ continue;
}
}
+ free(p0);
return;
err:
- fprint(2, "%s: invalid dynlinker line: %s\n", argv0, p0);
+ fprint(2, "%s: %s: invalid dynimport line: %s\n", argv0, file, p0);
nerrors++;
}
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index acfad97751..94ad76eccb 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -63,6 +63,7 @@ enum
SFILE,
SCONST,
SDYNIMPORT,
+ SHOSTOBJ,
SSUB = 1<<8, /* sub-symbol, linked from parent via ->sub list */
SMASK = SSUB - 1,
diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c
index 144f82a3ba..89a594872e 100644
--- a/src/cmd/ld/symtab.c
+++ b/src/cmd/ld/symtab.c
@@ -135,6 +135,8 @@ putelfsym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
void
asmelfsym(void)
{
+ Sym *s;
+
// the first symbol entry is reserved
putelfsyment(0, 0, 0, (STB_LOCAL<<4)|STT_NOTYPE, 0, 0);
@@ -144,6 +146,13 @@ asmelfsym(void)
elfbind = STB_GLOBAL;
elfglobalsymndx = numelfsym;
genasmsym(putelfsym);
+
+ for(s=allsym; s!=S; s=s->allsym) {
+ if(s->type != SHOSTOBJ)
+ continue;
+ putelfsyment(putelfstr(s->name), 0, 0, (STB_GLOBAL<<4)|STT_NOTYPE, 0, 0);
+ s->elfsym = numelfsym++;
+ }
}
static void