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.outFor 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)-8fixes: #63580
Could you alter the comment to include the condition. Something like.