forked from OSchip/llvm-project
ReExported symbols can point to a library that doesn't actually
contain the symbol, but just reexports wholesale from another library. Handle this case. <rdar://problem/16977589> llvm-svn: 209270
This commit is contained in:
parent
56f9c191e1
commit
fbe0b9abf9
|
@ -471,7 +471,7 @@ public:
|
|||
/// Gets the symbol file spec list for this object file.
|
||||
///
|
||||
/// If the object file format contains a debug symbol file link,
|
||||
/// the values will be return in the FileSpecList.
|
||||
/// the values will be returned in the FileSpecList.
|
||||
///
|
||||
/// @return
|
||||
/// Returns filespeclist.
|
||||
|
@ -482,6 +482,21 @@ public:
|
|||
return FileSpecList();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Gets the file spec list of libraries re-exported by this object file.
|
||||
///
|
||||
/// If the object file format has the notion of one library re-exporting the symbols from another,
|
||||
/// the re-exported libraries will be returned in the FileSpecList.
|
||||
///
|
||||
/// @return
|
||||
/// Returns filespeclist.
|
||||
//------------------------------------------------------------------
|
||||
virtual lldb_private::FileSpecList
|
||||
GetReExportedLibraries ()
|
||||
{
|
||||
return FileSpecList();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Sets the load address for an entire module, assuming a rigid
|
||||
/// slide of sections, if possible in the implementation.
|
||||
|
|
|
@ -303,7 +303,15 @@ public:
|
|||
Stream &strm);
|
||||
|
||||
protected:
|
||||
|
||||
// This is the internal guts of ResolveReExportedSymbol, it assumes reexport_name is not null, and that module_spec
|
||||
// is valid. We track the modules we've already seen to make sure we don't get caught in a cycle.
|
||||
|
||||
Symbol *
|
||||
ResolveReExportedSymbolInModuleSpec (Target &target,
|
||||
ConstString &reexport_name,
|
||||
lldb_private::ModuleSpec &module_spec,
|
||||
lldb_private::ModuleList &seen_modules);
|
||||
|
||||
uint32_t m_uid; // User ID (usually the original symbol table index)
|
||||
uint16_t m_type_data; // data specific to m_type
|
||||
uint16_t m_type_data_resolved:1, // True if the data in m_type_data has already been calculated
|
||||
|
|
|
@ -1838,6 +1838,11 @@ ObjectFileMachO::ParseSymtab ()
|
|||
// Strip the path if there is @rpath, @executanble, etc so we just use the basename
|
||||
if (path[0] == '@')
|
||||
file_spec.GetDirectory().Clear();
|
||||
|
||||
if (lc.cmd == LC_REEXPORT_DYLIB)
|
||||
{
|
||||
m_reexported_dylibs.AppendIfUnique(file_spec);
|
||||
}
|
||||
|
||||
dylib_files.Append(file_spec);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "lldb/Utility/SafeMachO.h"
|
||||
|
||||
#include "lldb/Core/Address.h"
|
||||
#include "lldb/Core/FileSpecList.h"
|
||||
#include "lldb/Core/RangeMap.h"
|
||||
#include "lldb/Host/FileSpec.h"
|
||||
#include "lldb/Host/Mutex.h"
|
||||
|
@ -127,6 +128,11 @@ public:
|
|||
virtual uint32_t
|
||||
GetDependentModules (lldb_private::FileSpecList& files);
|
||||
|
||||
virtual lldb_private::FileSpecList
|
||||
GetReExportedLibraries ()
|
||||
{
|
||||
return m_reexported_dylibs;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
// PluginInterface protocol
|
||||
//------------------------------------------------------------------
|
||||
|
@ -208,6 +214,7 @@ protected:
|
|||
lldb_private::Address m_entry_point_address;
|
||||
FileRangeArray m_thread_context_offsets;
|
||||
bool m_thread_context_offsets_valid;
|
||||
lldb_private::FileSpecList m_reexported_dylibs;
|
||||
|
||||
size_t
|
||||
ParseSymtab ();
|
||||
|
|
|
@ -536,6 +536,71 @@ Symbol::GetByteSize () const
|
|||
return m_addr_range.GetByteSize();
|
||||
}
|
||||
|
||||
|
||||
Symbol *
|
||||
Symbol::ResolveReExportedSymbolInModuleSpec (Target &target,
|
||||
ConstString &reexport_name,
|
||||
ModuleSpec &module_spec,
|
||||
ModuleList &seen_modules)
|
||||
{
|
||||
ModuleSP module_sp;
|
||||
if (module_spec.GetFileSpec())
|
||||
{
|
||||
// Try searching for the module file spec first using the full path
|
||||
module_sp = target.GetImages().FindFirstModule(module_spec);
|
||||
if (!module_sp)
|
||||
{
|
||||
// Next try and find the module by basename in case environment
|
||||
// variables or other runtime trickery causes shared libraries
|
||||
// to be loaded from alternate paths
|
||||
module_spec.GetFileSpec().GetDirectory().Clear();
|
||||
module_sp = target.GetImages().FindFirstModule(module_spec);
|
||||
}
|
||||
}
|
||||
|
||||
if (module_sp)
|
||||
{
|
||||
// There should not be cycles in the reexport list, but we don't want to crash if there are so make sure
|
||||
// we haven't seen this before:
|
||||
if (!seen_modules.AppendIfNeeded(module_sp))
|
||||
return nullptr;
|
||||
|
||||
lldb_private::SymbolContextList sc_list;
|
||||
module_sp->FindSymbolsWithNameAndType(reexport_name, eSymbolTypeAny, sc_list);
|
||||
const size_t num_scs = sc_list.GetSize();
|
||||
if (num_scs > 0)
|
||||
{
|
||||
for (size_t i=0; i<num_scs; ++i)
|
||||
{
|
||||
lldb_private::SymbolContext sc;
|
||||
if (sc_list.GetContextAtIndex(i, sc))
|
||||
{
|
||||
if (sc.symbol->IsExternal())
|
||||
return sc.symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we didn't find the symbol in this module, it may be because this module re-exports some
|
||||
// whole other library. We have to search those as well:
|
||||
seen_modules.Append(module_sp);
|
||||
|
||||
FileSpecList reexported_libraries = module_sp->GetObjectFile()->GetReExportedLibraries();
|
||||
size_t num_reexported_libraries = reexported_libraries.GetSize();
|
||||
for (size_t idx = 0; idx < num_reexported_libraries; idx++)
|
||||
{
|
||||
ModuleSpec reexported_module_spec;
|
||||
reexported_module_spec.GetFileSpec() = reexported_libraries.GetFileSpecAtIndex(idx);
|
||||
Symbol *result_symbol = ResolveReExportedSymbolInModuleSpec(target,
|
||||
reexport_name,
|
||||
reexported_module_spec,
|
||||
seen_modules);
|
||||
if (result_symbol)
|
||||
return result_symbol;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Symbol *
|
||||
Symbol::ResolveReExportedSymbol (Target &target)
|
||||
{
|
||||
|
@ -543,39 +608,11 @@ Symbol::ResolveReExportedSymbol (Target &target)
|
|||
if (reexport_name)
|
||||
{
|
||||
ModuleSpec module_spec;
|
||||
ModuleSP module_sp;
|
||||
ModuleList seen_modules;
|
||||
module_spec.GetFileSpec() = GetReExportedSymbolSharedLibrary();
|
||||
if (module_spec.GetFileSpec())
|
||||
{
|
||||
// Try searching for the module file spec first using the full path
|
||||
module_sp = target.GetImages().FindFirstModule(module_spec);
|
||||
if (!module_sp)
|
||||
{
|
||||
// Next try and find the module by basename in case environment
|
||||
// variables or other runtime trickery causes shared libraries
|
||||
// to be loaded from alternate paths
|
||||
module_spec.GetFileSpec().GetDirectory().Clear();
|
||||
module_sp = target.GetImages().FindFirstModule(module_spec);
|
||||
}
|
||||
}
|
||||
|
||||
if (module_sp)
|
||||
{
|
||||
lldb_private::SymbolContextList sc_list;
|
||||
module_sp->FindSymbolsWithNameAndType(reexport_name, eSymbolTypeAny, sc_list);
|
||||
const size_t num_scs = sc_list.GetSize();
|
||||
if (num_scs > 0)
|
||||
{
|
||||
for (size_t i=0; i<num_scs; ++i)
|
||||
{
|
||||
lldb_private::SymbolContext sc;
|
||||
if (sc_list.GetContextAtIndex(i, sc))
|
||||
{
|
||||
if (sc.symbol->IsExternal())
|
||||
return sc.symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ResolveReExportedSymbolInModuleSpec(target, reexport_name, module_spec, seen_modules);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
|
Loading…
Reference in New Issue