Hello,
the attached program changes the output from "true" to "false" when the -Bsymbolic / -Bsymbolic-functions options are passed to GCC. This happens on ARM -- on x86-64 output is always "true".
The program involves a comparison, within a shared library, of a PMF defined inside the shared library itself with the same PMF passed by the application.
At this stage I still don't know if it's a GCC problem, a ld.so problem, ABI constraints, undefined behaviour, or whatnot; but any help is appreciated.
Compile with:
g++ -fPIC -shared -Wall -o libshared.so -Wl,-Bsymbolic shared.cpp g++ -fPIE -Wall -o main main.cpp -L. -lshared
(The long story is that Qt 5 is taking PMFs in its public API, and the comparison failing inside of Qt shared libraries is breaking code on ARM, as -Bsymbolic is set by default there.)
Thanks,
On 10 January 2014 08:32, Giuseppe D'Angelo giuseppe.dangelo@kdab.com wrote:
Hi Guiseppe,
the attached program changes the output from "true" to "false" when the -Bsymbolic / -Bsymbolic-functions options are passed to GCC. This happens on ARM -- on x86-64 output is always "true".
The program involves a comparison, within a shared library, of a PMF defined inside the shared library itself with the same PMF passed by the application.
At this stage I still don't know if it's a GCC problem, a ld.so problem, ABI constraints, undefined behaviour, or whatnot; but any help is appreciated.
Compile with:
g++ -fPIC -shared -Wall -o libshared.so -Wl,-Bsymbolic shared.cpp g++ -fPIE -Wall -o main main.cpp -L. -lshared
(The long story is that Qt 5 is taking PMFs in its public API, and the comparison failing inside of Qt shared libraries is breaking code on ARM, as -Bsymbolic is set by default there.)
Thanks for the report and testcase.
The attached patch to ld may help. I am not yet sure whether or not it is the correct approach but if it works for you that would be interesting.
Hello Will,
Il 10/01/2014 15:50, Will Newton ha scritto:
The attached patch to ld may help. I am not yet sure whether or not it is the correct approach but if it works for you that would be interesting.
thank you very much for the patch, I'll test it and report back to you shortly.
In the meanwhile, I've found that if I add "-pie" (together with -fPIE) when building the final executable, the testcase works. Again, I don't quite know what's changing. But that might be a workaround (instead of dropping -Bsymbolic or start using --dynamic-list).
Thanks,
Hello Will,
Il 10/01/2014 15:50, Will Newton ha scritto:
Thanks for the report and testcase.
The attached patch to ld may help. I am not yet sure whether or not it is the correct approach but if it works for you that would be interesting.
Thanks again for the patch. The C++ testcase indeed works when your patch is applied to binutils! (I've tested it with binutils 2.22-8 in Debian Wheezy). I'm going to try with a Qt testcase ASAP.
By the way, do you mind explaining a bit what the patch does, or just why do you think this is a binutils bug? In Qt we're considering turning -Bsymbolic off on all architectures but x86/x86-64 (to avoid this issue) [1], but we could keep ARM and disable -Bsymbolic only on "older" binutils (if your patch gets merged).
[1] https://bugreports.qt-project.org/browse/QTBUG-36129
Thanks,
On 16 January 2014 10:04, Giuseppe D'Angelo giuseppe.dangelo@kdab.com wrote:
Hello Will,
Il 10/01/2014 15:50, Will Newton ha scritto:
Thanks for the report and testcase.
The attached patch to ld may help. I am not yet sure whether or not it is the correct approach but if it works for you that would be interesting.
Thanks again for the patch. The C++ testcase indeed works when your patch is applied to binutils! (I've tested it with binutils 2.22-8 in Debian Wheezy). I'm going to try with a Qt testcase ASAP.
By the way, do you mind explaining a bit what the patch does, or just why do you think this is a binutils bug? In Qt we're considering turning -Bsymbolic off on all architectures but x86/x86-64 (to avoid this issue) [1], but we could keep ARM and disable -Bsymbolic only on "older" binutils (if your patch gets merged).
I'm not entirely sure what it does. ;-)
At the moment ARM ld sets the st_value for a function symbol if it is a non-weak reference to the address of the PLT entry for that symbol (you can see this in the symbol table of the binary if you dump it with objdump -T). This means that as far as the executable is concerned the address of that function is the PLT entry, and when it passes the address to the shared library code the shared library compares it against it's own notion of the address which is the actual code address of the function in the shared library which is different - mis-compare, failure.
x86 works a bit differently, and only sets st_value to non-zero if !pointer_equality_needed for that symbol. This is where things start to get a bit hazy for me. I guess the current behaviour is useful for someone, but I am not sure what would potentially break by changing it. I'll raise the issue on the binutils list and see if there is anyone who can explain that.
That said, the fact that pointer equality using -Bsymbolic is reliant on these kinds of grungy linker internals suggests to me that it may not be a 100% reliable thing to use. Have you tried using the gold linker on x86 to see if that works? (I'm not sure if gold on ARM will work at all these days).
I'm going to try with a Qt testcase ASAP.
And indeed it works there.
Il 16/01/2014 11:23, Will Newton ha scritto:
That said, the fact that pointer equality using -Bsymbolic is reliant on these kinds of grungy linker internals suggests to me that it may not be a 100% reliable thing to use. Have you tried using the gold linker on x86 to see if that works? (I'm not sure if gold on ARM will work at all these days).
Even with gold (on x86) everything looks fine. But I guess this is not a proof of "it works", as the bug itself seems very tricky to reproduce (usually everything "just works" even on ARM; that's why we encountered the issue only these days...).
Thanks,
Hello,
Il 16/01/2014 11:23, Will Newton ha scritto:
x86 works a bit differently, and only sets st_value to non-zero if !pointer_equality_needed for that symbol. This is where things start to get a bit hazy for me. I guess the current behaviour is useful for someone, but I am not sure what would potentially break by changing it. I'll raise the issue on the binutils list and see if there is anyone who can explain that.
just FYI, I opened a bug report on binutils to keep track of the issue.
In Qt we'll probably drop -Bsymbolic from anything but x86/x86-64 to work around it for the time being, as we started getting reports of the same issue for PPC as well.
Thanks,
linaro-toolchain@lists.linaro.org