* Incorrect unwind when throwing exceptions - possible cause?
@ 2022-02-03 0:43 Juraj Oršulić
2022-02-03 1:06 ` Sam Varshavchik
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Juraj Oršulić @ 2022-02-03 0:43 UTC (permalink / raw)
To: gcc-help
I have a hair-tearing problem with x86_64 gcc 9.3.0 (Ubuntu 20.04),
-O2 and the following "minimal" example
(the real minimal example also links in a bunch of 3rd party libraries
and is a part of a big project, so I can't really provide a minimal example,
but I slimmed it down to basically this):
class Application() {
public:
Application(int argc, char **argv) {}
int process() {
if (argc > 1) { throw std::runtime_error("Exception"); }
// do some processing here
return 0;
}
int main(int argc, char **argv) {
Application app(argc, argv);
int result = 0;
try {
result = app.process();
} catch (const std::exception &e) {
result = 1;
puts(e.what());
}
return result;
}
I get crashes if I throw and there's some more core after the if() in process().
This is an excerpt of how .eh_frame looks like when it works (90% code
in process() commented out):
00014c84 000000000000002c 00000000 CIE
Version: 1
Augmentation: "zPLR"
Code alignment factor: 1
Data alignment factor: -8
Return address column: 16
Augmentation data: 9b 49 4f 3c 00 1b 1b
DW_CFA_def_cfa: r7 (rsp) ofs 8
DW_CFA_offset: r16 (rip) at cfa-8
DW_CFA_def_cfa: r6 (rbp) ofs 16
DW_CFA_offset: r3 (rbx) at cfa-56
DW_CFA_offset: r6 (rbp) at cfa-16
DW_CFA_offset: r12 (r12) at cfa-48
DW_CFA_offset: r13 (r13) at cfa-40
DW_CFA_offset: r14 (r14) at cfa-32
DW_CFA_offset: r15 (r15) at cfa-24
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
00014cb4 0000000000000014 00000034 FDE cie=00014c84
pc=000000000025081e..00000000002508d6
Augmentation data: d4 7e 20 00
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
However, if I put just a bit more stuff inside process() after that
throwing if(), gcc changes the process function prologue a bit
and the unwind table looks like this:
0001ce38 0000000000000034 00013428 FDE cie=00009a14
pc=0000000000252534..0000000000256376
Augmentation data: ab 34 20 00
DW_CFA_def_cfa_expression (DW_OP_breg6 (rbp): -40; DW_OP_deref)
DW_CFA_expression: r3 (rbx) (DW_OP_breg6 (rbp): -48)
DW_CFA_expression: r6 (rbp) (DW_OP_breg6 (rbp): 0)
DW_CFA_expression: r12 (r12) (DW_OP_breg6 (rbp): -32)
DW_CFA_expression: r13 (r13) (DW_OP_breg6 (rbp): -24)
DW_CFA_expression: r14 (r14) (DW_OP_breg6 (rbp): -16)
DW_CFA_expression: r15 (r15) (DW_OP_breg6 (rbp): -8)
So it basically references everything against rbp instead of against
the cfa, great. Here are the libunwind debug prints.
Notice how after processing the expression OP_breg(r6,0x0), thus
calculating the new value for r6 (rbp) by dereferencing itself with
offset zero, the change is reflected in the calculations for subsequent
registers r12-r15 which are wrong.
`apply_reg_state` in libunwind writes the new address for the value of
r6. However, the offsets for r12-r15 are supposed to be calculated
against the inner stack frame's value of rbp (0x7fffffffca70), not against
the new one (0x7fffffffcab0)!
>_ULx86_64_reuse_frame: reuse frame ip=0x5555557a9d46
cfa=0x7fffffff6cc0 format=0 addr=0x0 offset=+0
>_ULx86_64_dwarf_eval_expr: len=3, pushing cfa=0x7fffffff6cc0
>_ULx86_64_dwarf_eval_expr: OP_breg(r6,0xffffffffffffffd8)
>access_mem: mem[00007fffffff6c90] -> 7fffffffca70
>_ULx86_64_dwarf_eval_expr: OP_deref
>_ULx86_64_dwarf_eval_expr: final value = 0x7fffffffca90
>_ULx86_64_dwarf_eval_expr: len=2, pushing cfa=0x7fffffff6cc0
>_ULx86_64_dwarf_eval_expr: OP_breg(r6,0xffffffffffffffd0)
>access_mem: mem[00007fffffff6c90] -> 7fffffffca70
>_ULx86_64_dwarf_eval_expr: final value = 0x7fffffffca40
>_ULx86_64_dwarf_eval_expr: len=2, pushing cfa=0x7fffffff6cc0
>_ULx86_64_dwarf_eval_expr: OP_breg(r6,0x0)
>access_mem: mem[00007fffffff6c90] -> 7fffffffca70
>_ULx86_64_dwarf_eval_expr: final value = 0x7fffffffca70
>_ULx86_64_dwarf_eval_expr: len=2, pushing cfa=0x7fffffff6cc0
>_ULx86_64_dwarf_eval_expr: OP_breg(r6,0xffffffffffffffe0)
>access_mem: mem[00007fffffffca70] -> 7fffffffcab0
>_ULx86_64_dwarf_eval_expr: final value = 0x7fffffffca90
>_ULx86_64_dwarf_eval_expr: len=2, pushing cfa=0x7fffffff6cc0
>_ULx86_64_dwarf_eval_expr: OP_breg(r6,0xffffffffffffffe8)
>access_mem: mem[00007fffffffca70] -> 7fffffffcab0
>_ULx86_64_dwarf_eval_expr: final value = 0x7fffffffca98
>_ULx86_64_dwarf_eval_expr: len=2, pushing cfa=0x7fffffff6cc0
>_ULx86_64_dwarf_eval_expr: OP_breg(r6,0xfffffffffffffff0)
>access_mem: mem[00007fffffffca70] -> 7fffffffcab0
>_ULx86_64_dwarf_eval_expr: final value = 0x7fffffffcaa0
>_ULx86_64_dwarf_eval_expr: len=2, pushing cfa=0x7fffffff6cc0
>_ULx86_64_dwarf_eval_expr: OP_breg(r6,0xfffffffffffffff8)
>access_mem: mem[00007fffffffca70] -> 7fffffffcab0
>_ULx86_64_dwarf_eval_expr: final value = 0x7fffffffcaa8
>access_mem: mem[00007fffffffca88] -> 5555558b67a9
>_ULx86_64_dwarf_step: returning 1
>_ULx86_64_step: returning 1
>_ULx86_64_dwarf_find_proc_info: looking for IP=0x5555558b67a8
>_ULx86_64_dwarf_callback: checking , base=0x555555554000)
>_ULx86_64_dwarf_callback: found table `':
segbase=0x555557215230, len=57926, gp=0x5555576567e8,
table_data=0x55555721523c
>lookup: e->start_ip_offset = fffffffffebc5730
...........
>lookup: e->start_ip_offset = fffffffffe6a1410
>_ULx86_64_dwarf_search_unwind_table:
ip=0x5555558b67a8, start_ip=0xfffffffffe6a1410
>_ULx86_64_dwarf_search_unwind_table: e->fde_offset = 8e0b0, segbase
= 555557215230, debug_frame_base = 0, fde_addr = 5555572a32e0
>_ULx86_64_dwarf_extract_proc_info_from_fde: FDE @ 0x5555572a32e0
>_ULx86_64_dwarf_extract_proc_info_from_fde: looking
for CIE at address 55555728fe84
>parse_cie: CIE parsed OK, augmentation = "zPLR",
handler=0x7fffeeaf3a80
>_ULx86_64_dwarf_extract_proc_info_from_fde: FDE covers
IP 0x5555558b6640-0x5555558b6867, LSDA=0x5555574a67ec
>_ULx86_64_fetch_frame: fetch frame ip=0x5555558b67a9
cfa=0x7fffffffca90 format=0
>access_mem: mem[00007fffffffca88] <- 5555558b67e9
>_ULx86_64_resume: (cursor=0x7fffffff6870)
>establish_machine_state: copying out cursor state
>establish_machine_state: copying RBP 6
>access_mem: mem[00007fffffffca70] -> 7fffffffcab0
>access_reg: RBP <- 0x00007fffffffcab0
>establish_machine_state: copying RSP 7
>access_reg: RSP <- 0x00007fffffffca90
>establish_machine_state: copying R8 8
>access_mem: mem[00007fffffff64c8] -> 555557ced700
... All of these are wrong and cause a crash after landing in the
exception handler in main():
>access_reg: R12 <- 0x73746e6f662f6269
>establish_machine_state: copying R13 13
>access_mem: mem[00007fffffffca98] -> 257c32600
>access_reg: R13 <- 0x0000000257c32600
>establish_machine_state: copying R14 14
>access_mem: mem[00007fffffffcaa0] -> 555557c325d0
>access_reg: R14 <- 0x0000555557c325d0
>establish_machine_state: copying R15 15
>access_mem: mem[00007fffffffcaa8] -> 17ebc2371241f
>access_reg: R15 <- 0x00017ebc2371241f
>establish_machine_state: copying RIP 16
>access_mem: mem[00007fffffffca88] -> 5555558b67e9
>access_reg: RIP <- 0x00005555558b67e9
Does anyone have any ideas? What could be causing this?
I'm tearing my hair out. Thanks a lot!
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Incorrect unwind when throwing exceptions - possible cause?
2022-02-03 0:43 Incorrect unwind when throwing exceptions - possible cause? Juraj Oršulić
@ 2022-02-03 1:06 ` Sam Varshavchik
2022-02-03 1:36 ` Juraj Oršulić
2022-02-03 11:39 ` Florian Weimer
2 siblings, 0 replies; 8+ messages in thread
From: Sam Varshavchik @ 2022-02-03 1:06 UTC (permalink / raw)
To: gcc-help
[-- Attachment #1: Type: text/plain, Size: 646 bytes --]
Juraj Oršulić writes:
> I have a hair-tearing problem with x86_64 gcc 9.3.0 (Ubuntu 20.04),
> -O2 and the following "minimal" example
> (the real minimal example also links in a bunch of 3rd party libraries
> and is a part of a big project, so I can't really provide a minimal example,
> but I slimmed it down to basically this):
>
> class Application() {
> public:
> Application(int argc, char **argv) {}
>
> int process() {
> if (argc > 1) { throw std::runtime_error("Exception"); }
>
> // do some processing here
> return 0;
> }
This was slimmed down too much. I don't see how this would compile.
[-- Attachment #2: Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Incorrect unwind when throwing exceptions - possible cause?
2022-02-03 0:43 Incorrect unwind when throwing exceptions - possible cause? Juraj Oršulić
2022-02-03 1:06 ` Sam Varshavchik
@ 2022-02-03 1:36 ` Juraj Oršulić
2022-02-03 2:15 ` Juraj Oršulić
2022-02-03 11:39 ` Florian Weimer
2 siblings, 1 reply; 8+ messages in thread
From: Juraj Oršulić @ 2022-02-03 1:36 UTC (permalink / raw)
To: gcc-help
Hi Sam, thanks for replying. The example wasn't meant to be compile
(sure, I missed the class closing brace and omitted storing argc).
That's not the point.
To reproduce it I would need to include a bunch of other code from the
codebase and put it inside ::process().
The point is that the mere presence of this code causes it to crash
if I throw right at the beginning -- I don't even execute any of that code.
I'm trying to figure out why the DWARF unwinding code becomes incorrect,
as I described in detail.
Sam Varshavchik wrote:
> This was slimmed down too much. I don't see how this would compile.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Incorrect unwind when throwing exceptions - possible cause?
2022-02-03 1:36 ` Juraj Oršulić
@ 2022-02-03 2:15 ` Juraj Oršulić
0 siblings, 0 replies; 8+ messages in thread
From: Juraj Oršulić @ 2022-02-03 2:15 UTC (permalink / raw)
To: gcc-help
One additional detail: when I build in debug (-O0), it doesn't crash.
In that case, gcc decides to use an unwind table based on offsets
against the cfa instead of against rbp, which works fine:
>_ULx86_64_fetch_frame: fetch frame ip=0x55555589afb7
cfa=0x7fffffff94d0 format=0
>run_cfi_program: CFA_def_cfa r7+0x8
>run_cfi_program: CFA_offset r16 at cfa+0xfffffffffffffff8
>run_cfi_program: CFA_advance_loc to 0x5555558855b3
>run_cfi_program: CFA_def_cfa_offset 0x10
>run_cfi_program: CFA_offset r6 at cfa+0xfffffffffffffff0
>run_cfi_program: CFA_advance_loc to 0x5555558855b6
>run_cfi_program: CFA_def_cfa_register r6
>run_cfi_program: CFA_advance_loc to 0x5555558855e6
>run_cfi_program: CFA_offset r13 at cfa+0xffffffffffffffe8
>run_cfi_program: CFA_offset r12 at cfa+0xffffffffffffffe0
>run_cfi_program: CFA_offset r3 at cfa+0xffffffffffffffd8
On Thu, Feb 3, 2022 at 2:36 AM Juraj Oršulić <juraj.orsulic@fer.hr> wrote:
>
> Hi Sam, thanks for replying. The example wasn't meant to be compile
> (sure, I missed the class closing brace and omitted storing argc).
> That's not the point.
> To reproduce it I would need to include a bunch of other code from the
> codebase and put it inside ::process().
> The point is that the mere presence of this code causes it to crash
> if I throw right at the beginning -- I don't even execute any of that code.
> I'm trying to figure out why the DWARF unwinding code becomes incorrect,
> as I described in detail.
>
>
>
> Sam Varshavchik wrote:
>
> > This was slimmed down too much. I don't see how this would compile.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Incorrect unwind when throwing exceptions - possible cause?
2022-02-03 0:43 Incorrect unwind when throwing exceptions - possible cause? Juraj Oršulić
2022-02-03 1:06 ` Sam Varshavchik
2022-02-03 1:36 ` Juraj Oršulić
@ 2022-02-03 11:39 ` Florian Weimer
[not found] ` <CAEPqvowbo+iH4dazsfub3Vjc1D_zFGgKv2tg92Kv32vGVTq-2w@mail.gmail.com>
2 siblings, 1 reply; 8+ messages in thread
From: Florian Weimer @ 2022-02-03 11:39 UTC (permalink / raw)
To: Juraj Oršulić; +Cc: gcc-help
* Juraj Oršulić:
> I have a hair-tearing problem with x86_64 gcc 9.3.0 (Ubuntu 20.04),
> -O2 and the following "minimal" example
> (the real minimal example also links in a bunch of 3rd party libraries
> and is a part of a big project, so I can't really provide a minimal example,
> but I slimmed it down to basically this):
Are you using the libgcc unwinder in the crashing case? (And not
libunwind.)
Thanks,
Florian
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2022-02-04 10:37 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-03 0:43 Incorrect unwind when throwing exceptions - possible cause? Juraj Oršulić
2022-02-03 1:06 ` Sam Varshavchik
2022-02-03 1:36 ` Juraj Oršulić
2022-02-03 2:15 ` Juraj Oršulić
2022-02-03 11:39 ` Florian Weimer
[not found] ` <CAEPqvowbo+iH4dazsfub3Vjc1D_zFGgKv2tg92Kv32vGVTq-2w@mail.gmail.com>
[not found] ` <87wnict9uz.fsf@oldenburg.str.redhat.com>
2022-02-03 13:40 ` Juraj Oršulić
2022-02-03 15:38 ` Juraj Oršulić
2022-02-04 10:37 ` Andrew Haley
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).