aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGVTables.cpp
diff options
context:
space:
mode:
authorLeonard Chan <leonardchan@google.com>2022-08-26 18:20:34 +0000
committerLeonard Chan <leonardchan@google.com>2022-08-26 18:21:40 +0000
commit93e5cf6b9c08d99cf7cefc0adda346bd7ba56049 (patch)
treed3796ab2773a585062d240c2dc09a00405eb0926 /clang/lib/CodeGen/CGVTables.cpp
parentc58791c286e0b0feba04711e973bf7b4871d1dfb (diff)
downloadllvm-93e5cf6b9c08d99cf7cefc0adda346bd7ba56049.zip
llvm-93e5cf6b9c08d99cf7cefc0adda346bd7ba56049.tar.gz
llvm-93e5cf6b9c08d99cf7cefc0adda346bd7ba56049.tar.bz2
[clang] Do not instrument relative vtables under hwasan
Full context in https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=107017. Instrumenting hwasan with globals results in a linker error under the relative vtables abi: ``` ld.lld: error: libunwind.cpp:(.rodata..L_ZTVN9libunwind12UnwindCursorINS_17LocalAddressSpaceENS_15Registers_arm64EEE.hwasan+0x8): relocation R_AARCH64_PLT32 out of range: 6845471433603167792 is not in [-2147483648, 2147483647]; references libunwind::AbstractUnwindCursor::~AbstractUnwindCursor() >>> defined in libunwind/src/CMakeFiles/unwind_shared.dir/libunwind.cpp.obj ``` This is because the tag is included in the vtable address when calculating the offset between the vtable and virtual function. A temporary solution until we can resolve this is to just disable hwasan instrumentation on relative vtables specifically, which can be done in the frontend. Differential Revision: https://reviews.llvm.org/D132425
Diffstat (limited to 'clang/lib/CodeGen/CGVTables.cpp')
-rw-r--r--clang/lib/CodeGen/CGVTables.cpp25
1 files changed, 23 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index cdd40d2..c8b29ae 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -921,12 +921,33 @@ llvm::GlobalVariable *CodeGenVTables::GenerateConstructionVTable(
CGM.EmitVTableTypeMetadata(RD, VTable, *VTLayout.get());
- if (UsingRelativeLayout && !VTable->isDSOLocal())
- GenerateRelativeVTableAlias(VTable, OutName);
+ if (UsingRelativeLayout) {
+ RemoveHwasanMetadata(VTable);
+ if (!VTable->isDSOLocal())
+ GenerateRelativeVTableAlias(VTable, OutName);
+ }
return VTable;
}
+// Ensure this vtable is not instrumented by hwasan. That is, a global alias is
+// not generated for it. This is mainly used by the relative-vtables ABI where
+// vtables instead contain 32-bit offsets between the vtable and function
+// pointers. Hwasan is disabled for these vtables for now because the tag in a
+// vtable pointer may fail the overflow check when resolving 32-bit PLT
+// relocations. A future alternative for this would be finding which usages of
+// the vtable can continue to use the untagged hwasan value without any loss of
+// value in hwasan.
+void CodeGenVTables::RemoveHwasanMetadata(llvm::GlobalValue *VTable) {
+ if (CGM.getLangOpts().Sanitize.has(SanitizerKind::HWAddress)) {
+ llvm::GlobalValue::SanitizerMetadata Meta;
+ if (VTable->hasSanitizerMetadata())
+ Meta = VTable->getSanitizerMetadata();
+ Meta.NoHWAddress = true;
+ VTable->setSanitizerMetadata(Meta);
+ }
+}
+
// If the VTable is not dso_local, then we will not be able to indicate that
// the VTable does not need a relocation and move into rodata. A frequent
// time this can occur is for classes that should be made public from a DSO