Closed GoogleCodeExporter closed 9 years ago
More investigation:
$ cat exception_test.cc
#include <stdio.h>
void TouchR15AndThrow(const char& arg) {
volatile int n __attribute__((aligned(32))) = 0;
asm volatile ("nop" : : : "r15"); // force to save r15 on stack
throw arg;
}
int main() {
register int *a asm ("r15");
fprintf(stderr, "before throw: %p\n", a);
try {
TouchR15AndThrow('c');
} catch (const char&) { }
fprintf(stderr, "after catch: %p\n", a);
return 0;
}
$ ../my_clang++ -O2 exception_test.cc
$ ./a.out
before throw: 0x7fff7a68fa18
after catch: 0xffffffffffffff70
When 32-byte alignment is required for stack variables (ASan does this),
compiler adds instruction that aligns stack pointer before the registers are
saved on a stack. This change is not captured by DWARF. Later, when exception
is raised and we restore the context (and value in registers), we try to read
registers from wrong location in the memory. See also:
$ ../my_clang++ -O2 exception_test.cc -o exception_test.o
$ objdump -d exception_test.o
<...>
0000000000400870 <_Z16TouchR15AndThrowRKc>:
400870: 55 push %rbp
400871: 48 89 e5 mov %rsp,%rbp
400874: 48 81 e4 e0 ff ff ff and $0xffffffffffffffe0,%rsp #align rsp
40087b: 41 57 push %r15 #save r15
<...>
$ readelf --debug-dump=frames exception_test.o
<...>
00000018 0000001c 0000001c FDE cie=00000000 pc=00400870..004008aa
DW_CFA_advance_loc: 1 to 00400871
DW_CFA_def_cfa_offset: 16
DW_CFA_offset: r6 (rbp) at cfa-16
DW_CFA_advance_loc: 3 to 00400874
DW_CFA_def_cfa_register: r6 (rbp)
DW_CFA_advance_loc: 14 to 00400882
DW_CFA_offset: r3 (rbx) at cfa-32
DW_CFA_offset: r15 (r15) at cfa-24 # r15 is supposed to be after r6(rbp).
$ ../my_clang++ -O2 exception_test.cc -S -o -
<...>
_Z16TouchR15AndThrowRKc: # @_Z16TouchR15AndThrowRKc
.Ltmp3:
.cfi_startproc
# BB#0: # %entry
pushq %rbp
.Ltmp4:
.cfi_def_cfa_offset 16
.Ltmp5:
.cfi_offset %rbp, -16
movq %rsp, %rbp
.Ltmp6:
.cfi_def_cfa_register %rbp
andq $-32, %rsp <-- this is not used when calculating cfi_offset for %r15
pushq %r15
pushq %rbx
subq $48, %rsp
.Ltmp7:
.cfi_offset %rbx, -32
.Ltmp8:
.cfi_offset %r15, -24
Original comment by samso...@google.com
on 2 Dec 2011 at 1:43
Filed upstream: http://llvm.org/bugs/show_bug.cgi?id=11468
Original comment by samso...@google.com
on 2 Dec 2011 at 7:36
This is likely fixed in r160248.
Original comment by samso...@google.com
on 30 Jul 2012 at 8:57
Original issue reported on code.google.com by
samso...@google.com
on 23 Nov 2011 at 1:48