[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