[llvm] r369721 - hwasan: Untag unwound stack frames by wrapping personality functions.
Evgenii Stepanov via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 26 12:55:17 PDT 2019
Thank you for letting us know. I'm looking at it.
On Mon, Aug 26, 2019 at 1:14 AM Diana Picus via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
>
> 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
> _______________________________________________
> 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