With relative vtables the caller jumps directly to the plt entries in the shared object,
therefore landing pad is need for these entries.
Reproducer:
main.cpp
#include "v.hpp" int main() { A* a = new B(); a->do_something2(); return 0; }
v.hpp
struct A { virtual void do_something() = 0; virtual void do_something2(); }; struct B : public A { void do_something() override; void do_something2() override; };
v.cpp
#include "v.hpp" void A::do_something2() { } void B::do_something() { } void B::do_something2() { }
CC="clang++ --target=aarch64-unknown-linux-gnu -fuse-ld=lld -mbranch-protection=bti" F=-fexperimental-relative-c++-abi-vtables ${=CC} $F -shared v.cpp -o v.so -z force-bti ${=CC} $F main.cpp -L./ v.so -Wl,-rpath=. -z force-bti qemu-aarch64-static -L /usr/aarch64-linux-gnu -cpu max ./a.out
For v.so, the regular vtable entry is relocated by an R_AARCH64_ABS64 relocation referencing _ZN1B13do_something2Ev.
_ZTV1B: .xword _ZN1B13do_something2Ev
Using relative vtable entry for a DSO has a downside of creating many PLT entries and making their addresses escape.
The relative vtable entry references a PLT entry _ZN1B13do_something2Ev@plt.
.L_ZTV1A.local: .word (_ZN1A13do_something2Ev@PLT-.L_ZTV1A.local)-8
fixes: #63580
Could you alter the comment to include the condition. Something like.