augusto2112 created this revision.
augusto2112 added reviewers: aprantl, jingham, dblaikie.
Herald added a reviewer: shafik.
Herald added a project: All.
augusto2112 requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

This patch adds support for the DW_AT_trampoline attribute whose values
are mangled names. This patch makes it so stepping into a trampoline 
will step through to the target subprogram instead, stepping out from the
target subprogram will also step out of the trampoline, and that setting 
breakpoints by name will (by default) ignore trampolines.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D146679

Files:
  lldb/include/lldb/Symbol/Function.h
  lldb/include/lldb/Target/Target.h
  lldb/include/lldb/Target/ThreadPlanRunToAddress.h
  lldb/include/lldb/Target/ThreadPlanStepThrough.h
  lldb/source/Core/Module.cpp
  lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
  lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
  lldb/source/Symbol/Function.cpp
  lldb/source/Target/Target.cpp
  lldb/source/Target/TargetProperties.td
  lldb/source/Target/ThreadPlanRunToAddress.cpp
  lldb/source/Target/ThreadPlanShouldStopHere.cpp
  lldb/source/Target/ThreadPlanStepThrough.cpp
  lldb/test/API/lang/c/trampoline_stepping/Makefile
  lldb/test/API/lang/c/trampoline_stepping/TestTrampolineStepping.py
  lldb/test/API/lang/c/trampoline_stepping/main.c

Index: lldb/test/API/lang/c/trampoline_stepping/main.c
===================================================================
--- /dev/null
+++ lldb/test/API/lang/c/trampoline_stepping/main.c
@@ -0,0 +1,41 @@
+void bar(void) {}
+
+__attribute__((__trampoline__("bar")))
+void foo(void) {
+  bar();
+}
+
+__attribute__((__trampoline__("bar")))
+void baz(void) {
+  bar();
+}
+
+__attribute__((__trampoline__("bar")))
+void doesnt_call_trampoline(void) {
+  int a = 2;
+  int b = 3;
+  int c = a + b;
+}
+
+
+void direct_trampoline_call(void) {
+  foo(); // Break here for direct 
+  foo();
+}
+
+void chained_trampoline_call(void) {
+  baz(); // Break here for chained
+  baz();
+}
+
+void unused_target(void) {
+  doesnt_call_trampoline(); // Break here for unused
+}
+
+int main(void) {
+  direct_trampoline_call();
+  chained_trampoline_call();
+  unused_target();
+  return 0;
+}
+
Index: lldb/test/API/lang/c/trampoline_stepping/TestTrampolineStepping.py
===================================================================
--- /dev/null
+++ lldb/test/API/lang/c/trampoline_stepping/TestTrampolineStepping.py
@@ -0,0 +1,79 @@
+"""Test that stepping in/out of trampolines works as expected.
+"""
+
+
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestTrampoline(TestBase):
+    def setup(self, bkpt_str):
+        self.build()
+        
+        _, _, thread, _ = lldbutil.run_to_source_breakpoint(
+            self, bkpt_str, lldb.SBFileSpec('main.c'))
+        return thread
+
+    def test_direct_call(self):
+        thread = self.setup('Break here for direct')
+
+        # Sanity check that we start out in the correct function.
+        name = thread.frames[0].GetFunctionName()
+        self.assertIn('direct_trampoline_call', name)
+
+        # Check that stepping in will take us directly to the trampoline target.
+        thread.StepInto()
+        name = thread.frames[0].GetFunctionName()
+        self.assertIn('bar', name)
+
+        # Check that stepping out takes us back to the trampoline caller.
+        thread.StepOut()
+        name = thread.frames[0].GetFunctionName()
+        self.assertIn('direct_trampoline_call', name)
+
+        # Check that stepping over the end of the trampoline target 
+        # takes us back to the trampoline caller.
+        thread.StepInto()
+        thread.StepOver()
+        name = thread.frames[0].GetFunctionName()
+        self.assertIn('direct_trampoline_call', name)
+
+
+    def test_chained_call(self):
+        thread = self.setup('Break here for chained')
+
+        # Sanity check that we start out in the correct function.
+        name = thread.frames[0].GetFunctionName()
+        self.assertIn('chained_trampoline_call', name)
+
+        # Check that stepping in will take us directly to the trampoline target.
+        thread.StepInto()
+        name = thread.frames[0].GetFunctionName()
+        self.assertIn('bar', name)
+
+        # Check that stepping out takes us back to the trampoline caller.
+        thread.StepOut()
+        name = thread.frames[0].GetFunctionName()
+        self.assertIn('chained_trampoline_call', name)
+
+        # Check that stepping over the end of the trampoline target 
+        # takes us back to the trampoline caller.
+        thread.StepInto()
+        thread.StepOver()
+        name = thread.frames[0].GetFunctionName()
+        self.assertIn('chained_trampoline_call', name)
+
+    def test_unused_target(self):
+        thread = self.setup('Break here for unused')
+
+        # Sanity check that we start out in the correct function.
+        name = thread.frames[0].GetFunctionName()
+        self.assertIn('unused_target', name)
+
+        # Check that stepping into a trampoline that doesn't call its target
+        # jumps back to its caller.
+        thread.StepInto()
+        name = thread.frames[0].GetFunctionName()
+        self.assertIn('unused_target', name)
Index: lldb/test/API/lang/c/trampoline_stepping/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/lang/c/trampoline_stepping/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
Index: lldb/source/Target/ThreadPlanStepThrough.cpp
===================================================================
--- lldb/source/Target/ThreadPlanStepThrough.cpp
+++ lldb/source/Target/ThreadPlanStepThrough.cpp
@@ -8,11 +8,13 @@
 
 #include "lldb/Target/ThreadPlanStepThrough.h"
 #include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Symbol/Function.h"
 #include "lldb/Target/DynamicLoader.h"
 #include "lldb/Target/LanguageRuntime.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/RegisterContext.h"
 #include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlanRunToAddress.h"
 #include "lldb/Utility/LLDBLog.h"
 #include "lldb/Utility/Log.h"
 #include "lldb/Utility/Stream.h"
