Jordan Rupprecht via binutils
2018-10-27 00:19:40 UTC
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
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