[llvm] r369721 - hwasan: Untag unwound stack frames by wrapping personality functions.
Diana Picus via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 26 01:14:19 PDT 2019
Hi Peter,
This seems to be failing more often than not on one of our buildbots:
http://lab.llvm.org:8011/builders/clang-cmake-aarch64-lld/builds/7142
Any idea what the problem could be?
Thanks,
Diana
On Fri, 23 Aug 2019 at 03:27, Peter Collingbourne via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
>
> Author: pcc
> Date: Thu Aug 22 18:28:44 2019
> New Revision: 369721
>
> URL: http://llvm.org/viewvc/llvm-project?rev=369721&view=rev
> Log:
> hwasan: Untag unwound stack frames by wrapping personality functions.
>
> One problem with untagging memory in landing pads is that it only works
> correctly if the function that catches the exception is instrumented.
> If the function is uninstrumented, we have no opportunity to untag the
> memory.
>
> To address this, replace landing pad instrumentation with personality function
> wrapping. Each function with an instrumented stack has its personality function
> replaced with a wrapper provided by the runtime. Functions that did not have
> a personality function to begin with also get wrappers if they may be unwound
> past. As the unwinder calls personality functions during stack unwinding,
> the original personality function is called and the function's stack frame is
> untagged by the wrapper if the personality function instructs the unwinder
> to keep unwinding. If unwinding stops at a landing pad, the function is
> still responsible for untagging its stack frame if it resumes unwinding.
>
> The old landing pad mechanism is preserved for compatibility with old runtimes.
>
> Differential Revision: https://reviews.llvm.org/D66377
>
> Added:
> llvm/trunk/test/Instrumentation/HWAddressSanitizer/personality.ll
> Modified:
> llvm/trunk/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
> llvm/trunk/test/Instrumentation/HWAddressSanitizer/landingpad.ll
> llvm/trunk/utils/gn/secondary/compiler-rt/lib/hwasan/BUILD.gn
>
> Modified: llvm/trunk/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp?rev=369721&r1=369720&r2=369721&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp (original)
> +++ llvm/trunk/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp Thu Aug 22 18:28:44 2019
> @@ -12,6 +12,7 @@
> //===----------------------------------------------------------------------===//
>
> #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
> +#include "llvm/ADT/MapVector.h"
> #include "llvm/ADT/SmallVector.h"
> #include "llvm/ADT/StringExtras.h"
> #include "llvm/ADT/StringRef.h"
> @@ -55,6 +56,8 @@ using namespace llvm;
> static const char *const kHwasanModuleCtorName = "hwasan.module_ctor";
> static const char *const kHwasanNoteName = "hwasan.note";
> static const char *const kHwasanInitName = "__hwasan_init";
> +static const char *const kHwasanPersonalityThunkName =
> + "__hwasan_personality_thunk";
>
> static const char *const kHwasanShadowMemoryDynamicAddress =
> "__hwasan_shadow_memory_dynamic_address";
> @@ -160,8 +163,12 @@ static cl::opt<bool>
>
> static cl::opt<bool>
> ClInstrumentLandingPads("hwasan-instrument-landing-pads",
> - cl::desc("instrument landing pads"), cl::Hidden,
> - cl::init(true));
> + cl::desc("instrument landing pads"), cl::Hidden,
> + cl::init(false));
> +
> +static cl::opt<bool> ClInstrumentPersonalityFunctions(
> + "hwasan-instrument-personality-functions",
> + cl::desc("instrument personality functions"), cl::Hidden, cl::init(false));
>
> static cl::opt<bool> ClInlineAllChecks("hwasan-inline-all-checks",
> cl::desc("inline all checks"),
> @@ -224,6 +231,8 @@ public:
> void instrumentGlobal(GlobalVariable *GV, uint8_t Tag);
> void instrumentGlobals();
>
> + void instrumentPersonalityFunctions();
> +
> private:
> LLVMContext *C;
> Module &M;
> @@ -250,6 +259,7 @@ private:
> };
> ShadowMapping Mapping;
>
> + Type *VoidTy = Type::getVoidTy(M.getContext());
> Type *IntptrTy;
> Type *Int8PtrTy;
> Type *Int8Ty;
> @@ -258,6 +268,7 @@ private:
>
> bool CompileKernel;
> bool Recover;
> + bool InstrumentLandingPads;
>
> Function *HwasanCtorFunction;
>
> @@ -373,14 +384,27 @@ void HWAddressSanitizer::initializeModul
> });
>
> // Older versions of Android do not have the required runtime support for
> - // global instrumentation. On other platforms we currently require using the
> - // latest version of the runtime.
> - bool InstrumentGlobals =
> + // global or personality function instrumentation. On other platforms we
> + // currently require using the latest version of the runtime.
> + bool NewRuntime =
> !TargetTriple.isAndroid() || !TargetTriple.isAndroidVersionLT(30);
> - if (ClGlobals.getNumOccurrences())
> - InstrumentGlobals = ClGlobals;
> +
> + bool InstrumentGlobals =
> + ClGlobals.getNumOccurrences() ? ClGlobals : NewRuntime;
> if (InstrumentGlobals)
> instrumentGlobals();
> +
> + // If we don't have personality function support, fall back to landing pads.
> + InstrumentLandingPads = ClInstrumentLandingPads.getNumOccurrences()
> + ? ClInstrumentLandingPads
> + : !NewRuntime;
> +
> + bool InstrumentPersonalityFunctions =
> + ClInstrumentPersonalityFunctions.getNumOccurrences()
> + ? ClInstrumentPersonalityFunctions
> + : NewRuntime;
> + if (InstrumentPersonalityFunctions)
> + instrumentPersonalityFunctions();
> }
>
> if (!TargetTriple.isAndroid()) {
> @@ -1092,7 +1116,7 @@ bool HWAddressSanitizer::sanitizeFunctio
> if (auto *Alloca = dyn_cast_or_null<AllocaInst>(DDI->getAddress()))
> AllocaDeclareMap[Alloca].push_back(DDI);
>
> - if (ClInstrumentLandingPads && isa<LandingPadInst>(Inst))
> + if (InstrumentLandingPads && isa<LandingPadInst>(Inst))
> LandingPadVec.push_back(&Inst);
>
> Value *MaybeMask = nullptr;
> @@ -1111,6 +1135,13 @@ bool HWAddressSanitizer::sanitizeFunctio
> if (!LandingPadVec.empty())
> instrumentLandingPads(LandingPadVec);
>
> + if (AllocasToInstrument.empty() && F.hasPersonalityFn() &&
> + F.getPersonalityFn()->getName() == kHwasanPersonalityThunkName) {
> + // __hwasan_personality_thunk is a no-op for functions without an
> + // instrumented stack, so we can drop it.
> + F.setPersonalityFn(nullptr);
> + }
> +
> if (AllocasToInstrument.empty() && ToInstrument.empty())
> return false;
>
> @@ -1386,6 +1417,69 @@ void HWAddressSanitizer::instrumentGloba
> }
> }
>
> +void HWAddressSanitizer::instrumentPersonalityFunctions() {
> + // We need to untag stack frames as we unwind past them. That is the job of
> + // the personality function wrapper, which either wraps an existing
> + // personality function or acts as a personality function on its own. Each
> + // function that has a personality function or that can be unwound past has
> + // its personality function changed to a thunk that calls the personality
> + // function wrapper in the runtime.
> + MapVector<Constant *, std::vector<Function *>> PersonalityFns;
> + for (Function &F : M) {
> + if (F.isDeclaration() || !F.hasFnAttribute(Attribute::SanitizeHWAddress))
> + continue;
> +
> + if (F.hasPersonalityFn()) {
> + PersonalityFns[F.getPersonalityFn()->stripPointerCasts()].push_back(&F);
> + } else if (!F.hasFnAttribute(Attribute::NoUnwind)) {
> + PersonalityFns[nullptr].push_back(&F);
> + }
> + }
> +
> + if (PersonalityFns.empty())
> + return;
> +
> + FunctionCallee HwasanPersonalityWrapper = M.getOrInsertFunction(
> + "__hwasan_personality_wrapper", Int32Ty, Int32Ty, Int32Ty, Int64Ty,
> + Int8PtrTy, Int8PtrTy, Int8PtrTy, Int8PtrTy, Int8PtrTy);
> + FunctionCallee UnwindGetGR = M.getOrInsertFunction("_Unwind_GetGR", VoidTy);
> + FunctionCallee UnwindGetCFA = M.getOrInsertFunction("_Unwind_GetCFA", VoidTy);
> +
> + for (auto &P : PersonalityFns) {
> + std::string ThunkName = kHwasanPersonalityThunkName;
> + if (P.first)
> + ThunkName += ("." + P.first->getName()).str();
> + FunctionType *ThunkFnTy = FunctionType::get(
> + Int32Ty, {Int32Ty, Int32Ty, Int64Ty, Int8PtrTy, Int8PtrTy}, false);
> + bool IsLocal = P.first && (!isa<GlobalValue>(P.first) ||
> + cast<GlobalValue>(P.first)->hasLocalLinkage());
> + auto *ThunkFn = Function::Create(ThunkFnTy,
> + IsLocal ? GlobalValue::InternalLinkage
> + : GlobalValue::LinkOnceODRLinkage,
> + ThunkName, &M);
> + if (!IsLocal) {
> + ThunkFn->setVisibility(GlobalValue::HiddenVisibility);
> + ThunkFn->setComdat(M.getOrInsertComdat(ThunkName));
> + }
> +
> + auto *BB = BasicBlock::Create(*C, "entry", ThunkFn);
> + IRBuilder<> IRB(BB);
> + CallInst *WrapperCall = IRB.CreateCall(
> + HwasanPersonalityWrapper,
> + {ThunkFn->getArg(0), ThunkFn->getArg(1), ThunkFn->getArg(2),
> + ThunkFn->getArg(3), ThunkFn->getArg(4),
> + P.first ? IRB.CreateBitCast(P.first, Int8PtrTy)
> + : Constant::getNullValue(Int8PtrTy),
> + IRB.CreateBitCast(UnwindGetGR.getCallee(), Int8PtrTy),
> + IRB.CreateBitCast(UnwindGetCFA.getCallee(), Int8PtrTy)});
> + WrapperCall->setTailCall();
> + IRB.CreateRet(WrapperCall);
> +
> + for (Function *F : P.second)
> + F->setPersonalityFn(ThunkFn);
> + }
> +}
> +
> void HWAddressSanitizer::ShadowMapping::init(Triple &TargetTriple) {
> Scale = kDefaultShadowScale;
> if (ClMappingOffset.getNumOccurrences() > 0) {
>
> Modified: llvm/trunk/test/Instrumentation/HWAddressSanitizer/landingpad.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/HWAddressSanitizer/landingpad.ll?rev=369721&r1=369720&r2=369721&view=diff
> ==============================================================================
> --- llvm/trunk/test/Instrumentation/HWAddressSanitizer/landingpad.ll (original)
> +++ llvm/trunk/test/Instrumentation/HWAddressSanitizer/landingpad.ll Thu Aug 22 18:28:44 2019
> @@ -1,5 +1,6 @@
> -; RUN: opt < %s -mtriple aarch64-linux-android -hwasan -S | FileCheck %s --check-prefixes=COMMON,ARM
> -; RUN: opt < %s -mtriple x86_64-linux -hwasan -S | FileCheck %s --check-prefixes=COMMON,X86
> +; RUN: opt < %s -mtriple aarch64-linux-android29 -hwasan -S | FileCheck %s --check-prefixes=COMMON,LP,ARM
> +; RUN: opt < %s -mtriple x86_64-linux -hwasan-instrument-landing-pads -hwasan -S | FileCheck %s --check-prefixes=COMMON,LP,X86
> +; RUN: opt < %s -mtriple aarch64-linux-android30 -hwasan -S | FileCheck %s --check-prefixes=COMMON,NOLP
>
> target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
> target triple = "aarch64-unknown-linux-android"
> @@ -15,8 +16,9 @@ lpad:
> %0 = landingpad { i8*, i32 }
> catch i8* null
>
> - ; COMMON-NEXT: %[[X:[^ ]*]] = call i64 @llvm.read_register.i64(metadata ![[META:[^ ]*]])
> - ; COMMON-NEXT: call void @__hwasan_handle_vfork(i64 %[[X]])
> + ; NOLP-NOT: call void @__hwasan_handle_vfork
> + ; LP-NEXT: %[[X:[^ ]*]] = call i64 @llvm.read_register.i64(metadata ![[META:[^ ]*]])
> + ; LP-NEXT: call void @__hwasan_handle_vfork(i64 %[[X]])
>
> %1 = extractvalue { i8*, i32 } %0, 0
> %2 = tail call i8* @__cxa_begin_catch(i8* %1)
>
> Added: llvm/trunk/test/Instrumentation/HWAddressSanitizer/personality.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/HWAddressSanitizer/personality.ll?rev=369721&view=auto
> ==============================================================================
> --- llvm/trunk/test/Instrumentation/HWAddressSanitizer/personality.ll (added)
> +++ llvm/trunk/test/Instrumentation/HWAddressSanitizer/personality.ll Thu Aug 22 18:28:44 2019
> @@ -0,0 +1,90 @@
> +; RUN: opt < %s -mtriple aarch64-linux-android29 -hwasan -S | FileCheck %s --check-prefix=NOPERS
> +; RUN: opt < %s -mtriple aarch64-linux-android30 -hwasan -S | FileCheck %s --check-prefix=PERS
> +
> +; NOPERS: define void @nostack() #{{[0-9]+}} {
> +; PERS: define void @nostack() #{{[0-9]+}} {
> +define void @nostack() sanitize_hwaddress {
> + ret void
> +}
> +
> +; NOPERS: define void @stack1() #{{[0-9]+}} {
> +; PERS: personality {{.*}} @__hwasan_personality_thunk
> +define void @stack1() sanitize_hwaddress {
> + %p = alloca i8
> + call void @sink(i8* %p)
> + ret void
> +}
> +
> +
> +; NOPERS: personality void ()* @global
> +; PERS: personality {{.*}} @__hwasan_personality_thunk.global
> +define void @stack2() sanitize_hwaddress personality void ()* @global {
> + %p = alloca i8
> + call void @sink(i8* %p)
> + ret void
> +}
> +
> +define internal void @local() {
> + ret void
> +}
> +
> + at local_alias = internal alias void (), void ()* @local
> +
> +; NOPERS: personality void ()* @local
> +; PERS: personality {{.*}} @__hwasan_personality_thunk.local
> +define void @stack3() sanitize_hwaddress personality void ()* @local {
> + %p = alloca i8
> + call void @sink(i8* %p)
> + ret void
> +}
> +
> +; NOPERS: personality void ()* @local_alias
> +; PERS: personality {{.*}} @__hwasan_personality_thunk.local_alias
> +define void @stack4() sanitize_hwaddress personality void ()* @local_alias {
> + %p = alloca i8
> + call void @sink(i8* %p)
> + ret void
> +}
> +
> +; NOPERS: personality void ()* inttoptr (i64 1 to void ()*)
> +; PERS: personality i32 (i32, i32, i64, i8*, i8*)* @__hwasan_personality_thunk.
> +define void @stack5() sanitize_hwaddress personality void ()* inttoptr (i64 1 to void ()*) {
> + %p = alloca i8
> + call void @sink(i8* %p)
> + ret void
> +}
> +
> +; NOPERS: personality void ()* inttoptr (i64 2 to void ()*)
> +; PERS: personality i32 (i32, i32, i64, i8*, i8*)* @__hwasan_personality_thunk..1
> +define void @stack6() sanitize_hwaddress personality void ()* inttoptr (i64 2 to void ()*) {
> + %p = alloca i8
> + call void @sink(i8* %p)
> + ret void
> +}
> +
> +declare void @global()
> +declare void @sink(i8*)
> +
> +; PERS: define linkonce_odr hidden i32 @__hwasan_personality_thunk(i32 %0, i32 %1, i64 %2, i8* %3, i8* %4) comdat
> +; PERS: %5 = tail call i32 @__hwasan_personality_wrapper(i32 %0, i32 %1, i64 %2, i8* %3, i8* %4, i8* null, i8* bitcast (void ()* @_Unwind_GetGR to i8*), i8* bitcast (void ()* @_Unwind_GetCFA to i8*))
> +; PERS: ret i32 %5
> +
> +; PERS: define linkonce_odr hidden i32 @__hwasan_personality_thunk.global(i32 %0, i32 %1, i64 %2, i8* %3, i8* %4) comdat
> +; PERS: %5 = tail call i32 @__hwasan_personality_wrapper(i32 %0, i32 %1, i64 %2, i8* %3, i8* %4, i8* bitcast (void ()* @global to i8*), i8* bitcast (void ()* @_Unwind_GetGR to i8*), i8* bitcast (void ()* @_Unwind_GetCFA to i8*))
> +; PERS: ret i32 %5
> +
> +; PERS: define internal i32 @__hwasan_personality_thunk.local(i32 %0, i32 %1, i64 %2, i8* %3, i8* %4)
> +; PERS: %5 = tail call i32 @__hwasan_personality_wrapper(i32 %0, i32 %1, i64 %2, i8* %3, i8* %4, i8* bitcast (void ()* @local to i8*), i8* bitcast (void ()* @_Unwind_GetGR to i8*), i8* bitcast (void ()* @_Unwind_GetCFA to i8*))
> +; PERS: ret i32 %5
> +
> +; PERS: define internal i32 @__hwasan_personality_thunk.local_alias(i32 %0, i32 %1, i64 %2, i8* %3, i8* %4)
> +; PERS: %5 = tail call i32 @__hwasan_personality_wrapper(i32 %0, i32 %1, i64 %2, i8* %3, i8* %4, i8* bitcast (void ()* @local_alias to i8*), i8* bitcast (void ()* @_Unwind_GetGR to i8*), i8* bitcast (void ()* @_Unwind_GetCFA to i8*))
> +; PERS: ret i32 %5
> +
> +; PERS: define internal i32 @__hwasan_personality_thunk.(i32 %0, i32 %1, i64 %2, i8* %3, i8* %4) {
> +; PERS: %5 = tail call i32 @__hwasan_personality_wrapper(i32 %0, i32 %1, i64 %2, i8* %3, i8* %4, i8* inttoptr (i64 1 to i8*), i8* bitcast (void ()* @_Unwind_GetGR to i8*), i8* bitcast (void ()* @_Unwind_GetCFA to i8*))
> +; PERS: ret i32 %5
> +
> +; PERS: define internal i32 @__hwasan_personality_thunk..1(i32 %0, i32 %1, i64 %2, i8* %3, i8* %4) {
> +; PERS: %5 = tail call i32 @__hwasan_personality_wrapper(i32 %0, i32 %1, i64 %2, i8* %3, i8* %4, i8* inttoptr (i64 2 to i8*), i8* bitcast (void ()* @_Unwind_GetGR to i8*), i8* bitcast (void ()* @_Unwind_GetCFA to i8*))
> +; PERS: ret i32 %5
>
> Modified: llvm/trunk/utils/gn/secondary/compiler-rt/lib/hwasan/BUILD.gn
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/gn/secondary/compiler-rt/lib/hwasan/BUILD.gn?rev=369721&r1=369720&r2=369721&view=diff
> ==============================================================================
> --- llvm/trunk/utils/gn/secondary/compiler-rt/lib/hwasan/BUILD.gn (original)
> +++ llvm/trunk/utils/gn/secondary/compiler-rt/lib/hwasan/BUILD.gn Thu Aug 22 18:28:44 2019
> @@ -45,6 +45,7 @@ source_set("sources") {
> "hwasan_allocator.h",
> "hwasan_dynamic_shadow.cpp",
> "hwasan_dynamic_shadow.h",
> + "hwasan_exceptions.cpp",
> "hwasan_flags.h",
> "hwasan_interceptors.cpp",
> "hwasan_interceptors_vfork.S",
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list