@@ -33,6 +35,10 @@
       m_start_address(0), m_backstop_bkpt_id(LLDB_INVALID_BREAK_ID),
       m_backstop_addr(LLDB_INVALID_ADDRESS), m_return_stack_id(m_stack_id),
       m_stop_others(stop_others) {
+  // If trampoline support is disabled, there's nothing for us to do.
+  if (!Target::GetGlobalProperties().GetEnableTrampolineSupport())
+    return;
+
   LookForPlanToStepThroughFromCurrentPC();
 
   // If we don't get a valid step through plan, don't bother to set up a
@@ -95,6 +101,9 @@
     }
   }
 
+  if (!m_sub_plan_sp)
+    m_sub_plan_sp = LookForFunctionWithTrampolineTarget();
+
   Log *log = GetLog(LLDBLog::Step);
   if (log) {
     lldb::addr_t current_address = GetThread().GetRegisterContext()->GetPC(0);
@@ -111,6 +120,26 @@
   }
 }
 
+ThreadPlanSP ThreadPlanStepThrough::LookForFunctionWithTrampolineTarget() {
+  Thread &thread = GetThread();
+  TargetSP target_sp(thread.CalculateTarget());
+  StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get();
+  const SymbolContext &current_context =
+      current_frame->GetSymbolContext(lldb::eSymbolContextFunction);
+  Function *current_function = current_context.function;
+  if (!current_function)
+    return {};
+
+  ConstString trampoline_name =
+      ConstString(current_function->GetTrampolineTargetName());
+  if (trampoline_name.IsEmpty())
+    return {};
+
+  return ThreadPlanRunToAddress::MakeThreadPlanRunToAddressFromSymbol(
+      thread, trampoline_name, m_stop_others);
+  ;
+}
+
 void ThreadPlanStepThrough::GetDescription(Stream *s,
                                            lldb::DescriptionLevel level) {
   if (level == lldb::eDescriptionLevelBrief)
Index: lldb/source/Target/ThreadPlanShouldStopHere.cpp
===================================================================
--- lldb/source/Target/ThreadPlanShouldStopHere.cpp
+++ lldb/source/Target/ThreadPlanShouldStopHere.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Target/ThreadPlanShouldStopHere.h"
+#include "lldb/Symbol/Function.h"
 #include "lldb/Symbol/Symbol.h"
 #include "lldb/Target/RegisterContext.h"
 #include "lldb/Target/Thread.h"
@@ -81,10 +82,16 @@
   // independently.  If this ever
   // becomes expensive (this one isn't) we can try to have this set a state
   // that the StepFromHere can use.
-  if (frame) {
-    SymbolContext sc;
-    sc = frame->GetSymbolContext(eSymbolContextLineEntry);
-    if (sc.line_entry.line == 0)
+  SymbolContext sc;
+  sc = frame->GetSymbolContext(eSymbolContextLineEntry);
+
+  if (sc.line_entry.line == 0)
+    should_stop_here = false;
+
+  // If we're in a trampoline, don't stop by default.
+  if (Target::GetGlobalProperties().GetEnableTrampolineSupport()) {
+    sc = frame->GetSymbolContext(lldb::eSymbolContextFunction);
+    if (sc.function && sc.function->IsTrampoline())
       should_stop_here = false;
   }
 
Index: lldb/source/Target/ThreadPlanRunToAddress.cpp
===================================================================
--- lldb/source/Target/ThreadPlanRunToAddress.cpp
+++ lldb/source/Target/ThreadPlanRunToAddress.cpp
@@ -201,3 +201,111 @@
   }
   return found_it;
 }
