diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/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) diff --git a/clang/test/CodeGen/asan-frame-pointer.cpp b/clang/test/CodeGen/asan-frame-pointer.cpp new file mode 100644 --- /dev/null +++ b/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" } diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h --- a/llvm/include/llvm/IR/Module.h +++ b/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 /// @{ diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp --- a/llvm/lib/IR/Function.cpp +++ b/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; } diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp --- a/llvm/lib/IR/Module.cpp +++ b/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(getModuleFlag("frame-pointer")); + return Val ? cast(Val->getValue())->getZExtValue() : 0; +} + +void Module::setFramePointer(int V) { + addModuleFlag(ModFlagBehavior::Max, "frame-pointer", V); +} + void Module::setSDKVersion(const VersionTuple &V) { SmallVector Entries; Entries.push_back(V.getMajor()); diff --git a/llvm/test/Instrumentation/AddressSanitizer/uwtable.ll b/llvm/test/Instrumentation/AddressSanitizer/module-flags.ll rename from llvm/test/Instrumentation/AddressSanitizer/uwtable.ll rename to llvm/test/Instrumentation/AddressSanitizer/module-flags.ll --- a/llvm/test/Instrumentation/AddressSanitizer/uwtable.ll +++ b/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" }