[Lldb-commits] [lldb] [lldb] fix step in AArch64 trampoline (PR #90783)

Vincent Belliard via lldb-commits lldb-commits at lists.llvm.org
Wed May 1 14:33:57 PDT 2024


https://github.com/v-bulle created https://github.com/llvm/llvm-project/pull/90783

Detects AArch64 trampolines in order to be able to step in a function through a trampoline on AArch64.

>From 12464941c1b11ffad0ff2566642df3d30976a3f9 Mon Sep 17 00:00:00 2001
From: Vincent Belliard <v-bulle at github.com>
Date: Thu, 18 Apr 2024 10:39:59 -0700
Subject: [PATCH] [lldb] fix step in AArch64 trampoline

---
 .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp     | 26 ++++++++++++++++---
 .../Plugins/ObjectFile/ELF/ObjectFileELF.cpp  | 19 +++++++++++++-
 .../StepIn/Inputs/aarch64_thunk.cc            | 15 +++++++++++
 .../StepIn/step_through-aarch64-thunk.test    | 17 ++++++++++++
 4 files changed, 73 insertions(+), 4 deletions(-)
 create mode 100644 lldb/test/Shell/ExecControl/StepIn/Inputs/aarch64_thunk.cc
 create mode 100644 lldb/test/Shell/ExecControl/StepIn/step_through-aarch64-thunk.test

diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 9fa245fc41d40c..232030268e42c8 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -506,9 +506,29 @@ DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread,
   Target &target = thread.GetProcess()->GetTarget();
   const ModuleList &images = target.GetImages();
 
-  images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols);
-  if (!target_symbols.GetSize())
-    return thread_plan_sp;
+  llvm::StringRef target_name = sym_name.GetStringRef();
+  // On AArch64, the trampoline name has a prefix (__AArch64ADRPThunk_ or
+  // __AArch64AbsLongThunk_) added to the function name. If we detect a
+  // trampoline with the prefix, we need to remove the prefix to find the
+  // function symbol.
+  if (target_name.consume_front("__AArch64ADRPThunk_")) {
+    // An empty target name can happen when for trampolines generated for
+    // section-referencing relocations.
+    if (!target_name.empty()) {
+      images.FindSymbolsWithNameAndType(ConstString(target_name),
+                                        eSymbolTypeCode, target_symbols);
+    }
+  } else if (target_name.consume_front("__AArch64AbsLongThunk_")) {
+    // An empty target name can happen when for trampolines generated for
+    // section-referencing relocations.
+    if (!target_name.empty()) {
+      images.FindSymbolsWithNameAndType(ConstString(target_name),
+                                        eSymbolTypeCode, target_symbols);
+    }
+  } else {
+    images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode,
+                                      target_symbols);
+  }
 
   typedef std::vector<lldb::addr_t> AddressVector;
   AddressVector addrs;
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 16f6d2e884b577..1646ee9aa34a61 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -2356,13 +2356,30 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
     bool symbol_size_valid =
         symbol.st_size != 0 || symbol.getType() != STT_FUNC;
 
+    bool is_trampoline = false;
+    if (arch.IsValid() && (arch.GetMachine() == llvm::Triple::aarch64)) {
+      // On AArch64, trampolines are registered as code.
+      // If we detect a trampoline (which starts with __AArch64ADRPThunk_ or
+      // __AArch64AbsLongThunk_) we register the symbol as a trampoline. This
+      // way we will be able to detect the trampoline when we step in a function
+      // and step through the trampoline.
+      if (symbol_type == eSymbolTypeCode) {
+        llvm::StringRef trampoline_name = mangled.GetName().GetStringRef();
+        if (trampoline_name.starts_with("__AArch64ADRPThunk_") ||
+            trampoline_name.starts_with("__AArch64AbsLongThunk_")) {
+          symbol_type = eSymbolTypeTrampoline;
+          is_trampoline = true;
+        }
+      }
+    }
+
     Symbol dc_symbol(
         i + start_id, // ID is the original symbol table index.
         mangled,
         symbol_type,                    // Type of this symbol
         is_global,                      // Is this globally visible?
         false,                          // Is this symbol debug info?
-        false,                          // Is this symbol a trampoline?
+        is_trampoline,                  // Is this symbol a trampoline?
         false,                          // Is this symbol artificial?
         AddressRange(symbol_section_sp, // Section in which this symbol is
                                         // defined or null.
diff --git a/lldb/test/Shell/ExecControl/StepIn/Inputs/aarch64_thunk.cc b/lldb/test/Shell/ExecControl/StepIn/Inputs/aarch64_thunk.cc
new file mode 100644
index 00000000000000..02f3bef32a59a3
--- /dev/null
+++ b/lldb/test/Shell/ExecControl/StepIn/Inputs/aarch64_thunk.cc
@@ -0,0 +1,15 @@
+extern "C" int __attribute__((naked)) __AArch64ADRPThunk_step_here() {
+    asm (
+      "adrp x16, step_here\n"
+      "add x16, x16, :lo12:step_here\n"
+      "br x16"
+    );
+}
+
+extern "C" __attribute__((used)) int step_here() {
+    return 47;
+}
+
+int main() {
+  return __AArch64ADRPThunk_step_here();
+}
diff --git a/lldb/test/Shell/ExecControl/StepIn/step_through-aarch64-thunk.test b/lldb/test/Shell/ExecControl/StepIn/step_through-aarch64-thunk.test
new file mode 100644
index 00000000000000..336a746fa3a418
--- /dev/null
+++ b/lldb/test/Shell/ExecControl/StepIn/step_through-aarch64-thunk.test
@@ -0,0 +1,17 @@
+# REQUIRES: native && target-aarch64
+
+# This test is specific to elf platforms.
+# UNSUPPORTED: system-windows, system-darwin
+
+# RUN: %clangxx_host %p/Inputs/aarch64_thunk.cc -g -o %t.out
+# RUN: %lldb %t.out -s %s | FileCheck %s
+
+b main
+# CHECK: Breakpoint 1: where = step_through-aarch64-thunk.test.tmp.out`main
+
+r
+# CHECK: stop reason = breakpoint 1.1
+
+s
+# CHECK: stop reason = step in
+# CHECK:     frame #0: {{.*}} step_through-aarch64-thunk.test.tmp.out`::step_here()



More information about the lldb-commits mailing list