diff options
| author | Jim Ingham <jingham@apple.com> | 2011-11-19 00:19:25 +0000 |
|---|---|---|
| committer | Jim Ingham <jingham@apple.com> | 2011-11-19 00:19:25 +0000 |
| commit | 9683ff1211c1a00c812dfb6537421f3e99cd77cb (patch) | |
| tree | ad4966613a9f826abe1b85e746344d5032a6ffb3 | |
| parent | 6dc4c16417f13295f638a8360fd96237130140df (diff) | |
| download | bcm5719-llvm-9683ff1211c1a00c812dfb6537421f3e99cd77cb.tar.gz bcm5719-llvm-9683ff1211c1a00c812dfb6537421f3e99cd77cb.zip | |
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
| -rw-r--r-- | lldb/include/lldb/Core/ModuleList.h | 9 | ||||
| -rw-r--r-- | lldb/include/lldb/Target/DynamicLoader.h | 25 | ||||
| -rw-r--r-- | lldb/source/Core/ModuleList.cpp | 27 | ||||
| -rw-r--r-- | lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp | 114 | ||||
| -rw-r--r-- | lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h | 5 |
5 files changed, 149 insertions, 31 deletions
diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h index 4f9576aa243..213208ded89 100644 --- a/lldb/include/lldb/Core/ModuleList.h +++ b/lldb/include/lldb/Core/ModuleList.h @@ -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. /// diff --git a/lldb/include/lldb/Target/DynamicLoader.h b/lldb/include/lldb/Target/DynamicLoader.h index 0dc85920f31..097cc3251b1 100644 --- a/lldb/include/lldb/Target/DynamicLoader.h +++ b/lldb/include/lldb/Target/DynamicLoader.h @@ -143,6 +143,31 @@ public: //------------------------------------------------------------------ + /// 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). /// diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index d5cf9ab4566..9799f924575 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -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 diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp index b7790337b03..acdc42f4cc3 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp @@ -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++) + { + 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 { - context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range); - lldb::addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(&thread.GetProcess().GetTarget()); - addresses[i] = load_addr; + 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 () { diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h index c6f55ffc674..ce11eed85c9 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h @@ -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 (); |

