summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
authorJim Ingham <jingham@apple.com>2014-01-10 23:46:59 +0000
committerJim Ingham <jingham@apple.com>2014-01-10 23:46:59 +0000
commit1460e4bf0e722086d76de65ef74e76ec54a5534b (patch)
treee7e8ee24d300abecbf45a972b88a0bf9002e6d63 /lldb/source
parent87c2b0400d0675ad68d7e3d5b4e7e81508ba3c51 (diff)
downloadbcm5719-llvm-1460e4bf0e722086d76de65ef74e76ec54a5534b.tar.gz
bcm5719-llvm-1460e4bf0e722086d76de65ef74e76ec54a5534b.zip
Get the breakpoint setting, and the Mac OS X DYLD trampolines and expression evaluator to handle Indirect
symbols correctly. There were a couple of pieces to this. 1) When a breakpoint location finds itself pointing to an Indirect symbol, when the site for it is created it needs to resolve the symbol and actually set the site at its target. 2) Not all breakpoints want to do this (i.e. a straight address breakpoint should always set itself on the specified address, so somem machinery was needed to specify that. 3) I added some info to the break list output for indirect symbols so you could see what was happening. Also I made it clear when we re-route through re-exported symbols. 4) I moved ResolveIndirectFunction from ProcessPosix to Process since it works the exact same way on Mac OS X and the other posix systems. If we find a platform that doesn't do it this way, they can override the call in Process. 5) Fixed one bug in RunThreadPlan, if you were trying to run a thread plan after a "running" event had been broadcast, the event coalescing would cause you to miss the ThreadPlan running event. So I added a way to override the coalescing. 6) Made DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan handle Indirect & Re-exported symbols. <rdar://problem/15280639> llvm-svn: 198976
Diffstat (limited to 'lldb/source')
-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
13 files changed, 344 insertions, 176 deletions
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