[llvm] 3460f72 - EntryExitInstrumenter: skip naked functions

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Thu May 4 09:21:23 PDT 2023


Author: Fangrui Song
Date: 2023-05-04T09:21:18-07:00
New Revision: 3460f727eaa3a4c81f031b1533f9ad28c64faa4a

URL: https://github.com/llvm/llvm-project/commit/3460f727eaa3a4c81f031b1533f9ad28c64faa4a
DIFF: https://github.com/llvm/llvm-project/commit/3460f727eaa3a4c81f031b1533f9ad28c64faa4a.diff

LOG: EntryExitInstrumenter: skip naked functions

The asm in a naked function may reasonably expect the argument registers and the
return address register (if present) to be live.

When using -pg and -finstrument-functions, functions are instrumented by adding
a function call to `_mcount/__cyg_profile_func_enter/__cyg_profile_func_enter_bare`/etc,
which will clobber these registers. If the return address register is clobbered,
the function will be unable to return to the caller, possibly causing an
infinite loop.

```
__attribute__((naked)) void g() {
#if defined(__arm__)
  __asm__("bx lr");
#else
  __asm__("ret");
#endif
}

int main() { g(); }
```

It seems that the only one reasonable way to handle the combination is to
disable instrumenting for naked functions.

GCC PR: https://gcc.gnu.org/PR109707
Close https://github.com/llvm/llvm-project/issues/62504

Reviewed By: hans

Differential Revision: https://reviews.llvm.org/D149721

Added: 
    

Modified: 
    llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp
    llvm/test/Transforms/EntryExitInstrumenter/mcount.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp b/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp
index 2ccd2ab1641db..d424ebbef99d1 100644
--- a/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp
+++ b/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp
@@ -80,6 +80,13 @@ static void insertCall(Function &CurFn, StringRef Func,
 }
 
 static bool runOnFunction(Function &F, bool PostInlining) {
+  // The asm in a naked function may reasonably expect the argument registers
+  // and the return address register (if present) to be live. An inserted
+  // function call will clobber these registers. Simply skip naked functions for
+  // all targets.
+  if (F.hasFnAttribute(Attribute::Naked))
+    return false;
+
   StringRef EntryAttr = PostInlining ? "instrument-function-entry-inlined"
                                      : "instrument-function-entry";
 

diff  --git a/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll b/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll
index 9be81d96a8a37..c444b060d6130 100644
--- a/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll
+++ b/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll
@@ -99,6 +99,13 @@ define ptr @tailcaller2() #8 {
 ; CHECK: ret
 }
 
+;; naked functions are not instrumented, otherwise the argument registers
+;; and the return address register (if present) would be clobbered.
+define void @naked() naked { entry: ret void }
+; CHECK-LABEL:      define void @naked(
+; CHECK-LABEL-NEXT: entry:
+; CHECK-LABEL-NEXT:   ret void
+
 ; The attributes are "consumed" when the instrumentation is inserted.
 ; CHECK: attributes
 ; CHECK-NOT: instrument-function


        


More information about the llvm-commits mailing list