[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