This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

LOCAL symbols discarded at link time


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)
{
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]