aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2011-02-24 16:45:45 -0500
committerRuss Cox <rsc@golang.org>2011-02-24 16:45:45 -0500
commitd94bf76239441a5a819043db37bde28f22e20621 (patch)
treec3ac8b5c6332e97a9c6a457d669377aab8247881
parent4185a9e2b28f7ae29743f702d3b35fbc7edaebc6 (diff)
downloadgo-d94bf76239441a5a819043db37bde28f22e20621.tar.gz
go-d94bf76239441a5a819043db37bde28f22e20621.zip
ld: weak symbols
A reference to the address of weak.foo resolves at link time to the address of the symbol foo if foo would end up in the binary anyway, or to zero if foo would not be in the binary. For example: int xxx = 1; int yyy = 2; int weak·xxx; int weak·yyy; void main·main(void) { runtime·printf("%p %p %p\n", &xxx, &weak·xxx, &weak·yyy); } prints the same non-nil address twice, then 0 (because yyy is not referenced so it was dropped from the binary). This will be used by the reflection tables. R=iant CC=golang-dev https://golang.org/cl/4223044
-rw-r--r--src/cmd/5l/obj.c1
-rw-r--r--src/cmd/5l/pass.c12
-rw-r--r--src/cmd/6l/obj.c1
-rw-r--r--src/cmd/6l/pass.c12
-rw-r--r--src/cmd/8l/obj.c1
-rw-r--r--src/cmd/8l/pass.c12
-rw-r--r--src/cmd/ld/go.c31
-rw-r--r--src/cmd/ld/lib.c12
-rw-r--r--src/cmd/ld/lib.h2
9 files changed, 48 insertions, 36 deletions
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index c929b3291e..f252f9fc56 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -280,6 +280,7 @@ main(int argc, char *argv[])
symtab();
dodata();
address();
+ doweak();
reloc();
asmb();
undef();
diff --git a/src/cmd/5l/pass.c b/src/cmd/5l/pass.c
index e16b34171b..7e1ba6a09a 100644
--- a/src/cmd/5l/pass.c
+++ b/src/cmd/5l/pass.c
@@ -35,18 +35,6 @@
static void xfol(Prog*, Prog**);
-void
-undef(void)
-{
- int i;
- Sym *s;
-
- for(i=0; i<NHASH; i++)
- for(s = hash[i]; s != S; s = s->hash)
- if(s->type == SXREF)
- diag("%s: not defined", s->name);
-}
-
Prog*
brchain(Prog *p)
{
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index 8d602b649f..f113e3ec1e 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -267,6 +267,7 @@ main(int argc, char *argv[])
symtab();
dodata();
address();
+ doweak();
reloc();
asmb();
undef();
diff --git a/src/cmd/6l/pass.c b/src/cmd/6l/pass.c
index 98a32a7624..8fda943923 100644
--- a/src/cmd/6l/pass.c
+++ b/src/cmd/6l/pass.c
@@ -718,15 +718,3 @@ atolwhex(char *s)
n = -n;
return n;
}
-
-void
-undef(void)
-{
- int i;
- Sym *s;
-
- for(i=0; i<NHASH; i++)
- for(s = hash[i]; s != S; s = s->hash)
- if(s->type == SXREF)
- diag("%s: not defined", s->name);
-}
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index 791ba1e525..d505dc10e5 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -316,6 +316,7 @@ main(int argc, char *argv[])
symtab();
dodata();
address();
+ doweak();
reloc();
asmb();
undef();
diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c
index bbb86cff7d..294926f293 100644
--- a/src/cmd/8l/pass.c
+++ b/src/cmd/8l/pass.c
@@ -666,15 +666,3 @@ atolwhex(char *s)
n = -n;
return n;
}
-
-void
-undef(void)
-{
- int i;
- Sym *s;
-
- for(i=0; i<NHASH; i++)
- for(s = hash[i]; s != S; s = s->hash)
- if(s->type == SXREF)
- diag("%s(%d): not defined", s->name, s->version);
-}
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c
index 2c6a6d084b..2f5d31e515 100644
--- a/src/cmd/ld/go.c
+++ b/src/cmd/ld/go.c
@@ -550,6 +550,8 @@ mark(Sym *s)
if(s == S || s->reachable)
return;
+ if(strncmp(s->name, "weak.", 5) == 0)
+ return;
s->reachable = 1;
if(s->text)
marktext(s);
@@ -654,6 +656,35 @@ deadcode(void)
textp = nil;
else
last->next = nil;
+
+ for(i=0; i<NHASH; i++)
+ for(s = hash[i]; s != S; s = s->hash)
+ if(strncmp(s->name, "weak.", 5) == 0) {
+ s->special = 1; // do not lay out in data segment
+ s->reachable = 1;
+ }
+}
+
+void
+doweak(void)
+{
+ int i;
+ Sym *s, *t;
+
+ // resolve weak references only if
+ // target symbol will be in binary anyway.
+ for(i=0; i<NHASH; i++)
+ for(s = hash[i]; s != S; s = s->hash) {
+ if(strncmp(s->name, "weak.", 5) == 0) {
+ t = lookup(s->name+5, s->version);
+ if(t->type != 0 && t->reachable) {
+ s->value = t->value;
+ s->type = t->type;
+ } else
+ s->value = 0;
+ continue;
+ }
+ }
}
void
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index 39593085d4..e645502b33 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -1279,3 +1279,15 @@ headtype(char *name)
errorexit();
return -1; // not reached
}
+
+void
+undef(void)
+{
+ int i;
+ Sym *s;
+
+ for(i=0; i<NHASH; i++)
+ for(s = hash[i]; s != S; s = s->hash)
+ if(s->type == SXREF)
+ diag("%s(%d): not defined", s->name, s->version);
+}
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index 7df348353c..adde2c9ff2 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -167,6 +167,8 @@ int archreloc(Reloc*, Sym*, vlong*);
void adddynsym(Sym*);
void addexport(void);
void dostkcheck(void);
+void undef(void);
+void doweak(void);
int pathchar(void);
void* mal(uint32);