MaskRay created this revision. MaskRay added reviewers: Sanitizers, nickdesaulniers. Herald added subscribers: dexonsmith, hiraditya. MaskRay requested review of this revision. Herald added projects: clang, LLVM. Herald added subscribers: llvm-commits, cfe-commits.
The Linux kernel objtool diagnostic `call without frame pointer save/setup` arise in multiple instrumentation passes (asan/tsan/gcov). With the mechanism introduced in D100251 <https://reviews.llvm.org/D100251>, it's trivial to respect the command line -m[no-]omit-leaf-frame-pointer/-f[no-]omit-frame-pointer, so let's do it. Fix: https://github.com/ClangBuiltLinux/linux/issues/1236 (tsan) Fix: https://github.com/ClangBuiltLinux/linux/issues/1238 (asan) Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D101016 Files: clang/lib/CodeGen/CodeGenModule.cpp clang/test/CodeGen/asan-frame-pointer.cpp llvm/include/llvm/IR/Module.h llvm/lib/IR/Function.cpp llvm/lib/IR/Module.cpp llvm/test/Instrumentation/AddressSanitizer/module-flags.ll llvm/test/Instrumentation/AddressSanitizer/uwtable.ll
Index: llvm/test/Instrumentation/AddressSanitizer/module-flags.ll =================================================================== --- llvm/test/Instrumentation/AddressSanitizer/module-flags.ll +++ llvm/test/Instrumentation/AddressSanitizer/module-flags.ll @@ -10,12 +10,15 @@ ret i32 %tmp } -!llvm.module.flags = !{!0} +!llvm.module.flags = !{!0, !1} ;; Due to -fasynchronous-unwind-tables. !0 = !{i32 7, !"uwtable", i32 1} +;; Due to -fno-omit-frame-pointer. +!1 = !{i32 7, !"frame-pointer", i32 2} + ;; Set the uwtable attribute on ctor/dtor. ; CHECK: define internal void @asan.module_ctor() #[[#ATTR:]] ; CHECK: define internal void @asan.module_dtor() #[[#ATTR]] -; CHECK: attributes #[[#ATTR]] = { nounwind uwtable } +; CHECK: attributes #[[#ATTR]] = { nounwind uwtable "frame-pointer"="all" } Index: llvm/lib/IR/Module.cpp =================================================================== --- llvm/lib/IR/Module.cpp +++ llvm/lib/IR/Module.cpp @@ -676,6 +676,15 @@ void Module::setUwtable() { addModuleFlag(ModFlagBehavior::Max, "uwtable", 1); } +int Module::getFramePointer() const { + auto *Val = cast_or_null<ConstantAsMetadata>(getModuleFlag("frame-pointer")); + return Val ? cast<ConstantInt>(Val->getValue())->getZExtValue() : 0; +} + +void Module::setFramePointer(int V) { + addModuleFlag(ModFlagBehavior::Max, "frame-pointer", V); +} + void Module::setSDKVersion(const VersionTuple &V) { SmallVector<unsigned, 3> Entries; Entries.push_back(V.getMajor()); Index: llvm/lib/IR/Function.cpp =================================================================== --- llvm/lib/IR/Function.cpp +++ llvm/lib/IR/Function.cpp @@ -335,8 +335,23 @@ unsigned AddrSpace, const Twine &N, Module *M) { auto *F = new Function(Ty, Linkage, AddrSpace, N, M); + AttrBuilder B; if (M->getUwtable()) - F->addAttribute(AttributeList::FunctionIndex, Attribute::UWTable); + B.addAttribute(Attribute::UWTable); + switch (M->getFramePointer()) { + case 0: + // 0 ("none") is the default. + break; + case 1: + B.addAttribute("frame-pointer", "non-leaf"); + break; + case 2: + B.addAttribute("frame-pointer", "all"); + break; + default: + llvm_unreachable("unknown \"frame-pointer\" value"); + } + F->addAttributes(AttributeList::FunctionIndex, B); return F; } Index: llvm/include/llvm/IR/Module.h =================================================================== --- llvm/include/llvm/IR/Module.h +++ llvm/include/llvm/IR/Module.h @@ -890,6 +890,11 @@ bool getUwtable() const; void setUwtable(); + /// Get/set whether synthesized functions should get the "frame-pointer" + /// attribute. + int getFramePointer() const; + void setFramePointer(int V); + /// @name Utility functions for querying and setting the build SDK version /// @{ Index: clang/test/CodeGen/asan-frame-pointer.cpp =================================================================== --- /dev/null +++ clang/test/CodeGen/asan-frame-pointer.cpp @@ -0,0 +1,19 @@ +/// -mframe-pointer=none sets the module flag "frame-pointer" (merge behavior: max). +/// asan synthesized ctor/dtor get the "frame-pointer" function attribute if not zero (default). +// RUN: %clang_cc1 -emit-llvm -fsanitize=address -mframe-pointer=none %s -o - | FileCheck %s --check-prefix=NONE +// RUN: %clang_cc1 -emit-llvm -fsanitize=address -mframe-pointer=non-leaf %s -o - | FileCheck %s --check-prefix=NONLEAF +// RUN: %clang_cc1 -emit-llvm -fsanitize=address -mframe-pointer=all %s -o - | FileCheck %s --check-prefix=ALL + +int global; + +// NONE: define internal void @asan.module_ctor() #[[#ATTR:]] { +// NONE: define internal void @asan.module_dtor() #[[#ATTR]] { +// NONE: attributes #[[#ATTR]] = { nounwind } + +// NONLEAF: define internal void @asan.module_ctor() #[[#ATTR:]] { +// NONLEAF: define internal void @asan.module_dtor() #[[#ATTR]] { +// NONLEAF: attributes #[[#ATTR]] = { nounwind "frame-pointer"="non-leaf" } + +// ALL: define internal void @asan.module_ctor() #[[#ATTR:]] { +// ALL: define internal void @asan.module_dtor() #[[#ATTR]] { +// ALL: attributes #[[#ATTR]] = { nounwind "frame-pointer"="all" } Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -744,6 +744,18 @@ if (CodeGenOpts.UnwindTables) getModule().setUwtable(); + switch (CodeGenOpts.getFramePointer()) { + case CodeGenOptions::FramePointerKind::None: + // 0 is the default. + break; + case CodeGenOptions::FramePointerKind::NonLeaf: + getModule().setFramePointer(1); + break; + case CodeGenOptions::FramePointerKind::All: + getModule().setFramePointer(2); + break; + } + SimplifyPersonality(); if (getCodeGenOpts().EmitDeclMetadata)
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits