forked from OSchip/llvm-project
Handle stepping through a trampoline where the jump target is calculated a runtime - and so doesn't match
the name of the PLT entry. This solution assumes a naming convention agreed upon by us and the system folks, and isn't general. The general solution requires actually finding & calling the resolver function if it hasn't been called yet. That's more tricky. llvm-svn: 144981
This commit is contained in:
parent
6dc4c16417
commit
9683ff1211
|
@ -296,8 +296,15 @@ public:
|
|||
size_t
|
||||
FindSymbolsWithNameAndType (const ConstString &name,
|
||||
lldb::SymbolType symbol_type,
|
||||
SymbolContextList &sc_list);
|
||||
SymbolContextList &sc_list,
|
||||
bool append = false);
|
||||
|
||||
size_t
|
||||
FindSymbolsMatchingRegExAndType (const RegularExpression ®ex,
|
||||
lldb::SymbolType symbol_type,
|
||||
SymbolContextList &sc_list,
|
||||
bool append = false);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Find types by name.
|
||||
///
|
||||
|
|
|
@ -142,6 +142,31 @@ public:
|
|||
GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) = 0;
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Some dynamic loaders provide features where there are a group of symbols "equivalent to"
|
||||
/// a given symbol one of which will be chosen when the symbol is bound. If you want to
|
||||
/// set a breakpoint on one of these symbols, you really need to set it on all the
|
||||
/// equivalent symbols.
|
||||
///
|
||||
///
|
||||
/// @param[in] original_symbol
|
||||
/// The symbol for which we are finding equivalences.
|
||||
///
|
||||
/// @param[in] module_list
|
||||
/// The set of modules in which to search.
|
||||
///
|
||||
/// @param[out] equivalent_symbols
|
||||
/// The equivalent symbol list - any equivalent symbols found are appended to this list.
|
||||
///
|
||||
/// @return
|
||||
/// Number of equivalent symbols found.
|
||||
//------------------------------------------------------------------
|
||||
virtual size_t
|
||||
FindEquivalentSymbols (Symbol *original_symbol, ModuleList &module_list, SymbolContextList &equivalent_symbols)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Ask if it is ok to try and load or unload an shared library
|
||||
/// (image).
|
||||
|
|
|
@ -248,14 +248,35 @@ ModuleList::FindGlobalVariables (const RegularExpression& regex,
|
|||
size_t
|
||||
ModuleList::FindSymbolsWithNameAndType (const ConstString &name,
|
||||
SymbolType symbol_type,
|
||||
SymbolContextList &sc_list)
|
||||
SymbolContextList &sc_list,
|
||||
bool append)
|
||||
{
|
||||
Mutex::Locker locker(m_modules_mutex);
|
||||
sc_list.Clear();
|
||||
if (!append)
|
||||
sc_list.Clear();
|
||||
size_t initial_size = sc_list.GetSize();
|
||||
|
||||
collection::iterator pos, end = m_modules.end();
|
||||
for (pos = m_modules.begin(); pos != end; ++pos)
|
||||
(*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list);
|
||||
return sc_list.GetSize();
|
||||
return sc_list.GetSize() - initial_size;
|
||||
}
|
||||
|
||||
size_t
|
||||
ModuleList::FindSymbolsMatchingRegExAndType (const RegularExpression ®ex,
|
||||
lldb::SymbolType symbol_type,
|
||||
SymbolContextList &sc_list,
|
||||
bool append)
|
||||
{
|
||||
Mutex::Locker locker(m_modules_mutex);
|
||||
if (!append)
|
||||
sc_list.Clear();
|
||||
size_t initial_size = sc_list.GetSize();
|
||||
|
||||
collection::iterator pos, end = m_modules.end();
|
||||
for (pos = m_modules.begin(); pos != end; ++pos)
|
||||
(*pos)->FindSymbolsMatchingRegExAndType (regex, symbol_type, sc_list);
|
||||
return sc_list.GetSize() - initial_size;
|
||||
}
|
||||
|
||||
class ModuleMatches
|
||||
|
|
|
@ -1423,6 +1423,14 @@ 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)
|
||||
{
|
||||
|
@ -1442,46 +1450,75 @@ DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop
|
|||
{
|
||||
SymbolContextList target_symbols;
|
||||
ModuleList &images = thread.GetProcess().GetTarget().GetImages();
|
||||
|
||||
images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, 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 == 1)
|
||||
|
||||
size_t num_original_symbols = target_symbols.GetSize();
|
||||
bool orig_is_resolver = (current_symbol->GetFlags() & MACH_O_N_SYMBOL_RESOLVER) == MACH_O_N_SYMBOL_RESOLVER;
|
||||
|
||||
if (num_original_symbols > 0)
|
||||
{
|
||||
SymbolContext context;
|
||||
AddressRange addr_range;
|
||||
if (target_symbols.GetContextAtIndex(0, context))
|
||||
// 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++)
|
||||
{
|
||||
context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
|
||||
thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addr_range.GetBaseAddress(), stop_others));
|
||||
SymbolContext sc;
|
||||
target_symbols.GetContextAtIndex(i, sc);
|
||||
|
||||
Module* module_to_add = sc.symbol->CalculateSymbolContextModule();
|
||||
if (module_to_add)
|
||||
modules_to_search.AppendIfNeeded(static_cast<ModuleSP>(module_to_add));
|
||||
}
|
||||
else
|
||||
|
||||
// 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)
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("Couldn't resolve the symbol context.");
|
||||
target_symbols.Clear();
|
||||
|
||||
FindEquivalentSymbols (current_symbol, modules_to_search, target_symbols);
|
||||
}
|
||||
}
|
||||
else if (num_symbols > 1)
|
||||
{
|
||||
std::vector<lldb::addr_t> addresses;
|
||||
addresses.resize (num_symbols);
|
||||
for (uint32_t i = 0; i < num_symbols; i++)
|
||||
|
||||
// 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)
|
||||
{
|
||||
SymbolContext context;
|
||||
AddressRange addr_range;
|
||||
if (target_symbols.GetContextAtIndex(i, context))
|
||||
std::vector<lldb::addr_t> addresses;
|
||||
addresses.resize (num_symbols);
|
||||
for (uint32_t i = 0; i < num_symbols; i++)
|
||||
{
|
||||
context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
|
||||
lldb::addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(&thread.GetProcess().GetTarget());
|
||||
addresses[i] = load_addr;
|
||||
SymbolContext context;
|
||||
AddressRange addr_range;
|
||||
if (target_symbols.GetContextAtIndex(i, context))
|
||||
{
|
||||
context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
|
||||
lldb::addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(&thread.GetProcess().GetTarget());
|
||||
addresses[i] = 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.");
|
||||
}
|
||||
}
|
||||
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.");
|
||||
{
|
||||
log->Printf ("Found a resolver stub for: \"%s\" but could not find any symbols it resolves to.",
|
||||
trampoline_name.AsCString());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1503,6 +1540,29 @@ DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop
|
|||
return thread_plan_sp;
|
||||
}
|
||||
|
||||
size_t
|
||||
DynamicLoaderMacOSXDYLD::FindEquivalentSymbols (lldb_private::Symbol *original_symbol,
|
||||
lldb_private::ModuleList &images,
|
||||
lldb_private::SymbolContextList &equivalent_symbols)
|
||||
{
|
||||
const ConstString &trampoline_name = original_symbol->GetMangled().GetName(Mangled::ePreferMangled);
|
||||
if (!trampoline_name)
|
||||
return 0;
|
||||
|
||||
size_t initial_size = equivalent_symbols.GetSize();
|
||||
|
||||
static const char *resolver_name_regex = "(_gc|_non_gc|\\$[A-Z0-9]+)$";
|
||||
std::string equivalent_regex_buf("^");
|
||||
equivalent_regex_buf.append (trampoline_name.GetCString());
|
||||
equivalent_regex_buf.append (resolver_name_regex);
|
||||
|
||||
RegularExpression equivalent_name_regex (equivalent_regex_buf.c_str());
|
||||
const bool append = true;
|
||||
images.FindSymbolsMatchingRegExAndType (equivalent_name_regex, eSymbolTypeCode, equivalent_symbols, append);
|
||||
|
||||
return equivalent_symbols.GetSize() - initial_size;
|
||||
}
|
||||
|
||||
Error
|
||||
DynamicLoaderMacOSXDYLD::CanLoadImage ()
|
||||
{
|
||||
|
|
|
@ -66,6 +66,11 @@ public:
|
|||
GetStepThroughTrampolinePlan (lldb_private::Thread &thread,
|
||||
bool stop_others);
|
||||
|
||||
virtual size_t
|
||||
FindEquivalentSymbols (lldb_private::Symbol *original_symbol,
|
||||
lldb_private::ModuleList &module_list,
|
||||
lldb_private::SymbolContextList &equivalent_symbols);
|
||||
|
||||
virtual lldb_private::Error
|
||||
CanLoadImage ();
|
||||
|
||||
|
|
Loading…
Reference in New Issue