+
+ThreadPlanSP ThreadPlanRunToAddress::MakeThreadPlanRunToAddressFromSymbol(
+    Thread &thread, ConstString symbol_name, bool stop_others) {
+  TargetSP target_sp(thread.CalculateTarget());
+  if (!target_sp)
+    return {};
+
+  Log *log = GetLog(LLDBLog::Step);
+  std::vector<Address> addresses;
+  const ModuleList &images = target_sp->GetImages();
+
+  SymbolContextList code_symbols;
+  images.FindSymbolsWithNameAndType(symbol_name, eSymbolTypeCode, code_symbols);
+  size_t num_code_symbols = code_symbols.GetSize();
+
+  if (num_code_symbols > 0) {
+    for (uint32_t i = 0; i < num_code_symbols; i++) {
+      SymbolContext context;
+      AddressRange addr_range;
+      if (code_symbols.GetContextAtIndex(i, context)) {
+        context.GetAddressRange(eSymbolContextEverything, 0, false, addr_range);
+        addresses.push_back(addr_range.GetBaseAddress());
+        if (log) {
+          addr_t load_addr =
+              addr_range.GetBaseAddress().GetLoadAddress(target_sp.get());
+
+          LLDB_LOGF(log, "Found a trampoline target symbol at 0x%" PRIx64 ".",
+                    load_addr);
+        }
+      }
+    }
+  }
+
+  SymbolContextList reexported_symbols;
+  images.FindSymbolsWithNameAndType(symbol_name, eSymbolTypeReExported,
+                                    reexported_symbols);
+  size_t num_reexported_symbols = reexported_symbols.GetSize();
+  if (num_reexported_symbols > 0) {
+    for (uint32_t i = 0; i < num_reexported_symbols; i++) {
+      SymbolContext context;
+      if (reexported_symbols.GetContextAtIndex(i, context)) {
+        if (context.symbol) {
+          Symbol *actual_symbol =
+              context.symbol->ResolveReExportedSymbol(*target_sp.get());
+          if (actual_symbol) {
+            const Address actual_symbol_addr = actual_symbol->GetAddress();
+            if (actual_symbol_addr.IsValid()) {
+              addresses.push_back(actual_symbol_addr);
+              if (log) {
+                lldb::addr_t load_addr =
+                    actual_symbol_addr.GetLoadAddress(target_sp.get());
+                LLDB_LOGF(log,
+                          "Found a re-exported symbol: %s at 0x%" PRIx64 ".",
+                          actual_symbol->GetName().GetCString(), load_addr);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  SymbolContextList indirect_symbols;
+  images.FindSymbolsWithNameAndType(symbol_name, eSymbolTypeResolver,
+                                    indirect_symbols);
+  size_t num_indirect_symbols = indirect_symbols.GetSize();
+  if (num_indirect_symbols > 0) {
+    for (uint32_t i = 0; i < num_indirect_symbols; i++) {
+      SymbolContext context;
+      AddressRange addr_range;
+      if (indirect_symbols.GetContextAtIndex(i, context)) {
+        context.GetAddressRange(eSymbolContextEverything, 0, false, addr_range);
+        addresses.push_back(addr_range.GetBaseAddress());
+        if (log) {
+          addr_t load_addr =
+              addr_range.GetBaseAddress().GetLoadAddress(target_sp.get());
+
+          LLDB_LOGF(log, "Found an indirect target symbol at 0x%" PRIx64 ".",
+                    load_addr);
+        }
+      }
+    }
+  }
+
+  if (addresses.empty())
+    return {};
+
+  // First check whether any of the addresses point to Indirect symbols,
+  // and if they do, resolve them:
+  std::vector<lldb::addr_t> load_addrs;
+  for (Address address : addresses) {
+    Symbol *symbol = address.CalculateSymbolContextSymbol();
+    if (symbol && symbol->IsIndirect()) {
+      Status error;
+      Address symbol_address = symbol->GetAddress();
+      addr_t resolved_addr =
+          thread.GetProcess()->ResolveIndirectFunction(&symbol_address, error);
+      if (error.Success()) {
+        load_addrs.push_back(resolved_addr);
+      }
+    } else {
+      load_addrs.push_back(address.GetLoadAddress(target_sp.get()));
+    }
+  }
+
+  return std::make_shared<ThreadPlanRunToAddress>(thread, load_addrs,
+                                                  stop_others);
+}
Index: lldb/source/Target/TargetProperties.td
===================================================================
--- lldb/source/Target/TargetProperties.td
+++ lldb/source/Target/TargetProperties.td
@@ -182,6 +182,9 @@
   def DebugUtilityExpression: Property<"debug-utility-expression", "Boolean">,
     DefaultFalse,
     Desc<"Enable debugging of LLDB-internal utility expressions.">;
+  def EnableTrampolineSupport: Property<"enable-trampoline-support", "Boolean">,
+    Global, DefaultTrue,
+    Desc<"Enable trampoline support in LLDB. Trampoline support includes stepping through trampoline directly to their targets, stepping out of trampolines directly to their callers, automatically filtering out trampolines as possible breakpoints locations when set by name, etc.">;
 }
 
 let Definition = "process_experimental" in {
Index: lldb/source/Target/Target.cpp
===================================================================
--- lldb/source/Target/Target.cpp
+++ lldb/source/Target/Target.cpp
@@ -4770,6 +4770,12 @@
       nullptr, idx, g_target_properties[idx].default_uint_value != 0);
 }
 
+bool TargetProperties::GetEnableTrampolineSupport() const {
+  const uint32_t idx = ePropertyEnableTrampolineSupport;
+  return m_collection_sp->GetPropertyAtIndexAsBoolean(
+      nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+}
+
 void TargetProperties::SetDebugUtilityExpression(bool debug) {
   const uint32_t idx = ePropertyDebugUtilityExpression;
   m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, debug);
Index: lldb/source/Symbol/Function.cpp
===================================================================
--- lldb/source/Symbol/Function.cpp
+++ lldb/source/Symbol/Function.cpp
@@ -231,10 +231,12 @@
 //
 Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid,
                    lldb::user_id_t type_uid, const Mangled &mangled, Type *type,
-                   const AddressRange &range)
+                   const AddressRange &range,
+                   llvm::StringRef trampoline_target)
     : UserID(func_uid), m_comp_unit(comp_unit), m_type_uid(type_uid),
-      m_type(type), m_mangled(mangled), m_block(func_uid), m_range(range),
-      m_frame_base(), m_flags(), m_prologue_byte_size(0) {
+      m_type(type), m_mangled(mangled), m_trampoline_target(trampoline_target),
+      m_block(func_uid), m_range(range), m_frame_base(), m_flags(),
+      m_prologue_byte_size(0) {
   m_block.SetParentScope(this);
   assert(comp_unit != nullptr);
 }
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
@@ -99,6 +99,8 @@
   const char *GetMangledName(const DWARFUnit *cu,
                              bool substitute_name_allowed = true) const;
 
+  const char *GetTrampolineTargetName(const DWARFUnit *cu) const;
+
   const char *GetPubname(const DWARFUnit *cu) const;
 
   bool GetDIENamesAndRanges(
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -685,6 +685,10 @@
   return name;
 }
 
+const char *
+DWARFDebugInfoEntry::GetTrampolineTargetName(const DWARFUnit *cu) const {
+  return GetAttributeValueAsString(cu, DW_AT_trampoline, nullptr, true);
+}
 // GetPubname
 //
 // Get value the name for a DIE as it should appear for a .debug_pubnames or
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -28,6 +28,8 @@
   // Accessing information about a DIE
   const char *GetMangledName() const;
 
+  const char *GetTrampolineTargetName() const;
+
   const char *GetPubname() const;
 
   using DWARFBaseDIE::GetName;
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -203,6 +203,14 @@
     return nullptr;
 }
 
+
+const char *DWARFDIE::GetTrampolineTargetName() const {
+  if (IsValid())
+    return m_die->GetTrampolineTargetName(m_cu);
+  else
+    return nullptr;
+}
+
 const char *DWARFDIE::GetPubname() const {
   if (IsValid())
     return m_die->GetPubname(m_cu);
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2440,12 +2440,14 @@
 
     assert(func_type == nullptr || func_type != DIE_IS_BEING_PARSED);
 
+    auto *trampoline_target = die.GetTrampolineTargetName();
+
     const user_id_t func_user_id = die.GetID();
     func_sp =
         std::make_shared<Function>(&comp_unit,
                                    func_user_id, // UserID is the DIE offset
                                    func_user_id, func_name, func_type,
-                                   func_range); // first address range
+                                   func_range, trampoline_target); // first address range
 
     if (func_sp.get() != nullptr) {
       if (frame_base.IsValid())
Index: lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
===================================================================
--- lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
+++ lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
@@ -882,89 +882,10 @@
       ConstString trampoline_name =
           current_symbol->GetMangled().GetName(Mangled::ePreferMangled);
 
-      if (trampoline_name) {
-        const ModuleList &images = target_sp->GetImages();
-
-        SymbolContextList code_symbols;
-        images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode,
-                                          code_symbols);
-        size_t num_code_symbols = code_symbols.GetSize();
-
-        if (num_code_symbols > 0) {
-          for (uint32_t i = 0; i < num_code_symbols; i++) {
-            SymbolContext context;
-            AddressRange addr_range;
-            if (code_symbols.GetContextAtIndex(i, context)) {
-              context.GetAddressRange(eSymbolContextEverything, 0, false,
-                                      addr_range);
-              addresses.push_back(addr_range.GetBaseAddress());
-              if (log) {
-                addr_t load_addr =
-                    addr_range.GetBaseAddress().GetLoadAddress(target_sp.get());
-
-                LLDB_LOGF(log,
-                          "Found a trampoline target symbol at 0x%" PRIx64 ".",
-                          load_addr);
-              }
-            }
-          }
-        }
-
-        SymbolContextList reexported_symbols;
-        images.FindSymbolsWithNameAndType(
-            trampoline_name, eSymbolTypeReExported, reexported_symbols);
-        size_t num_reexported_symbols = reexported_symbols.GetSize();
-        if (num_reexported_symbols > 0) {
-          for (uint32_t i = 0; i < num_reexported_symbols; i++) {
-            SymbolContext context;
-            if (reexported_symbols.GetContextAtIndex(i, context)) {
-              if (context.symbol) {
-                Symbol *actual_symbol =
-                    context.symbol->ResolveReExportedSymbol(*target_sp.get());
-                if (actual_symbol) {
-                  const Address actual_symbol_addr =
-                      actual_symbol->GetAddress();
-                  if (actual_symbol_addr.IsValid()) {
-                    addresses.push_back(actual_symbol_addr);
-                    if (log) {
-                      lldb::addr_t load_addr =
-                          actual_symbol_addr.GetLoadAddress(target_sp.get());
-                      LLDB_LOGF(
-                          log,
-                          "Found a re-exported symbol: %s at 0x%" PRIx64 ".",
-                          actual_symbol->GetName().GetCString(), load_addr);
-                    }
-                  }
-                }
-              }
-            }
-          }
-        }
-
-        SymbolContextList indirect_symbols;
-        images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeResolver,
-                                          indirect_symbols);
-        size_t num_indirect_symbols = indirect_symbols.GetSize();
-        if (num_indirect_symbols > 0) {
-          for (uint32_t i = 0; i < num_indirect_symbols; i++) {
-            SymbolContext context;
-            AddressRange addr_range;
-            if (indirect_symbols.GetContextAtIndex(i, context)) {
-              context.GetAddressRange(eSymbolContextEverything, 0, false,
-                                      addr_range);
-              addresses.push_back(addr_range.GetBaseAddress());
-              if (log) {
-                addr_t load_addr =
-                    addr_range.GetBaseAddress().GetLoadAddress(target_sp.get());
-
-                LLDB_LOGF(log,
-                          "Found an indirect target symbol at 0x%" PRIx64 ".",
-                          load_addr);
-              }
-            }
-          }
-        }
-      }
+      if (trampoline_name)
+        thread_plan_sp =
+            ThreadPlanRunToAddress::MakeThreadPlanRunToAddressFromSymbol(
+                thread, trampoline_name, stop_others);
     } else if (current_symbol->GetType() == eSymbolTypeReExported) {
       // I am not sure we could ever end up stopped AT a re-exported symbol.
       // But just in case:
Index: lldb/source/Core/Module.cpp
===================================================================
--- lldb/source/Core/Module.cpp
+++ lldb/source/Core/Module.cpp
@@ -776,7 +776,14 @@
       if (!sc_list.GetContextAtIndex(i, sc))
         break;
 
+      bool is_trampoline = false;
+      if (Target::GetGlobalProperties().GetEnableTrampolineSupport() &&
+          sc.function) {
+        is_trampoline = !sc.function->IsTrampoline();
+      }
+
       bool keep_it =
+          !is_trampoline &&
           NameMatchesLookupInfo(sc.GetFunctionName(), sc.GetLanguage());
       if (keep_it)
         ++i;
Index: lldb/include/lldb/Target/ThreadPlanStepThrough.h
===================================================================
--- lldb/include/lldb/Target/ThreadPlanStepThrough.h
+++ lldb/include/lldb/Target/ThreadPlanStepThrough.h
@@ -44,6 +44,8 @@
                                         bool abort_other_plans,
                                         bool stop_others, Status &status);
 
+  lldb::ThreadPlanSP LookForFunctionWithTrampolineTarget();
+
   void ClearBackstopBreakpoint();
 
   lldb::ThreadPlanSP m_sub_plan_sp;
Index: lldb/include/lldb/Target/ThreadPlanRunToAddress.h
===================================================================
--- lldb/include/lldb/Target/ThreadPlanRunToAddress.h
+++ lldb/include/lldb/Target/ThreadPlanRunToAddress.h
@@ -45,6 +45,12 @@
 
   bool MischiefManaged() override;
 
+  /// Finds all the addresses the symbol name resolves to, and make a thread
+  /// plan that runs to them.
+  static lldb::ThreadPlanSP
+  MakeThreadPlanRunToAddressFromSymbol(Thread &thread, ConstString symbol_name,
+                                       bool stop_others);
+
 protected:
   bool DoPlanExplainsStop(Event *event_ptr) override;
 
Index: lldb/include/lldb/Target/Target.h
===================================================================
--- lldb/include/lldb/Target/Target.h
+++ lldb/include/lldb/Target/Target.h
@@ -250,6 +250,8 @@
 
   bool GetDebugUtilityExpression() const;
 
+  bool GetEnableTrampolineSupport() const;
+
 private:
   // Callbacks for m_launch_info.
   void Arg0ValueChangedCallback();
Index: lldb/include/lldb/Symbol/Function.h
===================================================================
--- lldb/include/lldb/Symbol/Function.h
+++ lldb/include/lldb/Symbol/Function.h
@@ -436,9 +436,12 @@
   ///
   /// \param[in] range
   ///     The section offset based address for this function.
+  /// \param[in] range
+  ///     The symbol name this function should trampoline to.
   Function(CompileUnit *comp_unit, lldb::user_id_t func_uid,
            lldb::user_id_t func_type_uid, const Mangled &mangled,
-           Type *func_type, const AddressRange &range);
+           Type *func_type, const AddressRange &range,
+           llvm::StringRef trampoline_target = {});
 
   /// Destructor.
   ~Function() override;
@@ -550,6 +553,14 @@
   ///     A type object pointer.
   Type *GetType();
 
+  llvm::StringRef GetTrampolineTargetName() const {
+    return m_trampoline_target;
+  }
+  
+  bool IsTrampoline() const {
+    return !m_trampoline_target.empty();
+  }
+
   /// Get const accessor for the type that describes the function return value
   /// type, and parameter types.
   ///
@@ -650,6 +661,8 @@
   /// information.
   Mangled m_mangled;
 
+  llvm::StringRef m_trampoline_target;
+
   /// All lexical blocks contained in this function.
   Block m_block;
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to