-
Notifications
You must be signed in to change notification settings - Fork 15.5k
Description
clang version 18.0.0 (bc41b0a)
Target: x86_64-unknown-linux-gnu
In the reproducer below, there's an indirect call through b's vtable to virtual function v. The vtable address is loaded into RAX, and as v is the second vtable entry we get the code call qword ptr [rax + 8].
The DW_AT_call_target attribute on the call site info, below, is not only wrong (see #70949) but also we should not be using a volatile register in DW_AT_call_target expressions.
DW_AT_call_target (DW_OP_reg0 RAX)
From the DWARF 5 spec
The call site may have a DW_AT_call_target attribute which is a DWARF expression. For indirect calls or jumps where it is unknown at compile time which subprogram will be called the expression computes the address of the subprogram that will be called.
The DWARF expression should not use register or memory locations that might be clobbered by the call.
DW_AT_call_target_clobbered should be used instead.
$ cat test.cpp
struct Base {
virtual int zz() { return x; }
[[clang::noinline]]
virtual int v() { return zz(); }
int x;
};
struct Child: public Base {
[[clang::noinline]]
virtual int v() { return x * 2; }
int x;
};
[[clang::noinline]]
[[clang::disable_tail_calls]]
int foo(Base* b) {
return b->v();
}
$ clang test.cpp -O2 -g -c -o test.o
$ llvm-dwarfdump test.o --name foo --show-children
0x00000027: DW_TAG_subprogram
DW_AT_name ("foo")
...
0x00000037: DW_TAG_formal_parameter
...
0x00000040: DW_TAG_call_site
DW_AT_call_target (DW_OP_reg0 RAX)
DW_AT_call_return_pc (0x0000000000000007)
0x00000044: DW_TAG_call_site_parameter
...
0x0000004b: NULL
0x0000004c: NULL
$ llvm-objdump --disassemble-symbols=_Z3fooP4Base test.o --x86-asm-syntax=intel
0000000000000000 <_Z3fooP4Base>:
0: 50 push rax
1: 48 8b 07 mov rax, qword ptr [rdi]
4: ff 50 08 call qword ptr [rax + 0x8]
7: 59 pop rcx
8: c3 ret