Discussion:
bfd/objcopy handling of localizing common symbols
Jordan Rupprecht via binutils
2018-10-27 00:19:40 UTC
Permalink
It's me again, with some more archaeology questions about libbfd :)

I'm looking at a project that uses objcopy --localize-hidden,
dynamorio: https://chromium.googlesource.com/external/dynamorio/+/master/core/CMakeLists.txt#541
It turns out that objcopy is not actually localizing all the hidden
symbols; most noticeably, common symbols are not being localized. This
works for them, but when dropping in llvm-objcopy (which always
localizes), it breaks. tl;dr: is this expected?

For example, a common symbol:
$ echo 'int foo;' | gcc -xc - -c -o /tmp/common.o; nm /tmp/common.o;
objdump -t /tmp/common.o | grep foo; objcopy --localize-symbol foo
/tmp/common.o; nm /tmp/common.o; objdump -t /tmp/common.o | grep foo
0000000000000004 C foo
0000000000000004 O *COM* 0000000000000004 foo
0000000000000004 C foo
0000000000000004 O *COM* 0000000000000004 foo

objdump actually reports it as neither a global nor a local symbol.

Compared to a non-common symbol:
$ echo 'int foo=0;' | gcc -xc - -c -o /tmp/common.o; nm /tmp/common.o;
objdump -t /tmp/common.o | grep foo; objcopy --localize-symbol foo
/tmp/common.o; nm /tmp/common.o;
objdump -t /tmp/common.o | grep foo
0000000000000000 B foo
0000000000000000 g O .bss 0000000000000004 foo
0000000000000000 b foo
0000000000000000 l O .bss 0000000000000004 foo
As expected, foo goes from global to local.

I noticed the same thing with hidden symbols, e.g. the dynamorio
example above, which compiles with -fvisibility=hidden and then runs
objcopy --localize-hidden.

I dug into the source a bit, and it turns out the flags for a global,
common symbol does not include BSF_GLOBAL because of this line:
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=bfd/elfcode.h;h=f224c8b79d2fb0516a90c1a8ad818d11a1a971a5;hb=HEAD#l1298
Which then causes the "flags & (BSF_GLOBAL | BSF_WEAK)" check to fail
here: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=binutils/objcopy.c;h=1d29059b8df90eebab2dc9ec99ff1796f7ff2a3b;hb=HEAD#l1637

I think I've connected the dots on why this is happening, but what I
couldn't figure out from the code or commit history is whether any of
this is intentional or desired. Does anyone know if this is expected?

(For completeness, I filed the bug against llvm-objcopy here:
https://bugs.llvm.org/show_bug.cgi?id=39461)

Thanks -- Jordan
Alan Modra
2018-10-29 11:43:55 UTC
Permalink
Post by Jordan Rupprecht via binutils
objdump actually reports it as neither a global nor a local symbol.
The patch responsible for not setting BSF_GLOBAL on ELF common symbols
is git commit 42cf6d7950e. I don't know why this was done but it
certainly didn't happen by accident.

Other places in objcopy.c that want to handle common symbols select
them with bfd_is_com_section (bfd_get_section (sym)).
--
Alan Modra
Australia Development Lab, IBM
Loading...