|
From: Jeffrey W. <nol...@gm...> - 2015-10-21 21:40:36
|
Hi Everyone, I have a cross platform project that uses a fair amount on inline assembly. The project is clean under Valgrind, Undefined Behavior sanitizer, Address sanitizer and even Microsoft's Enterprise Analysis and Coverity. However... A few Linux and Apple users report unexpected results and I am having trouble reproducing the issue. I have not been able to duplicate it, even, say on Debian Sid (unstable) with the bleeding edge GCC. Its been tough to narrow down, but it appears to be related to the latest GCC and possibly Clang compilers. I also suspect it might be related to the use of PIC. When PIC is in effect, the Global Offset Table (GOT) is utilized. Under the Linux ABI, that means EBX/RBX must be preserved because it holds the pointer to the GOT. Is it possible to use Valgrind to detect unexpected changes to the GOT pointer when PIC is in effect? Or put another way, is it possible to detect unexpected changes to EBX/RBX? (I know its not an easy request. My apologies for asking). Thanks in Advance. |
|
From: <jr...@bi...> - 2015-10-22 03:25:49
|
> Is it possible to use Valgrind to detect unexpected changes to the GOT > pointer when PIC is in effect? Or put another way, is it possible to detect > unexpected changes to EBX/RBX? There is no builtin feature to do that. But if you are highly motivated then here's how. Add two words to the VEX register state structure for a thread: the expected GOT value for RBX/EBX, and a pointer to a linked list of previous pairs of words. In the VEX code generator, recognize the "set GOT pointer" idiom "CALL [MOV (%RSP),%RBX; RET]; ADDQ $NNNN,RBX" then cons the new value of RBX into the front of the list. Recognize return-from-subroutine "POP %RBX; ...; RET", then check RBX against the expected GOT, and cdr the list. |
|
From: Julian S. <js...@ac...> - 2015-10-22 11:52:34
|
> When PIC is in effect, the Global Offset Table (GOT) is utilized. > Under the Linux ABI, that means EBX/RBX must be preserved because it > holds the pointer to the GOT. If the GOT pointer register is getting trashed by inline assembly, I'd imagine your program would crash very shortly afterwards, in a somewhat obvious way (if you're proficient at reading assembly that is). Also, if the inline asm is wrong, different optimisation levels may well have different effects. Is it -O level dependent? You list a bunch of memory-error checking tools (Memcheck, ASan, etc) but don't say anything about race-checking (Helgrind, DRD, TSan, etc). Did you check for races and other threading problems? J |
|
From: Jeffrey W. <nol...@gm...> - 2015-10-22 12:54:49
|
On Thu, Oct 22, 2015 at 7:52 AM, Julian Seward <js...@ac...> wrote:
>
>> When PIC is in effect, the Global Offset Table (GOT) is utilized.
>> Under the Linux ABI, that means EBX/RBX must be preserved because it
>> holds the pointer to the GOT.
>
> If the GOT pointer register is getting trashed by inline assembly, I'd
> imagine your program would crash very shortly afterwards, in a somewhat
> obvious way (if you're proficient at reading assembly that is).
Yeah, that's what I hoped for. But its showing up as a hang at the
moment. (And I would probably suffer my fair share of reading the
ASM).
No one has provided me with a dump, and no one has provided me with
remote/SSH access to a misbehaving machine. They are not making it
easy :(
I'm trying to go the extra mile because this could be a portent of
things to come at GCC 5.2 or 5.3. I want to get out ahead of this
issue in case it becomes wider spread.
> Also, if the inline asm is wrong, different optimisation levels may well
> have different effects. Is it -O level dependent?
The issue does not appear to be transient based on optimizations. The
folks who are reporting it use -O{1|2|3}.
I know a -DDISABLE_ASM resolves the issue. I don't know what happens
under the configuration {no-PIC, with-ASM}. No one has reported back.
I also know -mno-sse{3|4|4_1|4_2} does not affect the issue.
> You list a bunch of memory-error checking tools (Memcheck, ASan, etc) but
> don't say anything about race-checking (Helgrind, DRD, TSan, etc). Did you
> check for races and other threading problems?
The self tests are single threaded, so I guess I am fortunate that its
not a factor. Thank the {Lord|Allay|<Favorite Deity>} for small
miracles :)
Jeff
|
|
From: Jeffrey W. <nol...@gm...> - 2015-10-27 11:53:24
|
> A few Linux and Apple users report unexpected results and I am having > trouble reproducing the issue. I have not been able to duplicate it, > even, say on Debian Sid (unstable) with the bleeding edge GCC. Its > been tough to narrow down, but it appears to be related to the latest > GCC and possibly Clang compilers. I also suspect it might be related > to the use of PIC. We tracked this down to Debian Sid (unstable) running on real Core2 Duo hardware (I had to dust off an old Dell S1555 laptop). I also needed the Debian maintainer to tar his VM and send it to me. It appears the GCC 5.2.1 compiler was too aggressive with -fdevirtualize for a few functions when the definition of the function is in the header and its inlined. The functions had a call to SecureByteBlock class, which manages an array of bytes and zeroizes it on destruction. The function New does what you would expect - it allocates a new block of memory. It can also be used to reallocate if the new size is larger then when created. GCC was omitting some of the calls to New which grew the array. Jeff |