summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Breakpoint/Breakpoint.h21
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointLocation.h66
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointLocationList.h3
-rw-r--r--lldb/include/lldb/Target/Process.h14
-rw-r--r--lldb/include/lldb/Target/Target.h3
-rw-r--r--lldb/source/Breakpoint/Breakpoint.cpp11
-rw-r--r--lldb/source/Breakpoint/BreakpointLocation.cpp43
-rw-r--r--lldb/source/Breakpoint/BreakpointLocationList.cpp8
-rw-r--r--lldb/source/Breakpoint/BreakpointResolverName.cpp6
-rw-r--r--lldb/source/Core/Address.cpp22
-rw-r--r--lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp165
-rw-r--r--lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp4
-rw-r--r--lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp14
-rw-r--r--lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h3
-rw-r--r--lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp31
-rw-r--r--lldb/source/Target/LanguageRuntime.cpp3
-rw-r--r--lldb/source/Target/Process.cpp192
-rw-r--r--lldb/source/Target/Target.cpp18
18 files changed, 441 insertions, 186 deletions
diff --git a/lldb/include/lldb/Breakpoint/Breakpoint.h b/lldb/include/lldb/Breakpoint/Breakpoint.h
index e82d6eacf7a..749ff8d1a09 100644
--- a/lldb/include/lldb/Breakpoint/Breakpoint.h
+++ b/lldb/include/lldb/Breakpoint/Breakpoint.h
@@ -612,12 +612,30 @@ protected:
/// Only the Target can make a breakpoint, and it owns the breakpoint lifespans.
/// The constructor takes a filter and a resolver. Up in Target there are convenience
/// variants that make breakpoints for some common cases.
+ ///
+ /// @param[in] target
+ /// The target in which the breakpoint will be set.
+ ///
+ /// @param[in] filter_sp
+ /// Shared pointer to the search filter that restricts the search domain of the breakpoint.
+ ///
+ /// @param[in] resolver_sp
+ /// Shared pointer to the resolver object that will determine breakpoint matches.
+ ///
+ /// @param hardware
+ /// If true, request a hardware breakpoint to be used to implement the breakpoint locations.
+ ///
+ /// @param resolve_indirect_symbols
+ /// If true, and the address of a given breakpoint location in this breakpoint is set on an
+ /// indirect symbol (i.e. Symbol::IsIndirect returns true) then the actual breakpoint site will
+ /// be set on the target of the indirect symbol.
//------------------------------------------------------------------
// This is the generic constructor
Breakpoint(Target &target,
lldb::SearchFilterSP &filter_sp,
lldb::BreakpointResolverSP &resolver_sp,
- bool hardware);
+ bool hardware,
+ bool resolve_indirect_symbols = true);
friend class BreakpointLocation; // To call the following two when determining whether to stop.
@@ -643,6 +661,7 @@ private:
BreakpointOptions m_options; // Settable breakpoint options
BreakpointLocationList m_locations; // The list of locations currently found for this breakpoint.
std::string m_kind_description;
+ bool m_resolve_indirect_symbols;
void
SendBreakpointChangedEvent (lldb::BreakpointEventType eventKind);
diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocation.h b/lldb/include/lldb/Breakpoint/BreakpointLocation.h
index f4ba21a385f..ac4c28bb6e5 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointLocation.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointLocation.h
@@ -321,7 +321,59 @@ public:
//------------------------------------------------------------------
bool
InvokeCallback (StoppointCallbackContext *context);
+
+ //------------------------------------------------------------------
+ /// Returns whether we should resolve Indirect functions in setting the breakpoint site
+ /// for this location.
+ ///
+ /// @return
+ /// \b true if the breakpoint SITE for this location should be set on the
+ /// resolved location for Indirect functions.
+ //------------------------------------------------------------------
+ bool
+ ShouldResolveIndirectFunctions ()
+ {
+ return m_should_resolve_indirect_functions;
+ }
+ //------------------------------------------------------------------
+ /// Returns whether the address set in the breakpoint site for this location was found by resolving
+ /// an indirect symbol.
+ ///
+ /// @return
+ /// \b true or \b false as given in the description above.
+ //------------------------------------------------------------------
+ bool
+ IsIndirect ()
+ {
+ return m_is_indirect;
+ }
+
+ void
+ SetIsIndirect (bool is_indirect)
+ {
+ m_is_indirect = is_indirect;
+ }
+
+ //------------------------------------------------------------------
+ /// Returns whether the address set in the breakpoint location was re-routed to the target of a
+ /// re-exported symbol.
+ ///
+ /// @return
+ /// \b true or \b false as given in the description above.
+ //------------------------------------------------------------------
+ bool
+ IsReExported ()
+ {
+ return m_is_reexported;
+ }
+
+ void
+ SetIsReExported (bool is_reexported)
+ {
+ m_is_reexported = is_reexported;
+ }
+
protected:
friend class BreakpointLocationList;
friend class Process;
@@ -375,12 +427,16 @@ private:
Breakpoint &owner,
const Address &addr,
lldb::tid_t tid,
- bool hardware);
-
+ bool hardware,
+ bool check_for_resolver = true);
+
//------------------------------------------------------------------
// Data members:
//------------------------------------------------------------------
bool m_being_created;
+ bool m_should_resolve_indirect_functions;
+ bool m_is_reexported;
+ bool m_is_indirect;
Address m_address; ///< The address defining this location.
Breakpoint &m_owner; ///< The breakpoint that produced this object.
std::unique_ptr<BreakpointOptions> m_options_ap; ///< Breakpoint options pointer, NULL if we're using our breakpoint's options.
@@ -390,6 +446,12 @@ private:
size_t m_condition_hash; ///< For testing whether the condition source code changed.
void
+ SetShouldResolveIndirectFunctions (bool do_resolve)
+ {
+ m_should_resolve_indirect_functions = do_resolve;
+ }
+
+ void
SendBreakpointLocationChangedEvent (lldb::BreakpointEventType eventKind);
DISALLOW_COPY_AND_ASSIGN (BreakpointLocation);
diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocationList.h b/lldb/include/lldb/Breakpoint/BreakpointLocationList.h
index b25208659c7..ec34641b727 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointLocationList.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointLocationList.h
@@ -236,7 +236,7 @@ protected:
/// Returns breakpoint location id.
//------------------------------------------------------------------
lldb::BreakpointLocationSP
- Create (const Address &addr);
+ Create (const Address &addr, bool resolve_indirect_symbols);
void
StartRecordingNewLocations(BreakpointLocationCollection &new_locations);
@@ -246,6 +246,7 @@ protected:
lldb::BreakpointLocationSP
AddLocation (const Address &addr,
+ bool resolve_indirect_symbols,
bool *new_location = NULL);
bool
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index a1da6a39e35..fd1dd5ed4f2 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -2986,11 +2986,7 @@ public:
//------------------------------------------------------------------
virtual lldb::addr_t
- ResolveIndirectFunction(const Address *address, Error &error)
- {
- error.SetErrorStringWithFormat("error: %s does not support indirect functions in the debug process", GetPluginName().GetCString());
- return LLDB_INVALID_ADDRESS;
- }
+ ResolveIndirectFunction(const Address *address, Error &error);
virtual Error
GetMemoryRegionInfo (lldb::addr_t load_addr,
@@ -3670,6 +3666,12 @@ protected:
{
return IS_VALID_LLDB_HOST_THREAD(m_private_state_thread);
}
+
+ void
+ ForceNextEventDelivery()
+ {
+ m_force_next_event_delivery = true;
+ }
//------------------------------------------------------------------
// Type definitions
@@ -3744,7 +3746,9 @@ protected:
bool m_resume_requested; // If m_currently_handling_event or m_currently_handling_do_on_removals are true, Resume will only request a resume, using this flag to check.
bool m_finalize_called;
bool m_clear_thread_plans_on_stop;
+ bool m_force_next_event_delivery;
lldb::StateType m_last_broadcast_state; /// This helps with the Public event coalescing in ShouldBroadcastEvent.
+ std::map<lldb::addr_t,lldb::addr_t> m_resolved_indirect_addresses;
bool m_destroy_in_process;
enum {
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 084aa68424e..e20e72d9cb5 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -637,7 +637,8 @@ public:
CreateBreakpoint (lldb::SearchFilterSP &filter_sp,
lldb::BreakpointResolverSP &resolver_sp,
bool internal,
- bool request_hardware);
+ bool request_hardware,
+ bool resolve_indirect_symbols);
// Use this to create a watchpoint:
lldb::WatchpointSP
diff --git a/lldb/source/Breakpoint/Breakpoint.cpp b/lldb/source/Breakpoint/Breakpoint.cpp
index 32c0b1066f8..5ce064fc41a 100644
--- a/lldb/source/Breakpoint/Breakpoint.cpp
+++ b/lldb/source/Breakpoint/Breakpoint.cpp
@@ -45,14 +45,19 @@ Breakpoint::GetEventIdentifier ()
//----------------------------------------------------------------------
// Breakpoint constructor
//----------------------------------------------------------------------
-Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp, bool hardware) :
+Breakpoint::Breakpoint(Target &target,
+ SearchFilterSP &filter_sp,
+ BreakpointResolverSP &resolver_sp,
+ bool hardware,
+ bool resolve_indirect_symbols) :
m_being_created(true),
m_hardware(hardware),
m_target (target),
m_filter_sp (filter_sp),
m_resolver_sp (resolver_sp),
m_options (),
- m_locations (*this)
+ m_locations (*this),
+ m_resolve_indirect_symbols(resolve_indirect_symbols)
{
m_being_created = false;
}
@@ -87,7 +92,7 @@ Breakpoint::GetTarget () const
BreakpointLocationSP
Breakpoint::AddLocation (const Address &addr, bool *new_location)
{
- return m_locations.AddLocation (addr, new_location);
+ return m_locations.AddLocation (addr, m_resolve_indirect_symbols, new_location);
}
BreakpointLocationSP
diff --git a/lldb/source/Breakpoint/BreakpointLocation.cpp b/lldb/source/Breakpoint/BreakpointLocation.cpp
index 5009e862d84..2c75a11e978 100644
--- a/lldb/source/Breakpoint/BreakpointLocation.cpp
+++ b/lldb/source/Breakpoint/BreakpointLocation.cpp
@@ -39,16 +39,29 @@ BreakpointLocation::BreakpointLocation
Breakpoint &owner,
const Address &addr,
lldb::tid_t tid,
- bool hardware
+ bool hardware,
+ bool check_for_resolver
) :
StoppointLocation (loc_id, addr.GetOpcodeLoadAddress(&owner.GetTarget()), hardware),
m_being_created(true),
+ m_should_resolve_indirect_functions (false),
+ m_is_reexported (false),
+ m_is_indirect (false),
m_address (addr),
m_owner (owner),
m_options_ap (),
m_bp_site_sp (),
m_condition_mutex ()
{
+ if (check_for_resolver)
+ {
+ Symbol *symbol = m_address.CalculateSymbolContextSymbol();
+ if (symbol && symbol->IsIndirect())
+ {
+ SetShouldResolveIndirectFunctions (true);
+ }
+ }
+
SetThreadID (tid);
m_being_created = false;
}
@@ -545,7 +558,10 @@ BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
if (level == lldb::eDescriptionLevelFull || level == eDescriptionLevelInitial)
{
- s->PutCString("where = ");
+ if (IsReExported())
+ s->PutCString ("re-exported target = ");
+ else
+ s->PutCString("where = ");
sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false);
}
else
@@ -584,7 +600,10 @@ BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
if (sc.symbol)
{
s->EOL();
- s->Indent("symbol = ");
+ if (IsReExported())
+ s->Indent ("re-exported target = ");
+ else
+ s->Indent("symbol = ");
s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>"));
}
}
@@ -612,6 +631,24 @@ BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
else
m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
+
+ if (IsIndirect() && m_bp_site_sp)
+ {
+ Address resolved_address;
+ resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target);
+ Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol();
+ if (resolved_symbol)
+ {
+ if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)
+ s->Printf (", ");
+ else if (level == lldb::eDescriptionLevelVerbose)
+ {
+ s->EOL();
+ s->Indent();
+ }
+ s->Printf ("indirect target = %s", resolved_symbol->GetName().GetCString());
+ }
+ }
if (level == lldb::eDescriptionLevelVerbose)
{
diff --git a/lldb/source/Breakpoint/BreakpointLocationList.cpp b/lldb/source/Breakpoint/BreakpointLocationList.cpp
index 39b8d922585..917c776e75d 100644
--- a/lldb/source/Breakpoint/BreakpointLocationList.cpp
+++ b/lldb/source/Breakpoint/BreakpointLocationList.cpp
@@ -41,12 +41,12 @@ BreakpointLocationList::~BreakpointLocationList()
}
BreakpointLocationSP
-BreakpointLocationList::Create (const Address &addr)
+BreakpointLocationList::Create (const Address &addr, bool resolve_indirect_symbols)
{
Mutex::Locker locker (m_mutex);
// The location ID is just the size of the location list + 1
lldb::break_id_t bp_loc_id = ++m_next_id;
- BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr, LLDB_INVALID_THREAD_ID, m_owner.IsHardware()));
+ BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr, LLDB_INVALID_THREAD_ID, m_owner.IsHardware(), resolve_indirect_symbols));
m_locations.push_back (bp_loc_sp);
m_address_to_location[addr] = bp_loc_sp;
return bp_loc_sp;
@@ -247,7 +247,7 @@ BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level)
}
BreakpointLocationSP
-BreakpointLocationList::AddLocation (const Address &addr, bool *new_location)
+BreakpointLocationList::AddLocation (const Address &addr, bool resolve_indirect_symbols, bool *new_location)
{
Mutex::Locker locker (m_mutex);
@@ -256,7 +256,7 @@ BreakpointLocationList::AddLocation (const Address &addr, bool *new_location)
BreakpointLocationSP bp_loc_sp (FindByAddress(addr));
if (!bp_loc_sp)
{
- bp_loc_sp = Create (addr);
+ bp_loc_sp = Create (addr, resolve_indirect_symbols);
if (bp_loc_sp)
{
bp_loc_sp->ResolveBreakpointSite();
diff --git a/lldb/source/Breakpoint/BreakpointResolverName.cpp b/lldb/source/Breakpoint/BreakpointResolverName.cpp
index c82dd5ee050..cf5d89cb7a8 100644
--- a/lldb/source/Breakpoint/BreakpointResolverName.cpp
+++ b/lldb/source/Breakpoint/BreakpointResolverName.cpp
@@ -272,6 +272,8 @@ BreakpointResolverName::SearchCallback
{
if (func_list.GetContextAtIndex(i, sc))
{
+ bool is_reexported = false;
+
if (sc.block && sc.block->GetInlinedFunctionInfo())
{
if (!sc.block->GetStartAddress(break_addr))
@@ -293,7 +295,10 @@ BreakpointResolverName::SearchCallback
{
const Symbol *actual_symbol = sc.symbol->ResolveReExportedSymbol(m_breakpoint->GetTarget());
if (actual_symbol)
+ {
+ is_reexported = true;
break_addr = actual_symbol->GetAddress();
+ }
}
else
{
@@ -313,6 +318,7 @@ BreakpointResolverName::SearchCallback
if (filter.AddressPasses(break_addr))
{
BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location));
+ bp_loc_sp->SetIsReExported(is_reexported);
if (bp_loc_sp && new_location && !m_breakpoint->IsInternal())
{
if (log)
diff --git a/lldb/source/Core/Address.cpp b/lldb/source/Core/Address.cpp
index 3b97253d040..5ac2bcce70f 100644
--- a/lldb/source/Core/Address.cpp
+++ b/lldb/source/Core/Address.cpp
@@ -328,15 +328,27 @@ Address::GetLoadAddress (Target *target) const
addr_t
Address::GetCallableLoadAddress (Target *target, bool is_indirect) const
{
- if (is_indirect && target) {
+ addr_t code_addr = LLDB_INVALID_ADDRESS;
+
+ if (is_indirect && target)
+ {
ProcessSP processSP = target->GetProcessSP();
Error error;
if (processSP.get())
- return processSP->ResolveIndirectFunction(this, error);
+ {
+ code_addr = processSP->ResolveIndirectFunction(this, error);
+ if (!error.Success())
+ code_addr = LLDB_INVALID_ADDRESS;
+ }
}
-
- addr_t code_addr = GetLoadAddress (target);
-
+ else
+ {
+ code_addr = GetLoadAddress (target);
+ }
+
+ if (code_addr == LLDB_INVALID_ADDRESS)
+ return code_addr;
+
if (target)
return target->GetCallableLoadAddress (code_addr, GetAddressClass());
return code_addr;
diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
index f71b9cac3a3..43f6ce9e6a1 100644
--- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
@@ -1596,14 +1596,6 @@ DynamicLoaderMacOSXDYLD::PrivateProcessStateChanged (Process *process, StateType
}
}
-// This bit in the n_desc field of the mach file means that this is a
-// stub that runs arbitrary code to determine the trampoline target.
-// We've established a naming convention with the CoreOS folks for the
-// equivalent symbols they will use for this (which the objc guys didn't follow...)
-// For now we'll just look for all symbols matching that naming convention...
-
-#define MACH_O_N_SYMBOL_RESOLVER 0x100
-
ThreadPlanSP
DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
{
@@ -1612,104 +1604,123 @@ DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop
const SymbolContext &current_context = current_frame->GetSymbolContext(eSymbolContextSymbol);
Symbol *current_symbol = current_context.symbol;
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+ TargetSP target_sp (thread.CalculateTarget());
if (current_symbol != NULL)
{
+ std::vector<Address> addresses;
+
if (current_symbol->IsTrampoline())
{
const ConstString &trampoline_name = current_symbol->GetMangled().GetName(Mangled::ePreferMangled);
if (trampoline_name)
{
- SymbolContextList target_symbols;
- TargetSP target_sp (thread.CalculateTarget());
const ModuleList &images = target_sp->GetImages();
- images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols);
-
- size_t num_original_symbols = target_symbols.GetSize();
- // FIXME: The resolver symbol is only valid in object files. In binaries it is reused for the
- // shared library slot number. So we'll have to look this up in the dyld info.
- // For now, just turn this off.
-
- // bool orig_is_resolver = (current_symbol->GetFlags() & MACH_O_N_SYMBOL_RESOLVER) == MACH_O_N_SYMBOL_RESOLVER;
- // FIXME: Actually that isn't true, the N_SYMBOL_RESOLVER bit is only valid in .o files. You can't use
- // the symbol flags to tell whether something is a symbol resolver in a linked image.
- bool orig_is_resolver = false;
+ SymbolContextList code_symbols;
+ images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, code_symbols);
+ size_t num_code_symbols = code_symbols.GetSize();
- if (num_original_symbols > 0)
+ if (num_code_symbols > 0)
{
- // We found symbols that look like they are the targets to our symbol. Now look through the
- // modules containing our symbols to see if there are any for our symbol.
-
- ModuleList modules_to_search;
-
- for (size_t i = 0; i < num_original_symbols; i++)
- {
- SymbolContext sc;
- target_symbols.GetContextAtIndex(i, sc);
-
- ModuleSP module_sp (sc.symbol->CalculateSymbolContextModule());
- if (module_sp)
- modules_to_search.AppendIfNeeded(module_sp);
- }
-
- // If the original stub symbol is a resolver, then we don't want to break on the symbol with the
- // original name, but instead on all the symbols it could resolve to since otherwise we would stop
- // in the middle of the resolution...
- // Note that the stub is not of the resolver type it will point to the equivalent symbol,
- // not the original name, so in that case we don't need to do anything.
-
- if (orig_is_resolver)
- {
- target_symbols.Clear();
-
- FindEquivalentSymbols (current_symbol, modules_to_search, target_symbols);
- }
-
- // FIXME - Make the Run to Address take multiple addresses, and
- // run to any of them.
- uint32_t num_symbols = target_symbols.GetSize();
- if (num_symbols > 0)
+ for (uint32_t i = 0; i < num_code_symbols; i++)
{
- std::vector<lldb::addr_t> addresses;
- addresses.resize (num_symbols);
- for (uint32_t i = 0; i < num_symbols; i++)
+ SymbolContext context;
+ AddressRange addr_range;
+ if (code_symbols.GetContextAtIndex(i, context))
{
- SymbolContext context;
- AddressRange addr_range;
- if (target_symbols.GetContextAtIndex(i, context))
+ context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
+ addresses.push_back(addr_range.GetBaseAddress());
+ if (log)
{
- context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
- lldb::addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(target_sp.get());
- addresses[i] = load_addr;
+ addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(target_sp.get());
+
+ log->Printf ("Found a trampoline target symbol at 0x%" PRIx64 ".", load_addr);
}
}
- if (addresses.size() > 0)
- thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addresses, stop_others));
- else
- {
- if (log)
- log->Printf ("Couldn't resolve the symbol contexts.");
- }
}
- else
+ }
+
+ 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++)
{
- if (log)
+ SymbolContext context;
+ if (reexported_symbols.GetContextAtIndex(i, context))
{
- log->Printf ("Found a resolver stub for: \"%s\" but could not find any symbols it resolves to.",
- trampoline_name.AsCString());
+ if (context.symbol)
+ {
+ Symbol *actual_symbol = context.symbol->ResolveReExportedSymbol(*target_sp.get());
+ if (actual_symbol)
+ {
+ if (actual_symbol->GetAddress().IsValid())
+ {
+ addresses.push_back(actual_symbol->GetAddress());
+ if (log)
+ {
+ lldb::addr_t load_addr = actual_symbol->GetAddress().GetLoadAddress(target_sp.get());
+ log->Printf ("Found a re-exported symbol: %s at 0x%" PRIx64 ".",
+ actual_symbol->GetName().GetCString(), load_addr);
+ }
+ }
+ }
+ }
}
}
}
- else
+ }
+ }
+ 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:
+
+ const Symbol *actual_symbol = current_symbol->ResolveReExportedSymbol(*(target_sp.get()));
+ if (actual_symbol)
+ {
+ Address target_addr(actual_symbol->GetAddress());
+ if (target_addr.IsValid())
{
if (log)
+ log->Printf ("Found a re-exported symbol: %s pointing to: %s at 0x%" PRIx64 ".",
+ current_symbol->GetName().GetCString(),
+ actual_symbol->GetName().GetCString(),
+ target_addr.GetLoadAddress(target_sp.get()));
+ addresses.push_back (target_addr.GetLoadAddress(target_sp.get()));
+
+ }
+ }
+ }
+
+ if (addresses.size() > 0)
+ {
+ // 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())
+ {
+ Error error;
+ addr_t resolved_addr = thread.GetProcess()->ResolveIndirectFunction(&symbol->GetAddress(), error);
+ if (error.Success())
{
- log->Printf ("Could not find symbol for trampoline target: \"%s\"", trampoline_name.AsCString());
+ load_addrs.push_back(resolved_addr);
+ if (log)
+ log->Printf("ResolveIndirectFunction found resolved target for %s at 0x%" PRIx64 ".",
+ symbol->GetName().GetCString(), resolved_addr);
}
}
+ else
+ {
+ load_addrs.push_back(address.GetLoadAddress(target_sp.get()));
+ }
+
}
+ thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, load_addrs, stop_others));
}
}
else
@@ -1732,7 +1743,7 @@ DynamicLoaderMacOSXDYLD::FindEquivalentSymbols (lldb_private::Symbol *original_s
size_t initial_size = equivalent_symbols.GetSize();
- static const char *resolver_name_regex = "(_gc|_non_gc|\\$[A-Z0-9]+)$";
+ static const char *resolver_name_regex = "(_gc|_non_gc|\\$[A-Za-z0-9\\$]+)$";
std::string equivalent_regex_buf("^");
equivalent_regex_buf.append (trampoline_name.GetCString());
equivalent_regex_buf.append (resolver_name_regex);
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index 878f15645ec..9781dcb093a 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -403,7 +403,9 @@ ItaniumABILanguageRuntime::CreateExceptionBreakpoint (bool catch_bp,
FileSpecList filter_modules;
BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions);
SearchFilterSP filter_sp (CreateExceptionSearchFilter ());
- return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal, false);
+ const bool hardware = false;
+ const bool resolve_indirect_functions = false;
+ return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal, hardware, resolve_indirect_functions);
}
void
diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
index a5bd9b510a4..62394623c59 100644
--- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
+++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
@@ -632,20 +632,6 @@ ProcessPOSIX::DoDeallocateMemory(lldb::addr_t addr)
return error;
}
-addr_t
-ProcessPOSIX::ResolveIndirectFunction(const Address *address, Error &error)
-{
- addr_t function_addr = LLDB_INVALID_ADDRESS;
- if (address == NULL) {
- error.SetErrorStringWithFormat("unable to determine direct function call for NULL address");
- } else if (!InferiorCall(this, address, function_addr)) {
- function_addr = LLDB_INVALID_ADDRESS;
- error.SetErrorStringWithFormat("unable to determine direct function call for indirect function %s",
- address->CalculateSymbolContextSymbol()->GetName().AsCString());
- }
- return function_addr;
-}
-
size_t
ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
{
diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h
index beacb0186c6..7f705d33fe6 100644
--- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h
+++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h
@@ -104,9 +104,6 @@ public:
virtual lldb_private::Error
DoDeallocateMemory(lldb::addr_t ptr);
- virtual lldb::addr_t
- ResolveIndirectFunction(const lldb_private::Address *address, lldb_private::Error &error);
-
virtual size_t
GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site);
diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index 6d1b04f7f1a..1d5d19fad25 100644
--- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -34,9 +34,16 @@
using namespace lldb;
using namespace lldb_private;
-bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
- addr_t addr, addr_t length, unsigned prot,
- unsigned flags, addr_t fd, addr_t offset) {
+bool
+lldb_private::InferiorCallMmap (Process *process,
+ addr_t &allocated_addr,
+ addr_t addr,
+ addr_t length,
+ unsigned prot,
+ unsigned flags,
+ addr_t fd,
+ addr_t offset)
+{
Thread *thread = process->GetThreadList().GetSelectedThread().get();
if (thread == NULL)
return false;
@@ -139,8 +146,11 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
return false;
}
-bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
- addr_t length) {
+bool
+lldb_private::InferiorCallMunmap (Process *process,
+ addr_t addr,
+ addr_t length)
+{
Thread *thread = process->GetThreadList().GetSelectedThread().get();
if (thread == NULL)
return false;
@@ -209,7 +219,14 @@ bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
return false;
}
-bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t &returned_func) {
+// FIXME: This has nothing to do with Posix, it is just a convenience function that calls a
+// function of the form "void * (*)(void)". We should find a better place to put this.
+
+bool
+lldb_private::InferiorCall (Process *process,
+ const Address *address,
+ addr_t &returned_func)
+{
Thread *thread = process->GetThreadList().GetSelectedThread().get();
if (thread == NULL || address == NULL)
return false;
@@ -233,7 +250,7 @@ bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t
lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
if (call_plan_sp)
{
- StreamFile error_strm;
+ StreamString error_strm;
// This plan is a utility plan, so set it to discard itself when done.
call_plan_sp->SetIsMasterPlan (true);
call_plan_sp->SetOkayToDiscard(true);
diff --git a/lldb/source/Target/LanguageRuntime.cpp b/lldb/source/Target/LanguageRuntime.cpp
index 2fdc2539d08..a2b7f1d6ae8 100644
--- a/lldb/source/Target/LanguageRuntime.cpp
+++ b/lldb/source/Target/LanguageRuntime.cpp
@@ -269,7 +269,8 @@ LanguageRuntime::CreateExceptionBreakpoint (Target &target,
BreakpointResolverSP resolver_sp(new ExceptionBreakpointResolver(language, catch_bp, throw_bp));
SearchFilterSP filter_sp(new ExceptionSearchFilter(target.shared_from_this(), language));
bool hardware = false;
- BreakpointSP exc_breakpt_sp (target.CreateBreakpoint (filter_sp, resolver_sp, is_internal, hardware));
+ bool resolve_indirect_functions = false;
+ BreakpointSP exc_breakpt_sp (target.CreateBreakpoint (filter_sp, resolver_sp, is_internal, hardware, resolve_indirect_functions));
if (is_internal)
exc_breakpt_sp->SetBreakpointKind("exception");
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 8b1aba634b7..a5ef629e5eb 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -21,6 +21,7 @@
#include "lldb/Core/InputReader.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
+#include "lldb/Symbol/Symbol.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Expression/ClangUserExpression.h"
@@ -41,6 +42,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanBase.h"
+#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
#ifndef LLDB_DISABLE_POSIX
#include <spawn.h>
@@ -1052,6 +1054,7 @@ Process::Process(Target &target, Listener &listener) :
m_currently_handling_event(false),
m_finalize_called(false),
m_clear_thread_plans_on_stop (false),
+ m_force_next_event_delivery(false),
m_last_broadcast_state (eStateInvalid),
m_destroy_in_process (false),
m_can_jit(eCanJITDontKnow)
@@ -2143,7 +2146,60 @@ Process::EnableBreakpointSiteByID (lldb::user_id_t break_id)
lldb::break_id_t
Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardware)
{
- const addr_t load_addr = owner->GetAddress().GetOpcodeLoadAddress (&m_target);
+ addr_t load_addr = LLDB_INVALID_ADDRESS;
+
+ bool show_error = true;
+ switch (GetState())
+ {
+ case eStateInvalid:
+ case eStateUnloaded:
+ case eStateConnected:
+ case eStateAttaching:
+ case eStateLaunching:
+ case eStateDetached:
+ case eStateExited:
+ show_error = false;
+ break;
+
+ case eStateStopped:
+ case eStateRunning:
+ case eStateStepping:
+ case eStateCrashed:
+ case eStateSuspended:
+ show_error = IsAlive();
+ break;
+ }
+
+ // Reset the IsIndirect flag here, in case the location changes from
+ // pointing to a indirect symbol to a regular symbol.
+ owner->SetIsIndirect (false);
+
+ if (owner->ShouldResolveIndirectFunctions())
+ {
+ Symbol *symbol = owner->GetAddress().CalculateSymbolContextSymbol();
+ if (symbol && symbol->IsIndirect())
+ {
+ Error error;
+ load_addr = ResolveIndirectFunction (&symbol->GetAddress(), error);
+ if (!error.Success() && show_error)
+ {
+ m_target.GetDebugger().GetErrorFile().Printf ("warning: failed to resolve indirect function at 0x%" PRIx64 " for breakpoint %i.%i: %s\n",
+ symbol->GetAddress().GetLoadAddress(&m_target),
+ owner->GetBreakpoint().GetID(),
+ owner->GetID(),
+ error.AsCString() ? error.AsCString() : "unkown error");
+ return LLDB_INVALID_BREAK_ID;
+ }
+ Address resolved_address(load_addr);
+ load_addr = resolved_address.GetOpcodeLoadAddress (&m_target);
+ owner->SetIsIndirect(true);
+ }
+ else
+ load_addr = owner->GetAddress().GetOpcodeLoadAddress (&m_target);
+ }
+ else
+ load_addr = owner->GetAddress().GetOpcodeLoadAddress (&m_target);
+
if (load_addr != LLDB_INVALID_ADDRESS)
{
BreakpointSiteSP bp_site_sp;
@@ -2172,28 +2228,6 @@ Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardw
}
else
{
- bool show_error = true;
- switch (GetState())
- {
- case eStateInvalid:
- case eStateUnloaded:
- case eStateConnected:
- case eStateAttaching:
- case eStateLaunching:
- case eStateDetached:
- case eStateExited:
- show_error = false;
- break;
-
- case eStateStopped:
- case eStateRunning:
- case eStateStepping:
- case eStateCrashed:
- case eStateSuspended:
- show_error = IsAlive();
- break;
- }
-
if (show_error)
{
// Report error for setting breakpoint...
@@ -3804,33 +3838,38 @@ Process::ShouldBroadcastEvent (Event *event_ptr)
// stopped -> running: Report except when there is one or more no votes
// and no yes votes.
SynchronouslyNotifyStateChanged (state);
- switch (m_last_broadcast_state)
+ if (m_force_next_event_delivery)
+ return_value = true;
+ else
{
- case eStateRunning:
- case eStateStepping:
- // We always suppress multiple runnings with no PUBLIC stop in between.
- return_value = false;
- break;
- default:
- // TODO: make this work correctly. For now always report
- // run if we aren't running so we don't miss any runnning
- // events. If I run the lldb/test/thread/a.out file and
- // break at main.cpp:58, run and hit the breakpoints on
- // multiple threads, then somehow during the stepping over
- // of all breakpoints no run gets reported.
-
- // This is a transition from stop to run.
- switch (m_thread_list.ShouldReportRun (event_ptr))
- {
- case eVoteYes:
- case eVoteNoOpinion:
- return_value = true;
- break;
- case eVoteNo:
- return_value = false;
- break;
- }
- break;
+ switch (m_last_broadcast_state)
+ {
+ case eStateRunning:
+ case eStateStepping:
+ // We always suppress multiple runnings with no PUBLIC stop in between.
+ return_value = false;
+ break;
+ default:
+ // TODO: make this work correctly. For now always report
+ // run if we aren't running so we don't miss any runnning
+ // events. If I run the lldb/test/thread/a.out file and
+ // break at main.cpp:58, run and hit the breakpoints on
+ // multiple threads, then somehow during the stepping over
+ // of all breakpoints no run gets reported.
+
+ // This is a transition from stop to run.
+ switch (m_thread_list.ShouldReportRun (event_ptr))
+ {
+ case eVoteYes:
+ case eVoteNoOpinion:
+ return_value = true;
+ break;
+ case eVoteNo:
+ return_value = false;
+ break;
+ }
+ break;
+ }
}
break;
case eStateStopped:
@@ -3903,6 +3942,9 @@ Process::ShouldBroadcastEvent (Event *event_ptr)
break;
}
+ // Forcing the next event delivery is a one shot deal. So reset it here.
+ m_force_next_event_delivery = false;
+
// We do some coalescing of events (for instance two consecutive running events get coalesced.)
// But we only coalesce against events we actually broadcast. So we use m_last_broadcast_state
// to track that. NB - you can't use "m_public_state.GetValue()" for that purpose, as was originally done,
@@ -4984,6 +5026,22 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
final_timeout.OffsetWithMicroSeconds(timeout_usec);
}
+ // This isn't going to work if there are unfetched events on the queue.
+ // Are there cases where we might want to run the remaining events here, and then try to
+ // call the function? That's probably being too tricky for our own good.
+
+ Event *other_events = listener.PeekAtNextEvent();
+ if (other_events != NULL)
+ {
+ errors.Printf("Calling RunThreadPlan with pending events on the queue.");
+ return eExecutionSetupError;
+ }
+
+ // We also need to make sure that the next event is delivered. We might be calling a function as part of
+ // a thread plan, in which case the last delivered event could be the running event, and we don't want
+ // event coalescing to cause us to lose OUR running event...
+ ForceNextEventDelivery();
+
// This while loop must exit out the bottom, there's cleanup that we need to do when we are done.
// So don't call return anywhere within it.
@@ -5772,3 +5830,39 @@ Process::DidExec ()
target.DidExec();
}
+addr_t
+Process::ResolveIndirectFunction(const Address *address, Error &error)
+{
+ if (address == nullptr)
+ {
+ Symbol *symbol = address->CalculateSymbolContextSymbol();
+ error.SetErrorStringWithFormat("unable to determine direct function call for indirect function %s",
+ symbol ? symbol->GetName().AsCString() : "<UNKNOWN>");
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ addr_t function_addr = LLDB_INVALID_ADDRESS;
+
+ addr_t addr = address->GetLoadAddress(&GetTarget());
+ std::map<addr_t,addr_t>::const_iterator iter = m_resolved_indirect_addresses.find(addr);
+ if (iter != m_resolved_indirect_addresses.end())
+ {
+ function_addr = (*iter).second;
+ }
+ else
+ {
+ if (!InferiorCall(this, address, function_addr))
+ {
+ Symbol *symbol = address->CalculateSymbolContextSymbol();
+ error.SetErrorStringWithFormat ("Unable to call resolver for indirect function %s",
+ symbol ? symbol->GetName().AsCString() : "<UNKNOWN>");
+ function_addr = LLDB_INVALID_ADDRESS;
+ }
+ else
+ {
+ m_resolved_indirect_addresses.insert(std::pair<addr_t, addr_t>(addr, function_addr));
+ }
+ }
+ return function_addr;
+}
+
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index a0435d137fb..a34d53e88f8 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -250,7 +250,7 @@ Target::CreateSourceRegexBreakpoint (const FileSpecList *containingModules,
{
SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList (containingModules, source_file_spec_list));
BreakpointResolverSP resolver_sp(new BreakpointResolverFileRegex (NULL, source_regex));
- return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
+ return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
@@ -304,7 +304,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
line_no,
check_inlines,
skip_prologue));
- return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
+ return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
@@ -331,7 +331,7 @@ Target::CreateBreakpoint (Address &addr, bool internal, bool hardware)
{
SearchFilterSP filter_sp(new SearchFilterForNonModuleSpecificSearches (shared_from_this()));
BreakpointResolverSP resolver_sp (new BreakpointResolverAddress (NULL, addr));
- return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
+ return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, false);
}
BreakpointSP
@@ -356,7 +356,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
func_name_type_mask,
Breakpoint::Exact,
skip_prologue));
- bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
+ bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
return bp_sp;
}
@@ -383,7 +383,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
func_names,
func_name_type_mask,
skip_prologue));
- bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
+ bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
return bp_sp;
}
@@ -411,7 +411,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
num_names,
func_name_type_mask,
skip_prologue));
- bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
+ bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
return bp_sp;
}
@@ -489,7 +489,7 @@ Target::CreateFuncRegexBreakpoint (const FileSpecList *containingModules,
func_regex,
skip_prologue == eLazyBoolCalculate ? GetSkipPrologue() : skip_prologue));
- return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
+ return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
lldb::BreakpointSP
@@ -499,12 +499,12 @@ Target::CreateExceptionBreakpoint (enum lldb::LanguageType language, bool catch_
}
BreakpointSP
-Target::CreateBreakpoint (SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp, bool internal, bool request_hardware)
+Target::CreateBreakpoint (SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp, bool internal, bool request_hardware, bool resolve_indirect_symbols)
{
BreakpointSP bp_sp;
if (filter_sp && resolver_sp)
{
- bp_sp.reset(new Breakpoint (*this, filter_sp, resolver_sp, request_hardware));
+ bp_sp.reset(new Breakpoint (*this, filter_sp, resolver_sp, request_hardware, resolve_indirect_symbols));
resolver_sp->SetBreakpoint (bp_sp.get());
if (internal)
OpenPOWER on IntegriCloud