This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
LOCAL symbols discarded at link time
- From: Mark Hills <mark dot hills at framestore dot com>
- To: binutils at sourceware dot org
- Date: Wed, 2 Mar 2016 16:34:59 +0000 (GMT)
- Subject: LOCAL symbols discarded at link time
- Authentication-results: sourceware.org; auth=none
I'm am experiencing interactions at link time, despite "LOCAL" symbols and
applying careful use of 'visibility':
`_ZN3Bad15this_will_clashEi' referenced in section `.text' of banana.o: defined in discarded section `.text._ZN3Bad15this_will_clashEi[_ZN3Bad15this_will_clashEi]' of banana.o
This is from a minimal test case (below)
* C++ class member function "this_will_clash": breaks the final link
* C++ function "this_is_fine": links and is called correctly
After compilation with -fvisibility=hidden, the results are as I expected
(including the WEAK on the member function for "vague C++ linkage")
10: 0000000000000000 11 FUNC WEAK HIDDEN 6 _ZN3Bad15this_will_clashE
11: 0000000000000000 7 FUNC GLOBAL HIDDEN 2 _Z12this_is_finev
12: 0000000000000007 28 FUNC GLOBAL DEFAULT 2 apple1
After the partial linking step with localize-hidden, the new .o file:
12: 0000000000000000 11 FUNC LOCAL HIDDEN 4 _ZN3Bad15this_will_clashE
13: 0000000000000000 7 FUNC LOCAL HIDDEN 2 _Z12this_is_finev
14: 0000000000000007 28 FUNC GLOBAL DEFAULT 2 apple1
Now, "apple1" is the exported symbol. To my untrained eye the others are
now the same.
But on linking this file, the second occurance of "this_will_clash" is
being discarded.
- Why the difference in behaviour for the two symbols? More likely my
understanding is not correct, but otherwise could this be a linker bug?
- And how can I get the "this_is_fine" case where C++ classes and
templates are used?
Background info: this is for a large project, where the requirements are:
- stable C ABI between 'apple' and 'banana'
- each module self-contained to avoid crosstalk between 3rd party code
contained within (eg. different versions of the same code)
Many thanks
--
Mark
g++ -o main main.o apple.o banana.o
`_ZN3Bad15this_will_clashEv' referenced in section `.text' of banana.o: defined in discarded section `.text._ZN3Bad15this_will_clashEv[_ZN3Bad15this_will_clashEv]' of banana.o
$ readelf -s apple.o
Symbol table '.symtab' contains 18 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 SECTION LOCAL DEFAULT 1
2: 0000000000000000 0 SECTION LOCAL DEFAULT 2
3: 0000000000000000 0 SECTION LOCAL DEFAULT 4
4: 0000000000000000 0 SECTION LOCAL DEFAULT 6
5: 0000000000000000 0 SECTION LOCAL DEFAULT 7
6: 0000000000000000 0 SECTION LOCAL DEFAULT 9
7: 0000000000000000 0 SECTION LOCAL DEFAULT 10
8: 0000000000000000 0 SECTION LOCAL DEFAULT 11
9: 0000000000000000 0 SECTION LOCAL DEFAULT 12
10: 0000000000000000 0 FILE LOCAL DEFAULT ABS apple1.cc
11: 0000000000000000 0 FILE LOCAL DEFAULT ABS apple2.cc
12: 000000000000002f 7 FUNC LOCAL HIDDEN 2 _Z6apple2v
13: 0000000000000000 27 FUNC LOCAL HIDDEN 4 _ZN3Bad15this_will_clashE
14: 0000000000000000 19 FUNC LOCAL HIDDEN 2 _Z12this_is_finev
15: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts
16: 0000000000000013 28 FUNC GLOBAL DEFAULT 2 apple1
17: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _GLOBAL_OFFSET_TABLE_
$ readelf -s banana.o
Symbol table '.symtab' contains 18 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 SECTION LOCAL DEFAULT 1
2: 0000000000000000 0 SECTION LOCAL DEFAULT 2
3: 0000000000000000 0 SECTION LOCAL DEFAULT 4
4: 0000000000000000 0 SECTION LOCAL DEFAULT 6
5: 0000000000000000 0 SECTION LOCAL DEFAULT 7
6: 0000000000000000 0 SECTION LOCAL DEFAULT 9
7: 0000000000000000 0 SECTION LOCAL DEFAULT 10
8: 0000000000000000 0 SECTION LOCAL DEFAULT 11
9: 0000000000000000 0 SECTION LOCAL DEFAULT 12
10: 0000000000000000 0 FILE LOCAL DEFAULT ABS banana1.cc
11: 0000000000000000 0 FILE LOCAL DEFAULT ABS banana2.cc
12: 000000000000002f 7 FUNC LOCAL HIDDEN 2 _Z7banana2v
13: 0000000000000000 27 FUNC LOCAL HIDDEN 4 _ZN3Bad15this_will_clashE
14: 0000000000000000 19 FUNC LOCAL HIDDEN 2 _Z12this_is_finev
15: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts
16: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _GLOBAL_OFFSET_TABLE_
17: 0000000000000013 28 FUNC GLOBAL DEFAULT 2 banana1
$ g++ --version
g++ (GCC) 5.3.0
$ ld --version
GNU ld (GNU Binutils) 2.25.1
==> Makefile <==
%.o: %.cc
g++ -std=c++11 -c -o $@ $^ -fvisibility=hidden -Wall -fPIC
main: main.o apple.o banana.o
g++ -o $@ $^
apple.o: apple1.o apple2.o
ld -r -o $@ $^
objcopy --localize-hidden $@
banana.o: banana1.o banana2.o
ld -r -o $@ $^
objcopy --localize-hidden $@
==> main.cc <==
extern "C" {
void apple1(void);
void banana1(void);
}
int main(int argc, char *argv[])
{
apple1();
banana1();
}
==> apple1.cc <==
#include <stdio.h>
class Bad
{
public:
void this_will_clash() {
puts("apple will clash");
}
};
void this_is_fine(void)
{
puts("apple is fine");
}
extern "C" __attribute__((visibility("default"))) void apple1(void)
{
Bad b;
b.this_will_clash();
this_is_fine();
}
==> apple2.cc <==
void apple2(void)
{
}
==> banana1.cc <==
#include <stdio.h>
class Bad
{
public:
void this_will_clash() {
puts("banana will clash");
}
};
void this_is_fine(void)
{
puts("banana is fine");
}
extern "C" __attribute__((visibility("default"))) void banana1(void)
{
Bad b;
b.this_will_clash();
this_is_fine();
}
==> banana2.cc <==
void banana2(void)
{
}