Split symbol support for ELF and Linux.

llvm-svn: 185366
This commit is contained in:
Michael Sartain 2013-07-01 19:45:50 +00:00
parent 82bedb1f3b
commit a7499c9830
38 changed files with 1473 additions and 515 deletions

View File

@ -45,7 +45,7 @@ class Module :
public SymbolContextScope
{
public:
// Static functions that can track the lifetime of moodule objects.
// Static functions that can track the lifetime of module objects.
// This is handy because we might have Module objects that are in
// shared pointers that aren't in the global module list (from
// ModuleList). If this is the case we need to know about it.
@ -638,7 +638,21 @@ public:
//------------------------------------------------------------------
virtual ObjectFile *
GetObjectFile ();
//------------------------------------------------------------------
/// Get the unified section list for the module. This is the section
/// list created by the module's object file and any debug info and
/// symbol files created by the symbol vendor.
///
/// If the symbol vendor has not been loaded yet, this function
/// will return the section list for the object file.
///
/// @return
/// Unified module section list.
//------------------------------------------------------------------
virtual SectionList *
GetUnifiedSectionList ();
uint32_t
GetVersion (uint32_t *versions, uint32_t num_versions);
@ -986,6 +1000,7 @@ protected:
std::unique_ptr<SymbolVendor> m_symfile_ap; ///< A pointer to the symbol vendor for this module.
ClangASTContext m_ast; ///< The AST context for this module.
PathMappingList m_source_mappings; ///< Module specific source remappings for when you have debug info for a module that doesn't match where the sources currently are
std::unique_ptr<lldb_private::SectionList> m_unified_sections_ap; ///< Unified section list for module.
bool m_did_load_objfile:1,
m_did_load_symbol_vendor:1,

View File

@ -18,6 +18,7 @@
#include "lldb/Core/RangeMap.h"
#include "lldb/Core/UserID.h"
#include "lldb/Core/VMRange.h"
#include "lldb/Symbol/ObjectFile.h"
#include <limits.h>
namespace lldb_private {
@ -33,6 +34,9 @@ public:
~SectionList();
bool
Copy (SectionList* dest_section_list);
size_t
AddSection (const lldb::SectionSP& section_sp);
@ -77,6 +81,10 @@ public:
bool
ReplaceSection (lldb::user_id_t sect_id, const lldb::SectionSP& section_sp, uint32_t depth = UINT32_MAX);
// Warning, this can be slow as it's removing items from a std::vector.
bool
DeleteSection (size_t idx);
lldb::SectionSP
GetSectionAtIndex (size_t idx) const;
@ -87,6 +95,13 @@ public:
void
Finalize ();
// Each time Finalize() is called with changes, revision id increments.
uint32_t
GetRevisionID() const
{
return m_revision_id;
}
void
Clear ()
{
@ -94,6 +109,8 @@ public:
}
protected:
bool m_changed;
uint32_t m_revision_id;
collection m_sections;
};
@ -107,6 +124,7 @@ class Section :
public:
// Create a root section (one that has no parent)
Section (const lldb::ModuleSP &module_sp,
ObjectFile *obj_file,
lldb::user_id_t sect_id,
const ConstString &name,
lldb::SectionType sect_type,
@ -119,6 +137,7 @@ public:
// Create a section that is a child of parent_section_sp
Section (const lldb::SectionSP &parent_section_sp, // NULL for top level sections, non-NULL for child sections
const lldb::ModuleSP &module_sp,
ObjectFile *obj_file,
lldb::user_id_t sect_id,
const ConstString &name,
lldb::SectionType sect_type,
@ -271,8 +290,21 @@ public:
m_children.Finalize();
}
ObjectFile *
GetObjectFile ()
{
return m_obj_file;
}
const ObjectFile *
GetObjectFile () const
{
return m_obj_file;
}
protected:
ObjectFile *m_obj_file; // The object file that data for this section should be read from
lldb::SectionType m_type; // The type of this section
lldb::SectionWP m_parent_wp; // Weak pointer to parent section
ConstString m_name; // Name of this section

View File

@ -56,7 +56,7 @@ public:
SetBytes (const void *uuid_bytes, uint32_t num_uuid_bytes = 16);
std::string
GetAsString () const;
GetAsString (const char *separator = NULL) const;
size_t
SetFromCString (const char *c_str, uint32_t num_uuid_bytes = 16);

View File

@ -13,6 +13,7 @@
#include "lldb/lldb-private.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Core/FileSpecList.h"
#include "lldb/Core/ModuleChild.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Host/Endian.h"
@ -78,7 +79,12 @@ public:
eStrataKernel,
eStrataRawImage
} Strata;
typedef enum
{
eSymtabFromUnifiedSectionList = 0x0001 /// Return symbol table from unified module section list
} SymtabFlags;
//------------------------------------------------------------------
/// Construct with a parent module, offset, and header data.
///
@ -356,22 +362,30 @@ public:
/// Symbol table parsing can be deferred by ObjectFile instances
/// until this accessor is called the first time.
///
/// @param[in] flags
/// eSymtabFromUnifiedSectionList: Whether to get symbol table
/// for unified module section list, or object file.
///
/// @return
/// The symbol table for this object file.
//------------------------------------------------------------------
virtual Symtab *
GetSymtab () = 0;
GetSymtab (uint32_t flags = 0) = 0;
//------------------------------------------------------------------
/// Frees the symbol table.
///
/// This function should only be used when an object file is
///
/// @param[in] flags
/// eSymtabFromUnifiedSectionList: Whether to clear symbol table
/// for unified module section list, or object file.
///
/// @return
/// The symbol table for this object file.
//------------------------------------------------------------------
virtual void
ClearSymtab ();
ClearSymtab (uint32_t flags = 0);
//------------------------------------------------------------------
/// Gets the UUID for this object file.
@ -388,6 +402,21 @@ public:
virtual bool
GetUUID (lldb_private::UUID* uuid) = 0;
//------------------------------------------------------------------
/// 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.
///
/// @return
/// Returns filespeclist.
//------------------------------------------------------------------
virtual lldb_private::FileSpecList
GetDebugSymbolFilePaths()
{
return FileSpecList();
}
//------------------------------------------------------------------
/// Gets whether endian swapping should occur when extracting data
/// from this object file.
@ -485,6 +514,7 @@ public:
{
return lldb::RegisterContextSP();
}
//------------------------------------------------------------------
/// The object file should be able to calculate its type by looking
/// at its file header and possibly the sections or other data in
@ -500,6 +530,17 @@ public:
virtual Type
CalculateType() = 0;
//------------------------------------------------------------------
/// In cases where the type can't be calculated (elf files), this
/// routine allows someone to explicitly set it. As an example,
/// SymbolVendorELF uses this routine to set eTypeDebugInfo when
/// loading debug link files.
virtual void
SetType (Type type)
{
m_type = type;
}
//------------------------------------------------------------------
/// The object file should be able to calculate the strata of the
/// object file.
@ -635,6 +676,8 @@ protected:
const lldb::addr_t m_memory_addr;
std::unique_ptr<lldb_private::SectionList> m_sections_ap;
std::unique_ptr<lldb_private::Symtab> m_symtab_ap;
std::unique_ptr<lldb_private::Symtab> m_symtab_unified_ap; ///< Unified section list symbol table.
uint32_t m_symtab_unified_revisionid; ///< Unified section list symbol table revision id for when m_symtab_unified_ap was last modified.
//------------------------------------------------------------------
/// Sets the architecture for a module. At present the architecture

View File

@ -164,6 +164,14 @@ public:
return m_sym_file_ap.get();
}
// Get module unified section list symbol table.
virtual Symtab *
GetSymtab ();
// Clear module unified section list symbol table.
virtual void
ClearSymtab ();
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@ -184,7 +192,7 @@ protected:
TypeList m_type_list; // Uniqued types for all parsers owned by this module
CompileUnits m_compile_units; // The current compile units
lldb::ObjectFileSP m_objfile_sp; // Keep a reference to the object file in case it isn't the same as the module object file (debug symbols in a separate file)
std::unique_ptr<SymbolFile> m_sym_file_ap; // A single symbol file. Suclasses can add more of these if needed.
std::unique_ptr<SymbolFile> m_sym_file_ap; // A single symbol file. Subclasses can add more of these if needed.
private:
//------------------------------------------------------------------

View File

@ -118,6 +118,9 @@ public:
FileSpecList &
GetExecutableSearchPaths ();
FileSpecList &
GetDebugFileSearchPaths ();
bool
GetEnableSyntheticValue () const;
@ -378,6 +381,9 @@ public:
static FileSpecList
GetDefaultExecutableSearchPaths ();
static FileSpecList
GetDefaultDebugFileSearchPaths ();
static ArchSpec
GetDefaultArchitecture ();

View File

@ -515,6 +515,10 @@ namespace lldb {
eSectionTypeDWARFAppleTypes,
eSectionTypeDWARFAppleNamespaces,
eSectionTypeDWARFAppleObjC,
eSectionTypeELFSymbolTable, // Elf SHT_SYMTAB section
eSectionTypeELFDynamicSymbols, // Elf SHT_DYNSYM section
eSectionTypeELFRelocationEntries, // Elf SHT_REL or SHT_REL section
eSectionTypeELFDynamicLinkInfo, // Elf SHT_DYNAMIC section
eSectionTypeEHFrame,
eSectionTypeOther

View File

@ -40,6 +40,7 @@ USEDLIBS = lldbAPI.a \
lldbPluginLanguageRuntimeObjCAppleObjCRuntime.a \
lldbPluginObjectContainerBSDArchive.a \
lldbPluginObjectFileELF.a \
lldbPluginSymbolVendorELF.a \
lldbPluginObjectFilePECOFF.a \
lldbPluginOperatingSystemPython.a \
lldbPluginPlatformGDBServer.a \

View File

@ -300,19 +300,27 @@ SBModule::GetCompileUnitAtIndex (uint32_t index)
return sb_cu;
}
static Symtab *
GetUnifiedSymbolTable (const lldb::ModuleSP& module_sp)
{
if (module_sp)
{
SymbolVendor *symbols = module_sp->GetSymbolVendor();
if (symbols)
return symbols->GetSymtab();
}
return NULL;
}
size_t
SBModule::GetNumSymbols ()
{
ModuleSP module_sp (GetSP ());
if (module_sp)
{
ObjectFile *obj_file = module_sp->GetObjectFile();
if (obj_file)
{
Symtab *symtab = obj_file->GetSymtab();
if (symtab)
return symtab->GetNumSymbols();
}
Symtab *symtab = GetUnifiedSymbolTable (module_sp);
if (symtab)
return symtab->GetNumSymbols();
}
return 0;
}
@ -322,16 +330,9 @@ SBModule::GetSymbolAtIndex (size_t idx)
{
SBSymbol sb_symbol;
ModuleSP module_sp (GetSP ());
if (module_sp)
{
ObjectFile *obj_file = module_sp->GetObjectFile();
if (obj_file)
{
Symtab *symtab = obj_file->GetSymtab();
if (symtab)
sb_symbol.SetSymbol(symtab->SymbolAtIndex (idx));
}
}
Symtab *symtab = GetUnifiedSymbolTable (module_sp);
if (symtab)
sb_symbol.SetSymbol(symtab->SymbolAtIndex (idx));
return sb_symbol;
}
@ -343,16 +344,9 @@ SBModule::FindSymbol (const char *name,
if (name && name[0])
{
ModuleSP module_sp (GetSP ());
if (module_sp)
{
ObjectFile *obj_file = module_sp->GetObjectFile();
if (obj_file)
{
Symtab *symtab = obj_file->GetSymtab();
if (symtab)
sb_symbol.SetSymbol(symtab->FindFirstSymbolWithNameAndType(ConstString(name), symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny));
}
}
Symtab *symtab = GetUnifiedSymbolTable (module_sp);
if (symtab)
sb_symbol.SetSymbol(symtab->FindFirstSymbolWithNameAndType(ConstString(name), symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny));
}
return sb_symbol;
}
@ -365,28 +359,21 @@ SBModule::FindSymbols (const char *name, lldb::SymbolType symbol_type)
if (name && name[0])
{
ModuleSP module_sp (GetSP ());
if (module_sp)
Symtab *symtab = GetUnifiedSymbolTable (module_sp);
if (symtab)
{
ObjectFile *obj_file = module_sp->GetObjectFile();
if (obj_file)
std::vector<uint32_t> matching_symbol_indexes;
const size_t num_matches = symtab->FindAllSymbolsWithNameAndType(ConstString(name), symbol_type, matching_symbol_indexes);
if (num_matches)
{
Symtab *symtab = obj_file->GetSymtab();
if (symtab)
SymbolContext sc;
sc.module_sp = module_sp;
SymbolContextList &sc_list = *sb_sc_list;
for (size_t i=0; i<num_matches; ++i)
{
std::vector<uint32_t> matching_symbol_indexes;
const size_t num_matches = symtab->FindAllSymbolsWithNameAndType(ConstString(name), symbol_type, matching_symbol_indexes);
if (num_matches)
{
SymbolContext sc;
sc.module_sp = module_sp;
SymbolContextList &sc_list = *sb_sc_list;
for (size_t i=0; i<num_matches; ++i)
{
sc.symbol = symtab->SymbolAtIndex (matching_symbol_indexes[i]);
if (sc.symbol)
sc_list.Append(sc);
}
}
sc.symbol = symtab->SymbolAtIndex (matching_symbol_indexes[i]);
if (sc.symbol)
sc_list.Append(sc);
}
}
}
@ -403,13 +390,11 @@ SBModule::GetNumSections ()
ModuleSP module_sp (GetSP ());
if (module_sp)
{
ObjectFile *obj_file = module_sp->GetObjectFile();
if (obj_file)
{
SectionList *section_list = obj_file->GetSectionList ();
if (section_list)
return section_list->GetSize();
}
// Give the symbol vendor a chance to add to the unified section list.
module_sp->GetSymbolVendor();
SectionList *section_list = module_sp->GetUnifiedSectionList();
if (section_list)
return section_list->GetSize();
}
return 0;
}
@ -421,14 +406,12 @@ SBModule::GetSectionAtIndex (size_t idx)
ModuleSP module_sp (GetSP ());
if (module_sp)
{
ObjectFile *obj_file = module_sp->GetObjectFile();
if (obj_file)
{
SectionList *section_list = obj_file->GetSectionList ();
// Give the symbol vendor a chance to add to the unified section list.
module_sp->GetSymbolVendor();
SectionList *section_list = module_sp->GetUnifiedSectionList ();
if (section_list)
sb_section.SetSP(section_list->GetSectionAtIndex (idx));
}
if (section_list)
sb_section.SetSP(section_list->GetSectionAtIndex (idx));
}
return sb_section;
}
@ -588,18 +571,16 @@ SBModule::FindSection (const char *sect_name)
ModuleSP module_sp (GetSP ());
if (sect_name && module_sp)
{
ObjectFile *objfile = module_sp->GetObjectFile();
if (objfile)
// Give the symbol vendor a chance to add to the unified section list.
module_sp->GetSymbolVendor();
SectionList *section_list = module_sp->GetUnifiedSectionList();
if (section_list)
{
SectionList *section_list = objfile->GetSectionList();
if (section_list)
ConstString const_sect_name(sect_name);
SectionSP section_sp (section_list->FindSectionByName(const_sect_name));
if (section_sp)
{
ConstString const_sect_name(sect_name);
SectionSP section_sp (section_list->FindSectionByName(const_sect_name));
if (section_sp)
{
sb_section.SetSP (section_sp);
}
sb_section.SetSP (section_sp);
}
}
}

View File

@ -49,6 +49,7 @@ set( LLDB_USED_LIBS
lldbPluginObjectFileMachO
lldbPluginObjectFileELF
lldbPluginSymbolVendorELF
lldbPluginObjectContainerBSDArchive
lldbPluginObjectContainerMachOArchive
lldbPluginProcessGDBRemote

View File

@ -1438,10 +1438,10 @@ DumpModuleSymtab (CommandInterpreter &interpreter, Stream &strm, Module *module,
{
if (module)
{
ObjectFile *objfile = module->GetObjectFile ();
if (objfile)
SymbolVendor *sym_vendor = module->GetSymbolVendor ();
if (sym_vendor)
{
Symtab *symtab = objfile->GetSymtab();
Symtab *symtab = sym_vendor->GetSymtab();
if (symtab)
symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(), sort_order);
}
@ -1453,19 +1453,15 @@ DumpModuleSections (CommandInterpreter &interpreter, Stream &strm, Module *modul
{
if (module)
{
ObjectFile *objfile = module->GetObjectFile ();
if (objfile)
SectionList *section_list = module->GetUnifiedSectionList();
if (section_list)
{
SectionList *section_list = objfile->GetSectionList();
if (section_list)
{
strm.Printf ("Sections for '%s' (%s):\n",
module->GetSpecificationDescription().c_str(),
module->GetArchitecture().GetArchitectureName());
strm.IndentMore();
section_list->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(), true, UINT32_MAX);
strm.IndentLess();
}
strm.Printf ("Sections for '%s' (%s):\n",
module->GetSpecificationDescription().c_str(),
module->GetArchitecture().GetArchitectureName());
strm.IndentMore();
section_list->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(), true, UINT32_MAX);
strm.IndentLess();
}
}
}
@ -1569,10 +1565,10 @@ LookupSymbolInModule (CommandInterpreter &interpreter, Stream &strm, Module *mod
{
SymbolContext sc;
ObjectFile *objfile = module->GetObjectFile ();
if (objfile)
SymbolVendor *sym_vendor = module->GetSymbolVendor ();
if (sym_vendor)
{
Symtab *symtab = objfile->GetSymtab();
Symtab *symtab = sym_vendor->GetSymtab();
if (symtab)
{
uint32_t i;

View File

@ -18,6 +18,7 @@
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "llvm/ADT/Triple.h"
@ -456,10 +457,10 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum
case eSectionTypeData:
if (module_sp)
{
ObjectFile *objfile = module_sp->GetObjectFile();
if (objfile)
SymbolVendor *sym_vendor = module_sp->GetSymbolVendor();
if (sym_vendor)
{
Symtab *symtab = objfile->GetSymtab();
Symtab *symtab = sym_vendor->GetSymtab();
if (symtab)
{
const addr_t file_Addr = GetFileAddress();
@ -1023,7 +1024,11 @@ Address::GetAddressClass () const
{
ObjectFile *obj_file = module_sp->GetObjectFile();
if (obj_file)
{
// Give the symbol vendor a chance to add to the unified section list.
module_sp->GetSymbolVendor();
return obj_file->GetAddressClass (GetFileAddress());
}
}
return eAddressClassUnknown;
}

View File

@ -33,6 +33,7 @@
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Symbol/SymbolFile.h"
using namespace lldb;
using namespace lldb_private;
@ -244,6 +245,7 @@ Module::~Module()
// function calls back into this module object. The ordering is important
// here because symbol files can require the module object file. So we tear
// down the symbol file first, then the object file.
m_unified_sections_ap.reset();
m_symfile_ap.reset();
m_objfile_sp.reset();
}
@ -480,10 +482,10 @@ Module::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve
// Resolve the symbol if requested, but don't re-look it up if we've already found it.
if (resolve_scope & eSymbolContextSymbol && !(resolved_flags & eSymbolContextSymbol))
{
ObjectFile* ofile = GetObjectFile();
if (ofile)
SymbolVendor* sym_vendor = GetSymbolVendor();
if (sym_vendor)
{
Symtab *symtab = ofile->GetSymtab();
Symtab *symtab = sym_vendor->GetSymtab();
if (symtab)
{
if (so_addr.IsSectionOffset())
@ -613,6 +615,7 @@ Module::FindFunctions (const ConstString &name,
match_name_after_lookup);
if (symbols)
{
symbols->FindFunctions(lookup_name,
namespace_decl,
lookup_name_type_mask,
@ -620,13 +623,10 @@ Module::FindFunctions (const ConstString &name,
append,
sc_list);
// Now check our symbol table for symbols that are code symbols if requested
if (include_symbols)
{
ObjectFile *objfile = GetObjectFile();
if (objfile)
// Now check our symbol table for symbols that are code symbols if requested
if (include_symbols)
{
Symtab *symtab = objfile->GetSymtab();
Symtab *symtab = symbols->GetSymtab();
if (symtab)
symtab->FindFunctionSymbols(lookup_name, lookup_name_type_mask, sc_list);
}
@ -652,20 +652,17 @@ Module::FindFunctions (const ConstString &name,
++i;
}
}
}
else
{
if (symbols)
{
symbols->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, append, sc_list);
// Now check our symbol table for symbols that are code symbols if requested
if (include_symbols)
{
ObjectFile *objfile = GetObjectFile();
if (objfile)
// Now check our symbol table for symbols that are code symbols if requested
if (include_symbols)
{
Symtab *symtab = objfile->GetSymtab();
Symtab *symtab = symbols->GetSymtab();
if (symtab)
symtab->FindFunctionSymbols(name, name_type_mask, sc_list);
}
@ -689,14 +686,13 @@ Module::FindFunctions (const RegularExpression& regex,
SymbolVendor *symbols = GetSymbolVendor ();
if (symbols)
symbols->FindFunctions(regex, include_inlines, append, sc_list);
// Now check our symbol table for symbols that are code symbols if requested
if (include_symbols)
{
ObjectFile *objfile = GetObjectFile();
if (objfile)
symbols->FindFunctions(regex, include_inlines, append, sc_list);
// Now check our symbol table for symbols that are code symbols if requested
if (include_symbols)
{
Symtab *symtab = objfile->GetSymtab();
Symtab *symtab = symbols->GetSymtab();
if (symtab)
{
std::vector<uint32_t> symbol_indexes;
@ -1067,13 +1063,12 @@ Module::Dump(Stream *s)
m_object_name ? ")" : "");
s->IndentMore();
ObjectFile *objfile = GetObjectFile ();
if (objfile)
objfile->Dump(s);
SymbolVendor *symbols = GetSymbolVendor ();
if (symbols)
symbols->Dump(s);
@ -1115,15 +1110,29 @@ Module::GetObjectFile()
data_offset);
if (m_objfile_sp)
{
// Once we get the object file, update our module with the object file's
// architecture since it might differ in vendor/os if some parts were
// unknown.
// Once we get the object file, update our module with the object file's
// architecture since it might differ in vendor/os if some parts were
// unknown.
m_objfile_sp->GetArchitecture (m_arch);
// Populate m_unified_sections_ap with sections from objfile.
SectionList *section_list = m_objfile_sp->GetSectionList();
if (section_list)
{
m_unified_sections_ap.reset(new SectionList());
section_list->Copy (m_unified_sections_ap.get());
m_unified_sections_ap->Finalize();
}
}
}
return m_objfile_sp.get();
}
SectionList *
Module::GetUnifiedSectionList()
{
return m_unified_sections_ap.get();
}
const Symbol *
Module::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type)
@ -1132,10 +1141,10 @@ Module::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symb
"Module::FindFirstSymbolWithNameAndType (name = %s, type = %i)",
name.AsCString(),
symbol_type);
ObjectFile *objfile = GetObjectFile();
if (objfile)
SymbolVendor* sym_vendor = GetSymbolVendor();
if (sym_vendor)
{
Symtab *symtab = objfile->GetSymtab();
Symtab *symtab = sym_vendor->GetSymtab();
if (symtab)
return symtab->FindFirstSymbolWithNameAndType (name, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny);
}
@ -1170,10 +1179,10 @@ Module::FindFunctionSymbols (const ConstString &name,
"Module::FindSymbolsFunctions (name = %s, mask = 0x%8.8x)",
name.AsCString(),
name_type_mask);
ObjectFile *objfile = GetObjectFile ();
if (objfile)
SymbolVendor* sym_vendor = GetSymbolVendor();
if (sym_vendor)
{
Symtab *symtab = objfile->GetSymtab();
Symtab *symtab = sym_vendor->GetSymtab();
if (symtab)
return symtab->FindFunctionSymbols (name, name_type_mask, sc_list);
}
@ -1192,10 +1201,10 @@ Module::FindSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_t
name.AsCString(),
symbol_type);
const size_t initial_size = sc_list.GetSize();
ObjectFile *objfile = GetObjectFile ();
if (objfile)
SymbolVendor* sym_vendor = GetSymbolVendor();
if (sym_vendor)
{
Symtab *symtab = objfile->GetSymtab();
Symtab *symtab = sym_vendor->GetSymtab();
if (symtab)
{
std::vector<uint32_t> symbol_indexes;
@ -1217,10 +1226,10 @@ Module::FindSymbolsMatchingRegExAndType (const RegularExpression &regex, SymbolT
regex.GetText(),
symbol_type);
const size_t initial_size = sc_list.GetSize();
ObjectFile *objfile = GetObjectFile ();
if (objfile)
SymbolVendor* sym_vendor = GetSymbolVendor();
if (sym_vendor)
{
Symtab *symtab = objfile->GetSymtab();
Symtab *symtab = sym_vendor->GetSymtab();
if (symtab)
{
std::vector<uint32_t> symbol_indexes;
@ -1234,12 +1243,35 @@ Module::FindSymbolsMatchingRegExAndType (const RegularExpression &regex, SymbolT
void
Module::SetSymbolFileFileSpec (const FileSpec &file)
{
// Remove any sections in the unified section list that come from the current symbol vendor.
if (m_symfile_ap)
{
SectionList *section_list = GetUnifiedSectionList();
SymbolFile *symbol_file = m_symfile_ap->GetSymbolFile();
if (section_list && symbol_file)
{
ObjectFile *obj_file = symbol_file->GetObjectFile();
if (obj_file)
{
size_t num_sections = section_list->GetNumSections (0);
for (size_t idx = num_sections; idx > 0; --idx)
{
lldb::SectionSP section_sp (section_list->GetSectionAtIndex (idx - 1));
if (section_sp->GetObjectFile() == obj_file)
{
m_unified_sections_ap->DeleteSection (idx - 1);
}
}
m_unified_sections_ap->Finalize();
}
}
}
m_symfile_spec = file;
m_symfile_ap.reset();
m_did_load_symbol_vendor = false;
}
bool
Module::IsExecutable ()
{

View File

@ -16,6 +16,7 @@ using namespace lldb;
using namespace lldb_private;
Section::Section (const ModuleSP &module_sp,
ObjectFile *obj_file,
user_id_t sect_id,
const ConstString &name,
SectionType sect_type,
@ -27,6 +28,7 @@ Section::Section (const ModuleSP &module_sp,
ModuleChild (module_sp),
UserID (sect_id),
Flags (flags),
m_obj_file (obj_file),
m_type (sect_type),
m_parent_wp (),
m_name (name),
@ -45,6 +47,7 @@ Section::Section (const ModuleSP &module_sp,
Section::Section (const lldb::SectionSP &parent_section_sp,
const ModuleSP &module_sp,
ObjectFile *obj_file,
user_id_t sect_id,
const ConstString &name,
SectionType sect_type,
@ -56,6 +59,7 @@ Section::Section (const lldb::SectionSP &parent_section_sp,
ModuleChild (module_sp),
UserID (sect_id),
Flags (flags),
m_obj_file (obj_file),
m_type (sect_type),
m_parent_wp (),
m_name (name),
@ -242,13 +246,16 @@ Section::DumpName (Stream *s) const
else
{
// The top most section prints the module basename
const char * name = NULL;
ModuleSP module_sp (GetModule());
if (module_sp)
{
const char *module_basename = module_sp->GetFileSpec().GetFilename().AsCString();
if (module_basename && module_basename[0])
s->Printf("%s.", module_basename);
}
const FileSpec &file_spec = m_obj_file->GetFileSpec();
if (m_obj_file)
name = file_spec.GetFilename().AsCString();
if ((!name || !name[0]) && module_sp)
name = module_sp->GetFileSpec().GetFilename().AsCString();
if (name && name[0])
s->Printf("%s.", name);
}
m_name.Dump(s);
}
@ -285,6 +292,8 @@ Section::Slide (addr_t slide_amount, bool slide_children)
#pragma mark SectionList
SectionList::SectionList () :
m_changed(false),
m_revision_id(0),
m_sections()
{
}
@ -294,15 +303,41 @@ SectionList::~SectionList ()
{
}
bool
SectionList::Copy (SectionList *dest_section_list)
{
if (dest_section_list)
{
dest_section_list->m_sections = m_sections;
dest_section_list->m_changed = true;
return true;
}
return false;
}
size_t
SectionList::AddSection (const lldb::SectionSP& section_sp)
{
m_changed = true;
assert (section_sp.get());
size_t section_index = m_sections.size();
m_sections.push_back(section_sp);
return section_index;
}
// Warning, this can be slow as it's removing items from a std::vector.
bool
SectionList::DeleteSection (size_t idx)
{
if (idx < m_sections.size())
{
m_changed = true;
m_sections.erase (m_sections.begin() + idx);
return true;
}
return false;
}
size_t
SectionList::FindSectionIndex (const Section* sect)
{
@ -325,11 +360,13 @@ SectionList::AddUniqueSection (const lldb::SectionSP& sect_sp)
{
size_t sect_idx = FindSectionIndex (sect_sp.get());
if (sect_idx == UINT32_MAX)
{
m_changed = true;
sect_idx = AddSection (sect_sp);
}
return sect_idx;
}
bool
SectionList::ReplaceSection (user_id_t sect_id, const lldb::SectionSP& sect_sp, uint32_t depth)
{
@ -338,6 +375,7 @@ SectionList::ReplaceSection (user_id_t sect_id, const lldb::SectionSP& sect_sp,
{
if ((*sect_iter)->GetID() == sect_id)
{
m_changed = true;
*sect_iter = sect_sp;
return true;
}
@ -350,7 +388,6 @@ SectionList::ReplaceSection (user_id_t sect_id, const lldb::SectionSP& sect_sp,
return false;
}
size_t
SectionList::GetNumSections (uint32_t depth) const
{
@ -527,5 +564,10 @@ SectionList::Finalize ()
sect->GetChildren().Finalize();
}
}
if (m_changed)
{
m_revision_id++;
m_changed = false;
}
}

View File

@ -67,20 +67,26 @@ UUID::GetBytes() const
}
std::string
UUID::GetAsString () const
UUID::GetAsString (const char *separator) const
{
std::string result;
char buf[64];
char buf[256];
if (!separator)
separator = "-";
const uint8_t *u = (const uint8_t *)GetBytes();
if (sizeof (buf) > (size_t)snprintf (buf,
sizeof (buf),
"%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7],u[8],u[9],u[10],u[11],u[12],u[13],u[14],u[15]))
"%2.2X%2.2X%2.2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
u[0],u[1],u[2],u[3],separator,
u[4],u[5],separator,
u[6],u[7],separator,
u[8],u[9],separator,
u[10],u[11],u[12],u[13],u[14],u[15]))
{
result.append (buf);
if (m_num_uuid_bytes == 20)
{
if (sizeof (buf) > (size_t)snprintf (buf, sizeof (buf), "-%2.2X%2.2X%2.2X%2.2X", u[16],u[17],u[18],u[19]))
if (sizeof (buf) > (size_t)snprintf (buf, sizeof (buf), "%s%2.2X%2.2X%2.2X%2.2X", separator,u[16],u[17],u[18],u[19]))
result.append (buf);
}
}

View File

@ -8,11 +8,127 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/Symbols.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/UUID.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
#if !defined (__APPLE__)
#if defined (__linux__)
FileSpec
Symbols::LocateExecutableObjectFile (const ModuleSpec &module_spec)
{
// FIXME
return FileSpec();
}
FileSpec
Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec)
{
const char *symbol_filename = module_spec.GetSymbolFileSpec().GetFilename().AsCString();
if (!symbol_filename || !symbol_filename[0])
return FileSpec();
FileSpecList debug_file_search_paths (Target::GetDefaultDebugFileSearchPaths());
// Add module directory.
const ConstString &file_dir = module_spec.GetFileSpec().GetDirectory();
debug_file_search_paths.AppendIfUnique (FileSpec(file_dir.AsCString("."), true));
// Add current working directory.
debug_file_search_paths.AppendIfUnique (FileSpec(".", true));
// Add /usr/lib/debug directory.
debug_file_search_paths.AppendIfUnique (FileSpec("/usr/lib/debug", true));
std::string uuid_str;
const UUID &module_uuid = module_spec.GetUUID();
if (module_uuid.IsValid())
{
// Some debug files are stored in the .build-id directory like this:
// /usr/lib/debug/.build-id/ff/e7fe727889ad82bb153de2ad065b2189693315.debug
uuid_str = module_uuid.GetAsString("");
uuid_str.insert (2, 1, '/');
uuid_str = uuid_str + ".debug";
}
// Get full path to our module. Needed to check debug files like this:
// /usr/lib/debug/usr/lib/libboost_date_time.so.1.46.1
std::string module_filename = module_spec.GetFileSpec().GetPath();
size_t num_directories = debug_file_search_paths.GetSize();
for (size_t idx = 0; idx < num_directories; ++idx)
{
FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex (idx);
dirspec.ResolvePath();
if (!dirspec.Exists() || !dirspec.IsDirectory())
continue;
std::vector<std::string> files;
std::string dirname = dirspec.GetPath();
files.push_back (dirname + "/" + symbol_filename);
files.push_back (dirname + "/.debug/" + symbol_filename);
files.push_back (dirname + "/.build-id/" + uuid_str);
files.push_back (dirname + module_filename);
const uint32_t num_files = files.size();
for (size_t idx_file = 0; idx_file < num_files; ++idx_file)
{
const std::string &filename = files[idx_file];
FileSpec file_spec (filename.c_str(), true);
if (file_spec == module_spec.GetFileSpec())
continue;
if (file_spec.Exists())
{
lldb_private::ModuleSpecList specs;
const size_t num_specs = ObjectFile::GetModuleSpecifications (file_spec, 0, specs);
assert (num_specs <= 1 && "Symbol Vendor supports only a single architecture");
if (num_specs == 1)
{
ModuleSpec mspec;
if (specs.GetModuleSpecAtIndex (0, mspec))
{
if (mspec.GetUUID() == module_uuid)
return file_spec;
}
}
}
}
}
return FileSpec();
}
FileSpec
Symbols::FindSymbolFileInBundle (const FileSpec& symfile_bundle,
const lldb_private::UUID *uuid,
const ArchSpec *arch)
{
// FIXME
return FileSpec();
}
bool
Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec, bool force_lookup)
{
// Fill in the module_spec.GetFileSpec() for the object file and/or the
// module_spec.GetSymbolFileSpec() for the debug symbols file.
return false;
}
#elif !defined (__APPLE__)
FileSpec
Symbols::LocateExecutableObjectFile (const ModuleSpec &module_spec)
@ -44,5 +160,4 @@ Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec, bool force_lookup
return false;
}
#endif

View File

@ -262,13 +262,27 @@ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,
if (spec.GetArchitecture().IsValid())
{
// We could parse the ABI tag information (in .note, .notes, or .note.ABI-tag) to get the
// machine information. However, we'd have to read a good bit of the rest of the file,
// and this info isn't guaranteed to exist or be correct. More details here:
// machine information. However, this info isn't guaranteed to exist or be correct. Details:
// http://refspecs.linuxfoundation.org/LSB_1.2.0/gLSB/noteabitag.html
// Instead of passing potentially incorrect information down the pipeline, grab
// the host information and use it.
spec.GetArchitecture().GetTriple().setOSName (Host::GetOSString().GetCString());
spec.GetArchitecture().GetTriple().setVendorName(Host::GetVendorString().GetCString());
// Try to get the UUID from the section list. Usually that's at the end, so
// map the file in if we don't have it already.
size_t section_header_end = header.e_shoff + header.e_shnum * header.e_shentsize;
if (section_header_end > data_sp->GetByteSize())
{
data_sp = file.MemoryMapFileContents (file_offset, section_header_end);
data.SetData(data_sp);
}
uint32_t gnu_debuglink_crc;
std::string gnu_debuglink_file;
SectionHeaderColl section_headers;
GetSectionHeaderInfo(section_headers, data, header, spec.GetUUID(), gnu_debuglink_file, gnu_debuglink_crc);
specs.Append(spec);
}
}
@ -306,12 +320,13 @@ ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp,
m_header(),
m_program_headers(),
m_section_headers(),
m_filespec_ap(),
m_shstr_data()
m_filespec_ap()
{
if (file)
m_file = *file;
::memset(&m_header, 0, sizeof(m_header));
m_gnu_debuglink_crc = 0;
m_gnu_debuglink_file.clear();
}
ObjectFileELF::~ObjectFileELF()
@ -359,18 +374,111 @@ ObjectFileELF::ParseHeader()
return m_header.Parse(m_data, &offset);
}
/*
* crc function from http://svnweb.freebsd.org/base/head/sys/libkern/crc32.c
*
* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
* code or tables extracted from it, as desired without restriction.
*/
static uint32_t
calc_gnu_debuglink_crc32(const void *buf, size_t size)
{
static const uint32_t g_crc32_tab[] =
{
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
const uint8_t *p = (const uint8_t *)buf;
uint32_t crc;
crc = ~0U;
while (size--)
crc = g_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
return crc ^ ~0U;
}
bool
ObjectFileELF::GetUUID(lldb_private::UUID* uuid)
{
// Need to parse the section list to get the UUIDs, so make sure that's been done.
if (!ParseSectionHeaders())
return false;
if (m_uuid.IsValid())
{
// We have the full build id uuid.
*uuid = m_uuid;
return true;
}
// FIXME: Return MD5 sum here. See comment in ObjectFile.h.
else
{
m_gnu_debuglink_crc = calc_gnu_debuglink_crc32 (m_data.GetDataStart(), m_data.GetByteSize());
if (m_gnu_debuglink_crc)
{
// Use 4 bytes of crc from the .gnu_debuglink section.
uint32_t uuidt[4] = { m_gnu_debuglink_crc, 0, 0, 0 };
uuid->SetBytes (uuidt, sizeof(uuidt));
return true;
}
}
return false;
}
lldb_private::FileSpecList
ObjectFileELF::GetDebugSymbolFilePaths()
{
FileSpecList file_spec_list;
if (!m_gnu_debuglink_file.empty())
{
FileSpec file_spec (m_gnu_debuglink_file.c_str(), false);
file_spec_list.Append (file_spec);
}
return file_spec_list;
}
uint32_t
ObjectFileELF::GetDependentModules(FileSpecList &files)
{
@ -416,7 +524,7 @@ ObjectFileELF::GetImageInfoAddress()
if (!dynsym_id)
return Address();
const ELFSectionHeader *dynsym_hdr = GetSectionHeaderByIndex(dynsym_id);
const ELFSectionHeaderInfo *dynsym_hdr = GetSectionHeaderByIndex(dynsym_id);
if (!dynsym_hdr)
return Address();
@ -477,7 +585,7 @@ ObjectFileELF::ParseDependentModules()
m_filespec_ap.reset(new FileSpecList());
if (!(ParseSectionHeaders() && GetSectionHeaderStringTable()))
if (!ParseSectionHeaders())
return 0;
// Locate the dynamic table.
@ -574,102 +682,8 @@ ObjectFileELF::ParseProgramHeaders()
return m_program_headers.size();
}
//----------------------------------------------------------------------
// ParseSectionHeaders
//----------------------------------------------------------------------
size_t
ObjectFileELF::ParseSectionHeaders()
{
// We have already parsed the section headers
if (!m_section_headers.empty())
return m_section_headers.size();
// If there are no section headers we are done.
if (m_header.e_shnum == 0)
return 0;
m_section_headers.resize(m_header.e_shnum);
if (m_section_headers.size() != m_header.e_shnum)
return 0;
const size_t sh_size = m_header.e_shnum * m_header.e_shentsize;
const elf_off sh_offset = m_header.e_shoff;
DataExtractor data;
if (GetData (sh_offset, sh_size, data) != sh_size)
return 0;
uint32_t idx;
lldb::offset_t offset;
for (idx = 0, offset = 0; idx < m_header.e_shnum; ++idx)
{
if (m_section_headers[idx].Parse(data, &offset) == false)
break;
}
if (idx < m_section_headers.size())
m_section_headers.resize(idx);
return m_section_headers.size();
}
size_t
ObjectFileELF::GetSectionHeaderStringTable()
{
if (m_shstr_data.GetByteSize() == 0)
{
const unsigned strtab_idx = m_header.e_shstrndx;
if (strtab_idx && strtab_idx < m_section_headers.size())
{
const ELFSectionHeader &sheader = m_section_headers[strtab_idx];
const size_t byte_size = sheader.sh_size;
const Elf64_Off offset = sheader.sh_offset;
m_shstr_data.SetData (m_data, offset, byte_size);
if (m_shstr_data.GetByteSize() != byte_size)
return 0;
}
}
return m_shstr_data.GetByteSize();
}
lldb::user_id_t
ObjectFileELF::GetSectionIndexByName(const char *name)
{
if (!(ParseSectionHeaders() && GetSectionHeaderStringTable()))
return 0;
// Search the collection of section headers for one with a matching name.
for (SectionHeaderCollIter I = m_section_headers.begin();
I != m_section_headers.end(); ++I)
{
const char *sectionName = m_shstr_data.PeekCStr(I->sh_name);
if (!sectionName)
return 0;
if (strcmp(name, sectionName) != 0)
continue;
return SectionIndex(I);
}
return 0;
}
const elf::ELFSectionHeader *
ObjectFileELF::GetSectionHeaderByIndex(lldb::user_id_t id)
{
if (!ParseSectionHeaders() || !id)
return NULL;
if (--id < m_section_headers.size())
return &m_section_headers[id];
return NULL;
}
static bool
ParseNoteGNUBuildID(DataExtractor& data, lldb_private::UUID& uuid)
ParseNoteGNUBuildID(DataExtractor &data, lldb_private::UUID &uuid)
{
// Try to parse the note section (ie .note.gnu.build-id|.notes|.note|...) and get the build id.
// BuildID documentation: https://fedoraproject.org/wiki/Releases/FeatureBuildId
@ -712,23 +726,158 @@ ParseNoteGNUBuildID(DataExtractor& data, lldb_private::UUID& uuid)
}
return false;
}
//----------------------------------------------------------------------
// GetSectionHeaderInfo
//----------------------------------------------------------------------
size_t
ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
lldb_private::DataExtractor &object_data,
const elf::ELFHeader &header,
lldb_private::UUID &uuid,
std::string &gnu_debuglink_file,
uint32_t &gnu_debuglink_crc)
{
// We have already parsed the section headers
if (!section_headers.empty())
return section_headers.size();
// If there are no section headers we are done.
if (header.e_shnum == 0)
return 0;
section_headers.resize(header.e_shnum);
if (section_headers.size() != header.e_shnum)
return 0;
const size_t sh_size = header.e_shnum * header.e_shentsize;
const elf_off sh_offset = header.e_shoff;
DataExtractor sh_data;
if (sh_data.SetData (object_data, sh_offset, sh_size) != sh_size)
return 0;
uint32_t idx;
lldb::offset_t offset;
for (idx = 0, offset = 0; idx < header.e_shnum; ++idx)
{
if (section_headers[idx].Parse(sh_data, &offset) == false)
break;
}
if (idx < section_headers.size())
section_headers.resize(idx);
const unsigned strtab_idx = header.e_shstrndx;
if (strtab_idx && strtab_idx < section_headers.size())
{
const ELFSectionHeaderInfo &sheader = section_headers[strtab_idx];
const size_t byte_size = sheader.sh_size;
const Elf64_Off offset = sheader.sh_offset;
lldb_private::DataExtractor shstr_data;
if (shstr_data.SetData (object_data, offset, byte_size) == byte_size)
{
for (SectionHeaderCollIter I = section_headers.begin();
I != section_headers.end(); ++I)
{
static ConstString g_sect_name_gnu_debuglink (".gnu_debuglink");
const ELFSectionHeaderInfo &header = *I;
const uint64_t section_size = header.sh_type == SHT_NOBITS ? 0 : header.sh_size;
ConstString name(shstr_data.PeekCStr(I->sh_name));
I->section_name = name;
if (name == g_sect_name_gnu_debuglink)
{
DataExtractor data;
if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size))
{
lldb::offset_t gnu_debuglink_offset = 0;
gnu_debuglink_file = data.GetCStr (&gnu_debuglink_offset);
gnu_debuglink_offset = llvm::RoundUpToAlignment (gnu_debuglink_offset, 4);
data.GetU32 (&gnu_debuglink_offset, &gnu_debuglink_crc, 1);
}
}
if (header.sh_type == SHT_NOTE && !uuid.IsValid())
{
DataExtractor data;
if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size))
{
ParseNoteGNUBuildID (data, uuid);
}
}
}
return section_headers.size();
}
}
section_headers.clear();
return 0;
}
//----------------------------------------------------------------------
// ParseSectionHeaders
//----------------------------------------------------------------------
size_t
ObjectFileELF::ParseSectionHeaders()
{
return GetSectionHeaderInfo(m_section_headers, m_data, m_header, m_uuid, m_gnu_debuglink_file, m_gnu_debuglink_crc);
}
lldb::user_id_t
ObjectFileELF::GetSectionIndexByName(const char *name)
{
if (!ParseSectionHeaders())
return 0;
// Search the collection of section headers for one with a matching name.
for (SectionHeaderCollIter I = m_section_headers.begin();
I != m_section_headers.end(); ++I)
{
const char *sectionName = I->section_name.AsCString();
if (!sectionName)
return 0;
if (strcmp(name, sectionName) != 0)
continue;
return SectionIndex(I);
}
return 0;
}
const ObjectFileELF::ELFSectionHeaderInfo *
ObjectFileELF::GetSectionHeaderByIndex(lldb::user_id_t id)
{
if (!ParseSectionHeaders() || !id)
return NULL;
if (--id < m_section_headers.size())
return &m_section_headers[id];
return NULL;
}
SectionList *
ObjectFileELF::GetSectionList()
{
if (m_sections_ap.get())
return m_sections_ap.get();
if (ParseSectionHeaders() && GetSectionHeaderStringTable())
if (ParseSectionHeaders())
{
m_sections_ap.reset(new SectionList());
for (SectionHeaderCollIter I = m_section_headers.begin();
I != m_section_headers.end(); ++I)
{
const ELFSectionHeader &header = *I;
const ELFSectionHeaderInfo &header = *I;
ConstString name(m_shstr_data.PeekCStr(header.sh_name));
ConstString& name = I->section_name;
const uint64_t file_size = header.sh_type == SHT_NOBITS ? 0 : header.sh_size;
const uint64_t vm_size = header.sh_flags & SHF_ALLOC ? header.sh_size : 0;
@ -753,7 +902,7 @@ ObjectFileELF::GetSectionList()
SectionType sect_type = eSectionTypeOther;
bool is_thread_specific = false;
if (name == g_sect_name_text) sect_type = eSectionTypeCode;
else if (name == g_sect_name_data) sect_type = eSectionTypeData;
else if (name == g_sect_name_bss) sect_type = eSectionTypeZeroFill;
@ -767,6 +916,19 @@ ObjectFileELF::GetSectionList()
sect_type = eSectionTypeZeroFill;
is_thread_specific = true;
}
// .debug_abbrev Abbreviations used in the .debug_info section
// .debug_aranges Lookup table for mapping addresses to compilation units
// .debug_frame Call frame information
// .debug_info The core DWARF information section
// .debug_line Line number information
// .debug_loc Location lists used in DW_AT_location attributes
// .debug_macinfo Macro information
// .debug_pubnames Lookup table for mapping object and function names to compilation units
// .debug_pubtypes Lookup table for mapping type names to compilation units
// .debug_ranges Address ranges used in DW_AT_ranges attributes
// .debug_str String table used in .debug_info
// MISSING? .debug-index http://src.chromium.org/viewvc/chrome/trunk/src/build/gdb-add-index?pathrev=144644
// MISSING? .debug_types - Type descriptions from DWARF 4? See http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo
else if (name == g_sect_name_dwarf_debug_abbrev) sect_type = eSectionTypeDWARFDebugAbbrev;
else if (name == g_sect_name_dwarf_debug_aranges) sect_type = eSectionTypeDWARFDebugAranges;
else if (name == g_sect_name_dwarf_debug_frame) sect_type = eSectionTypeDWARFDebugFrame;
@ -779,20 +941,31 @@ ObjectFileELF::GetSectionList()
else if (name == g_sect_name_dwarf_debug_ranges) sect_type = eSectionTypeDWARFDebugRanges;
else if (name == g_sect_name_dwarf_debug_str) sect_type = eSectionTypeDWARFDebugStr;
else if (name == g_sect_name_eh_frame) sect_type = eSectionTypeEHFrame;
else if (header.sh_type == SHT_NOTE)
switch (header.sh_type)
{
if (!m_uuid.IsValid())
{
DataExtractor data;
if (vm_size && (GetData (header.sh_offset, vm_size, data) == vm_size))
{
ParseNoteGNUBuildID (data, m_uuid);
}
}
case SHT_SYMTAB:
assert (sect_type == eSectionTypeOther);
sect_type = eSectionTypeELFSymbolTable;
break;
case SHT_DYNSYM:
assert (sect_type == eSectionTypeOther);
sect_type = eSectionTypeELFDynamicSymbols;
break;
case SHT_RELA:
case SHT_REL:
assert (sect_type == eSectionTypeOther);
sect_type = eSectionTypeELFRelocationEntries;
break;
case SHT_DYNAMIC:
assert (sect_type == eSectionTypeOther);
sect_type = eSectionTypeELFDynamicLinkInfo;
break;
}
SectionSP section_sp(new Section(
GetModule(), // Module to which this section belongs.
this, // ObjectFile to which this section belongs and should read section data from.
SectionIndex(I), // Section ID.
name, // Section name.
sect_type, // Section type.
@ -806,18 +979,18 @@ ObjectFileELF::GetSectionList()
section_sp->SetIsThreadSpecific (is_thread_specific);
m_sections_ap->AddSection(section_sp);
}
m_sections_ap->Finalize(); // Now that we're done adding sections, finalize to build fast-lookup caches
}
return m_sections_ap.get();
}
static unsigned
ParseSymbols(Symtab *symtab,
unsigned
ObjectFileELF::ParseSymbols(Symtab *symtab,
user_id_t start_id,
SectionList *section_list,
const ELFSectionHeader *symtab_shdr,
const ELFSectionHeaderInfo *symtab_shdr,
const DataExtractor &symtab_data,
const DataExtractor &strtab_data)
{
@ -936,6 +1109,29 @@ ParseSymbols(Symtab *symtab,
}
}
// If the symbol section we've found has no data (SHT_NOBITS), then check the module
// for the main object file and use the section there if it has data. This can happen
// if we're parsing the debug file and the it has no .text section, for example.
if (symbol_section_sp && (symbol_section_sp->GetFileSize() == 0))
{
ModuleSP module_sp(GetModule());
if (module_sp)
{
ObjectFile *obj_file = module_sp->GetObjectFile();
// Check if we've got a different object file than ourselves.
if (obj_file && (obj_file != this))
{
const ConstString &sect_name = symbol_section_sp->GetName();
SectionList *obj_file_section_list = obj_file->GetSectionList();
lldb::SectionSP section_sp (obj_file_section_list->FindSectionByName (sect_name));
if (section_sp && section_sp->GetFileSize())
{
symbol_section_sp = section_sp;
}
}
}
}
uint64_t symbol_value = symbol.st_value;
if (symbol_section_sp)
symbol_value -= symbol_section_sp->GetFileAddress();
@ -963,18 +1159,17 @@ ParseSymbols(Symtab *symtab,
}
unsigned
ObjectFileELF::ParseSymbolTable(Symtab *symbol_table, user_id_t start_id,
const ELFSectionHeader *symtab_hdr,
user_id_t symtab_id)
ObjectFileELF::ParseSymbolTable(Symtab *symbol_table, user_id_t start_id, user_id_t symtab_id)
{
assert(symtab_hdr->sh_type == SHT_SYMTAB ||
symtab_hdr->sh_type == SHT_DYNSYM);
// Parse in the section list if needed.
SectionList *section_list = GetSectionList();
if (!section_list)
return 0;
const ELFSectionHeaderInfo *symtab_hdr = &m_section_headers[symtab_id - 1];
assert(symtab_hdr->sh_type == SHT_SYMTAB ||
symtab_hdr->sh_type == SHT_DYNSYM);
// Section ID's are ones based.
user_id_t strtab_id = symtab_hdr->sh_link + 1;
@ -1040,10 +1235,6 @@ ObjectFileELF::FindDynamicSymbol(unsigned tag)
if (!ParseDynamicSymbols())
return NULL;
SectionList *section_list = GetSectionList();
if (!section_list)
return 0;
DynamicSymbolCollIter I = m_dynamic_symbols.begin();
DynamicSymbolCollIter E = m_dynamic_symbols.end();
for ( ; I != E; ++I)
@ -1057,21 +1248,6 @@ ObjectFileELF::FindDynamicSymbol(unsigned tag)
return NULL;
}
Section *
ObjectFileELF::PLTSection()
{
const ELFDynamic *symbol = FindDynamicSymbol(DT_JMPREL);
SectionList *section_list = GetSectionList();
if (symbol && section_list)
{
addr_t addr = symbol->d_ptr;
return section_list->FindSectionContainingFileAddress(addr).get();
}
return NULL;
}
unsigned
ObjectFileELF::PLTRelocationType()
{
@ -1160,12 +1336,12 @@ ParsePLTRelocations(Symtab *symbol_table,
unsigned
ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table,
user_id_t start_id,
const ELFSectionHeader *rel_hdr,
const ELFSectionHeaderInfo *rel_hdr,
user_id_t rel_id)
{
assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL);
// The link field points to the asscoiated symbol table. The info field
// The link field points to the associated symbol table. The info field
// points to the section holding the plt.
user_id_t symtab_id = rel_hdr->sh_link;
user_id_t plt_id = rel_hdr->sh_info;
@ -1177,11 +1353,11 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table,
symtab_id++;
plt_id++;
const ELFSectionHeader *plt_hdr = GetSectionHeaderByIndex(plt_id);
const ELFSectionHeaderInfo *plt_hdr = GetSectionHeaderByIndex(plt_id);
if (!plt_hdr)
return 0;
const ELFSectionHeader *sym_hdr = GetSectionHeaderByIndex(symtab_id);
const ELFSectionHeaderInfo *sym_hdr = GetSectionHeaderByIndex(symtab_id);
if (!sym_hdr)
return 0;
@ -1235,45 +1411,82 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table,
}
Symtab *
ObjectFileELF::GetSymtab()
ObjectFileELF::GetSymtab(uint32_t flags)
{
if (m_symtab_ap.get())
return m_symtab_ap.get();
Symtab *symbol_table = new Symtab(this);
m_symtab_ap.reset(symbol_table);
Mutex::Locker locker(symbol_table->GetMutex());
if (!(ParseSectionHeaders() && GetSectionHeaderStringTable()))
return symbol_table;
// Locate and parse all linker symbol tables.
uint64_t symbol_id = 0;
for (SectionHeaderCollIter I = m_section_headers.begin();
I != m_section_headers.end(); ++I)
ModuleSP module_sp(GetModule());
if (module_sp)
{
if (I->sh_type == SHT_SYMTAB || I->sh_type == SHT_DYNSYM)
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
bool from_unified_section_list = !!(flags & eSymtabFromUnifiedSectionList);
SectionList *section_list = from_unified_section_list ? module_sp->GetUnifiedSectionList() : GetSectionList();
if (!section_list)
return NULL;
// If we're doing the unified section list and it has been modified, then clear our
// cache and reload the symbols. If needed, we could check on only the sections that
// we use to create the symbol table...
std::unique_ptr<lldb_private::Symtab> &symtab_ap = from_unified_section_list ? m_symtab_unified_ap : m_symtab_ap;
if (from_unified_section_list && (m_symtab_unified_revisionid != section_list->GetRevisionID()))
{
const ELFSectionHeader &symtab_header = *I;
user_id_t section_id = SectionIndex(I);
symbol_id += ParseSymbolTable(symbol_table, symbol_id,
&symtab_header, section_id);
symtab_ap.reset();
m_symtab_unified_revisionid = section_list->GetRevisionID();
}
else if (symtab_ap.get())
{
return symtab_ap.get();
}
}
// Synthesize trampoline symbols to help navigate the PLT.
Section *reloc_section = PLTSection();
if (reloc_section)
{
user_id_t reloc_id = reloc_section->GetID();
const ELFSectionHeader *reloc_header = GetSectionHeaderByIndex(reloc_id);
assert(reloc_header);
ParseTrampolineSymbols(symbol_table, symbol_id, reloc_header, reloc_id);
}
Symtab *symbol_table = new Symtab(this);
symtab_ap.reset(symbol_table);
return symbol_table;
// Sharable objects and dynamic executables usually have 2 distinct symbol
// tables, one named ".symtab", and the other ".dynsym". The dynsym is a smaller
// version of the symtab that only contains global symbols. The information found
// in the dynsym is therefore also found in the symtab, while the reverse is not
// necessarily true.
Section *section_sym = section_list->FindSectionByType (eSectionTypeELFSymbolTable, true).get();
if (!section_sym)
{
// The symtab section is non-allocable and can be stripped, so if it doesn't exist
// then use the dynsym section which should always be there.
section_sym = section_list->FindSectionByType (eSectionTypeELFDynamicSymbols, true).get();
}
uint64_t symbol_id = 0;
if (section_sym)
{
user_id_t section_id = section_sym->GetID();
ObjectFileELF *obj_file_elf = static_cast<ObjectFileELF *>(section_sym->GetObjectFile());
symbol_id += obj_file_elf->ParseSymbolTable (symbol_table, symbol_id, section_id);
}
Section *section = section_list->FindSectionByType (eSectionTypeELFDynamicLinkInfo, true).get();
if (section)
{
ObjectFileELF *obj_file_elf = static_cast<ObjectFileELF *>(section->GetObjectFile());
// Synthesize trampoline symbols to help navigate the PLT.
const ELFDynamic *symbol = obj_file_elf->FindDynamicSymbol(DT_JMPREL);
if (symbol)
{
addr_t addr = symbol->d_ptr;
Section *reloc_section = section_list->FindSectionContainingFileAddress(addr).get();
if (reloc_section)
{
user_id_t reloc_id = reloc_section->GetID();
const ELFSectionHeaderInfo *reloc_header = obj_file_elf->GetSectionHeaderByIndex(reloc_id);
assert(reloc_header);
obj_file_elf->ParseTrampolineSymbols(symbol_table, symbol_id, reloc_header, reloc_id);
}
}
}
return symbol_table;
}
return NULL;
}
//===----------------------------------------------------------------------===//
@ -1472,7 +1685,7 @@ ObjectFileELF::DumpELFProgramHeaders(Stream *s)
// Dump a single ELF section header to the specified output stream
//----------------------------------------------------------------------
void
ObjectFileELF::DumpELFSectionHeader(Stream *s, const ELFSectionHeader &sh)
ObjectFileELF::DumpELFSectionHeader(Stream *s, const ELFSectionHeaderInfo &sh)
{
s->Printf("%8.8x ", sh.sh_name);
DumpELFSectionHeader_sh_type(s, sh.sh_type);
@ -1540,7 +1753,7 @@ ObjectFileELF::DumpELFSectionHeader_sh_flags(Stream *s, elf_xword sh_flags)
void
ObjectFileELF::DumpELFSectionHeaders(Stream *s)
{
if (!(ParseSectionHeaders() && GetSectionHeaderStringTable()))
if (!ParseSectionHeaders())
return;
s->PutCString("Section Headers\n");
@ -1557,7 +1770,7 @@ ObjectFileELF::DumpELFSectionHeaders(Stream *s)
{
s->Printf("[%2u] ", idx);
ObjectFileELF::DumpELFSectionHeader(s, *I);
const char* section_name = m_shstr_data.PeekCStr(I->sh_name);
const char* section_name = I->section_name.AsCString("");
if (section_name)
*s << ' ' << section_name << "\n";
}

View File

@ -100,7 +100,7 @@ public:
GetAddressByteSize() const;
virtual lldb_private::Symtab *
GetSymtab();
GetSymtab(uint32_t flags = 0);
virtual lldb_private::SectionList *
GetSectionList();
@ -114,6 +114,9 @@ public:
virtual bool
GetUUID(lldb_private::UUID* uuid);
virtual lldb_private::FileSpecList
GetDebugSymbolFilePaths();
virtual uint32_t
GetDependentModules(lldb_private::FileSpecList& files);
@ -141,7 +144,11 @@ private:
typedef ProgramHeaderColl::iterator ProgramHeaderCollIter;
typedef ProgramHeaderColl::const_iterator ProgramHeaderCollConstIter;
typedef std::vector<elf::ELFSectionHeader> SectionHeaderColl;
struct ELFSectionHeaderInfo : public elf::ELFSectionHeader
{
lldb_private::ConstString section_name;
};
typedef std::vector<ELFSectionHeaderInfo> SectionHeaderColl;
typedef SectionHeaderColl::iterator SectionHeaderCollIter;
typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter;
@ -155,9 +162,13 @@ private:
/// ELF file header.
elf::ELFHeader m_header;
/// ELF build ID
/// ELF build ID.
lldb_private::UUID m_uuid;
/// ELF .gnu_debuglink file and crc data if available.
std::string m_gnu_debuglink_file;
uint32_t m_gnu_debuglink_crc;
/// Collection of program headers.
ProgramHeaderColl m_program_headers;
@ -171,9 +182,6 @@ private:
/// libraries) on which this object file depends.
mutable std::unique_ptr<lldb_private::FileSpecList> m_filespec_ap;
/// Data extractor holding the string table used to resolve section names.
lldb_private::DataExtractor m_shstr_data;
/// Cached value of the entry point for this module.
lldb_private::Address m_entry_point_address;
@ -197,6 +205,15 @@ private:
size_t
ParseSectionHeaders();
/// Parses the elf section headers and returns the uuid, debug link name, crc.
static size_t
GetSectionHeaderInfo(SectionHeaderColl &section_headers,
lldb_private::DataExtractor &data,
const elf::ELFHeader &header,
lldb_private::UUID &uuid,
std::string &gnu_debuglink_file,
uint32_t &gnu_debuglink_crc);
/// Scans the dynamic section and locates all dependent modules (shared
/// libraries) populating m_filespec_ap. This method will compute the
/// dependent module list only once. Returns the number of dependent
@ -215,23 +232,26 @@ private:
unsigned
ParseSymbolTable(lldb_private::Symtab *symbol_table,
lldb::user_id_t start_id,
const elf::ELFSectionHeader *symtab_section,
lldb::user_id_t symtab_id);
/// Helper routine for ParseSymbolTable().
unsigned
ParseSymbols(lldb_private::Symtab *symbol_table,
lldb::user_id_t start_id,
lldb_private::SectionList *section_list,
const ELFSectionHeaderInfo *symtab_shdr,
const lldb_private::DataExtractor &symtab_data,
const lldb_private::DataExtractor &strtab_data);
/// Scans the relocation entries and adds a set of artificial symbols to the
/// given symbol table for each PLT slot. Returns the number of symbols
/// added.
unsigned
ParseTrampolineSymbols(lldb_private::Symtab *symbol_table,
lldb::user_id_t start_id,
const elf::ELFSectionHeader *rela_hdr,
const ELFSectionHeaderInfo *rela_hdr,
lldb::user_id_t section_id);
/// Loads the section name string table into m_shstr_data. Returns the
/// number of bytes constituting the table.
size_t
GetSectionHeaderStringTable();
/// Utility method for looking up a section given its name. Returns the
/// index of the corresponding section or zero if no section with the given
/// name can be found (note that section indices are always 1 based, and so
@ -244,7 +264,7 @@ private:
GetSectionIndexByType(unsigned type);
/// Returns the section header with the given id or NULL.
const elf::ELFSectionHeader *
const ELFSectionHeaderInfo *
GetSectionHeaderByIndex(lldb::user_id_t id);
/// @name ELF header dump routines
@ -284,7 +304,7 @@ private:
static void
DumpELFSectionHeader(lldb_private::Stream *s,
const elf::ELFSectionHeader& sh);
const ELFSectionHeaderInfo& sh);
static void
DumpELFSectionHeader_sh_type(lldb_private::Stream *s,
@ -302,9 +322,6 @@ private:
const elf::ELFDynamic *
FindDynamicSymbol(unsigned tag);
lldb_private::Section *
PLTSection();
unsigned
PLTRelocationType();
};

View File

@ -838,6 +838,10 @@ ObjectFileMachO::GetAddressClass (lldb::addr_t file_addr)
case eSectionTypeDWARFAppleObjC:
return eAddressClassDebug;
case eSectionTypeEHFrame: return eAddressClassRuntime;
case eSectionTypeELFSymbolTable:
case eSectionTypeELFDynamicSymbols:
case eSectionTypeELFRelocationEntries:
case eSectionTypeELFDynamicLinkInfo:
case eSectionTypeOther: return eAddressClassUnknown;
}
}
@ -891,7 +895,7 @@ ObjectFileMachO::GetAddressClass (lldb::addr_t file_addr)
}
Symtab *
ObjectFileMachO::GetSymtab()
ObjectFileMachO::GetSymtab(uint32_t flags)
{
ModuleSP module_sp(GetModule());
if (module_sp)
@ -1033,6 +1037,7 @@ ObjectFileMachO::ParseSections ()
if (segment_name || is_core)
{
segment_sp.reset(new Section (module_sp, // Module to which this section belongs
this, // Object file to which this sections belongs
++segID << 8, // Section ID is the 1 based segment index shifted right by 8 bits as not to collide with any of the 256 section IDs that are possible
segment_name, // Name of this section
eSectionTypeContainer, // This section is a container of other sections.
@ -1129,7 +1134,8 @@ ObjectFileMachO::ParseSections ()
{
// Create a fake section for the section's named segment
segment_sp.reset(new Section (segment_sp, // Parent section
module_sp, // Module to which this section belongs
module_sp, // Module to which this section belongs
this, // Object file to which this section belongs
++segID << 8, // Section ID is the 1 based segment index shifted right by 8 bits as not to collide with any of the 256 section IDs that are possible
segment_name, // Name of this section
eSectionTypeContainer, // This section is a container of other sections.
@ -1258,6 +1264,7 @@ ObjectFileMachO::ParseSections ()
SectionSP section_sp(new Section (segment_sp,
module_sp,
this,
++sectID,
section_name,
sect_type,

View File

@ -102,7 +102,7 @@ public:
GetAddressClass (lldb::addr_t file_addr);
virtual lldb_private::Symtab *
GetSymtab();
GetSymtab(uint32_t flags = 0);
virtual lldb_private::SectionList *
GetSectionList();

View File

@ -511,7 +511,7 @@ ObjectFilePECOFF::GetSectionName(std::string& sect_name, const section_header_t&
// GetNListSymtab
//----------------------------------------------------------------------
Symtab *
ObjectFilePECOFF::GetSymtab()
ObjectFilePECOFF::GetSymtab(uint32_t flags)
{
ModuleSP module_sp(GetModule());
if (module_sp)
@ -698,9 +698,10 @@ ObjectFilePECOFF::GetSectionList()
// Use a segment ID of the segment index shifted left by 8 so they
// never conflict with any of the sections.
SectionSP section_sp (new Section (module_sp, // Module to which this section belongs
this, // Object file to which this section belongs
idx + 1, // Section ID is the 1 based segment index shifted right by 8 bits as not to collide with any of the 256 section IDs that are possible
const_sect_name, // Name of this section
section_type, // This section is a container of other sections.
section_type, // This section is a container of other sections.
m_coff_header_opt.image_base + m_sect_headers[idx].vmaddr, // File VM address == addresses as they are found in the object file
m_sect_headers[idx].vmsize, // VM size in bytes of this section
m_sect_headers[idx].offset, // Offset to the data for this section in the file

View File

@ -86,7 +86,7 @@ public:
// GetAddressClass (lldb::addr_t file_addr);
//
virtual lldb_private::Symtab *
GetSymtab();
GetSymtab(uint32_t flags = 0);
virtual lldb_private::SectionList *
GetSectionList();

View File

@ -81,7 +81,7 @@ ProcessPOSIX::ProcessPOSIX(Target& target, Listener &listener)
// FIXME: Putting this code in the ctor and saving the byte order in a
// member variable is a hack to avoid const qual issues in GetByteOrder.
lldb::ModuleSP module = GetTarget().GetExecutableModule();
if (module != NULL && module->GetObjectFile() != NULL)
if (module && module->GetObjectFile())
m_byte_order = module->GetObjectFile()->GetByteOrder();
}

View File

@ -543,7 +543,7 @@ SymbolFileDWARF::InitializeObject()
ModuleSP module_sp (m_obj_file->GetModule());
if (module_sp)
{
const SectionList *section_list = m_obj_file->GetSectionList();
const SectionList *section_list = module_sp->GetUnifiedSectionList();
const Section* section = section_list->FindSectionByName(GetDWARFMachOSegmentName ()).get();
@ -704,8 +704,9 @@ SymbolFileDWARF::GetCachedSectionData (uint32_t got_flag, SectionType sect_type,
{
if (m_flags.IsClear (got_flag))
{
ModuleSP module_sp (m_obj_file->GetModule());
m_flags.Set (got_flag);
const SectionList *section_list = m_obj_file->GetSectionList();
const SectionList *section_list = module_sp->GetUnifiedSectionList();
if (section_list)
{
SectionSP section_sp (section_list->FindSectionByType(sect_type, true));
@ -1054,7 +1055,8 @@ SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, DWARFCompile
lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd (0);
if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr)
{
func_range.GetBaseAddress().ResolveAddressUsingFileSections (lowest_func_addr, m_obj_file->GetSectionList());
ModuleSP module_sp (m_obj_file->GetModule());
func_range.GetBaseAddress().ResolveAddressUsingFileSections (lowest_func_addr, module_sp->GetUnifiedSectionList());
if (func_range.GetBaseAddress().IsValid())
func_range.SetByteSize(highest_func_addr - lowest_func_addr);
}
@ -4721,7 +4723,7 @@ SymbolFileDWARF::GetObjCClassSymbol (const ConstString &objc_class_name)
Symbol *objc_class_symbol = NULL;
if (m_obj_file)
{
Symtab *symtab = m_obj_file->GetSymtab();
Symtab *symtab = m_obj_file->GetSymtab (ObjectFile::eSymtabFromUnifiedSectionList);
if (symtab)
{
objc_class_symbol = symtab->FindFirstSymbolWithNameAndType (objc_class_name,
@ -7429,13 +7431,12 @@ SymbolFileDWARF::ParseVariableDIE
bool linked_oso_file_addr = false;
if (is_external && location_DW_OP_addr == 0)
{
// we have a possible uninitialized extern global
ConstString const_name(mangled ? mangled : name);
ObjectFile *debug_map_objfile = debug_map_symfile->GetObjectFile();
if (debug_map_objfile)
{
Symtab *debug_map_symtab = debug_map_objfile->GetSymtab();
Symtab *debug_map_symtab = debug_map_objfile->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList);
if (debug_map_symtab)
{
Symbol *exe_symbol = debug_map_symtab->FindFirstSymbolWithNameAndType (const_name,

View File

@ -75,9 +75,9 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa
{
for (auto comp_unit_info : cu_infos)
{
Symtab *exe_symtab = exe_symfile->GetObjectFile()->GetSymtab();
Symtab *exe_symtab = exe_symfile->GetObjectFile()->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList);
ModuleSP oso_module_sp (oso_objfile->GetModule());
Symtab *oso_symtab = oso_objfile->GetSymtab();
Symtab *oso_symtab = oso_objfile->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList);
///const uint32_t fun_resolve_flags = SymbolContext::Module | eSymbolContextCompUnit | eSymbolContextFunction;
//SectionList *oso_sections = oso_objfile->Sections();
@ -169,7 +169,7 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa
exe_symfile->FinalizeOSOFileRanges (this);
// We don't need the symbols anymore for the .o files
oso_objfile->ClearSymtab();
oso_objfile->ClearSymtab(ObjectFile::eSymtabFromUnifiedSectionList);
}
}
return file_range_map;
@ -330,7 +330,7 @@ SymbolFileDWARFDebugMap::InitOSO()
// these files exist and also contain valid DWARF. If we get any of that
// then we return the abilities of the first N_OSO's DWARF.
Symtab* symtab = m_obj_file->GetSymtab();
Symtab* symtab = m_obj_file->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList);
if (symtab)
{
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP));
@ -777,7 +777,7 @@ uint32_t
SymbolFileDWARFDebugMap::ResolveSymbolContext (const Address& exe_so_addr, uint32_t resolve_scope, SymbolContext& sc)
{
uint32_t resolved_flags = 0;
Symtab* symtab = m_obj_file->GetSymtab();
Symtab* symtab = m_obj_file->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList);
if (symtab)
{
const addr_t exe_file_addr = exe_so_addr.GetFileAddress();

View File

@ -93,7 +93,7 @@ SymbolFileSymtab::CalculateAbilities ()
uint32_t abilities = 0;
if (m_obj_file)
{
const Symtab *symtab = m_obj_file->GetSymtab();
const Symtab *symtab = m_obj_file->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList);
if (symtab)
{
//----------------------------------------------------------------------
@ -159,7 +159,7 @@ SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx)
// the entire object file
if (idx < m_source_indexes.size())
{
const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]);
const Symbol *cu_symbol = m_obj_file->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList)->SymbolAtIndex(m_source_indexes[idx]);
if (cu_symbol)
cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetMangled().GetName().AsCString(), 0, eLanguageTypeUnknown));
}
@ -179,7 +179,7 @@ SymbolFileSymtab::ParseCompileUnitFunctions (const SymbolContext &sc)
size_t num_added = 0;
// We must at least have a valid compile unit
assert (sc.comp_unit != NULL);
const Symtab *symtab = m_obj_file->GetSymtab();
const Symtab *symtab = m_obj_file->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList);
const Symbol *curr_symbol = NULL;
const Symbol *next_symbol = NULL;
// const char *prefix = m_obj_file->SymbolPrefix();
@ -307,13 +307,13 @@ SymbolFileSymtab::FindNamespace (const SymbolContext& sc, const ConstString &nam
uint32_t
SymbolFileSymtab::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
{
if (m_obj_file->GetSymtab() == NULL)
if (m_obj_file->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList) == NULL)
return 0;
uint32_t resolved_flags = 0;
if (resolve_scope & eSymbolContextSymbol)
{
sc.symbol = m_obj_file->GetSymtab()->FindSymbolContainingFileAddress(so_addr.GetFileAddress());
sc.symbol = m_obj_file->GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList)->FindSymbolContainingFileAddress(so_addr.GetFileAddress());
if (sc.symbol)
resolved_flags |= eSymbolContextSymbol;
}

View File

@ -1,3 +1,5 @@
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
add_subdirectory(MacOSX)
endif()
add_subdirectory(ELF)

View File

@ -0,0 +1,5 @@
set(LLVM_NO_RTTI 1)
add_lldb_library(lldbPluginSymbolVendorELF
SymbolVendorELF.cpp
)

View File

@ -0,0 +1,14 @@
##===- source/Plugins/SymbolVendor/ELF/Makefile ---------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
LLDB_LEVEL := ../../../..
LIBRARYNAME := lldbPluginSymbolVendorELF
BUILD_ARCHIVE = 1
include $(LLDB_LEVEL)/Makefile

View File

@ -0,0 +1,200 @@
//===-- SymbolVendorELF.cpp ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "SymbolVendorELF.h"
//#include <libxml/parser.h>
// #include <libxml/tree.h>
#include <string.h>
// #include <AvailabilityMacros.h>
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/Symbols.h"
#include "lldb/Symbol/ObjectFile.h"
using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
// SymbolVendorELF constructor
//----------------------------------------------------------------------
SymbolVendorELF::SymbolVendorELF(const lldb::ModuleSP &module_sp) :
SymbolVendor (module_sp)
{
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
SymbolVendorELF::~SymbolVendorELF()
{
}
void
SymbolVendorELF::Initialize()
{
PluginManager::RegisterPlugin (GetPluginNameStatic(),
GetPluginDescriptionStatic(),
CreateInstance);
}
void
SymbolVendorELF::Terminate()
{
PluginManager::UnregisterPlugin (CreateInstance);
}
lldb_private::ConstString
SymbolVendorELF::GetPluginNameStatic()
{
static ConstString g_name("ELF");
return g_name;
}
const char *
SymbolVendorELF::GetPluginDescriptionStatic()
{
return "Symbol vendor for ELF that looks for dSYM files that match executables.";
}
//----------------------------------------------------------------------
// CreateInstance
//
// Platforms can register a callback to use when creating symbol
// vendors to allow for complex debug information file setups, and to
// also allow for finding separate debug information files.
//----------------------------------------------------------------------
SymbolVendor*
SymbolVendorELF::CreateInstance (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm)
{
if (!module_sp)
return NULL;
ObjectFile *obj_file = module_sp->GetObjectFile();
if (!obj_file)
return NULL;
static ConstString obj_file_elf("elf");
ConstString obj_name = obj_file->GetPluginName();
if (obj_name != obj_file_elf)
return NULL;
lldb_private::UUID uuid;
if (!obj_file->GetUUID (&uuid))
return NULL;
// Get the .gnu_debuglink file (if specified).
FileSpecList file_spec_list = obj_file->GetDebugSymbolFilePaths();
// If the module specified a filespec, use it first.
FileSpec debug_symbol_fspec (module_sp->GetSymbolFileFileSpec());
if (debug_symbol_fspec)
file_spec_list.Insert (0, debug_symbol_fspec);
// If we have no debug symbol files, then nothing to do.
if (file_spec_list.IsEmpty())
return NULL;
Timer scoped_timer (__PRETTY_FUNCTION__,
"SymbolVendorELF::CreateInstance (module = %s)",
module_sp->GetFileSpec().GetPath().c_str());
for (size_t idx = 0; idx < file_spec_list.GetSize(); ++idx)
{
ModuleSpec module_spec;
const FileSpec fspec = file_spec_list.GetFileSpecAtIndex (idx);
module_spec.GetFileSpec() = obj_file->GetFileSpec();
module_spec.GetFileSpec().ResolvePath();
module_spec.GetSymbolFileSpec() = fspec;
module_spec.GetUUID() = uuid;
FileSpec dsym_fspec = Symbols::LocateExecutableSymbolFile (module_spec);
if (dsym_fspec)
{
DataBufferSP dsym_file_data_sp;
lldb::offset_t dsym_file_data_offset = 0;
ObjectFileSP dsym_objfile_sp = ObjectFile::FindPlugin(module_sp, &dsym_fspec, 0, dsym_fspec.GetByteSize(), dsym_file_data_sp, dsym_file_data_offset);
if (dsym_objfile_sp)
{
// This objfile is for debugging purposes. Sadly, ObjectFileELF won't be able
// to figure this out consistently as the symbol file may not have stripped the
// code sections, etc.
dsym_objfile_sp->SetType (ObjectFile::eTypeDebugInfo);
SymbolVendorELF* symbol_vendor = new SymbolVendorELF(module_sp);
if (symbol_vendor)
{
// Get the module unified section list and add our debug sections to that.
SectionList *module_section_list = module_sp->GetUnifiedSectionList();
SectionList *objfile_section_list = dsym_objfile_sp->GetSectionList();
static const SectionType g_sections[] =
{
eSectionTypeDWARFDebugAranges,
eSectionTypeDWARFDebugInfo,
eSectionTypeDWARFDebugAbbrev,
eSectionTypeDWARFDebugFrame,
eSectionTypeDWARFDebugLine,
eSectionTypeDWARFDebugStr,
eSectionTypeDWARFDebugLoc,
eSectionTypeDWARFDebugMacInfo,
eSectionTypeDWARFDebugPubNames,
eSectionTypeDWARFDebugPubTypes,
eSectionTypeDWARFDebugRanges,
eSectionTypeELFSymbolTable,
};
for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]); ++idx)
{
SectionType section_type = g_sections[idx];
SectionSP section_sp (objfile_section_list->FindSectionByType (section_type, true));
if (section_sp)
{
SectionSP module_section_sp (module_section_list->FindSectionByType (section_type, true));
if (module_section_sp)
module_section_list->ReplaceSection (module_section_sp->GetID(), section_sp);
else
module_section_list->AddSection (section_sp);
}
}
module_section_list->Finalize();
symbol_vendor->AddSymbolFileRepresentation (dsym_objfile_sp);
return symbol_vendor;
}
}
}
}
return NULL;
}
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
ConstString
SymbolVendorELF::GetPluginName()
{
return GetPluginNameStatic();
}
uint32_t
SymbolVendorELF::GetPluginVersion()
{
return 1;
}

View File

@ -0,0 +1,58 @@
//===-- SymbolVendorELF.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_SymbolVendorELF_h_
#define liblldb_SymbolVendorELF_h_
#include "lldb/lldb-private.h"
#include "lldb/Symbol/SymbolVendor.h"
class SymbolVendorELF : public lldb_private::SymbolVendor
{
public:
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
static void
Initialize();
static void
Terminate();
static lldb_private::ConstString
GetPluginNameStatic();
static const char *
GetPluginDescriptionStatic();
static lldb_private::SymbolVendor*
CreateInstance (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm);
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
SymbolVendorELF (const lldb::ModuleSP &module_sp);
virtual
~SymbolVendorELF();
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
virtual lldb_private::ConstString
GetPluginName();
virtual uint32_t
GetPluginVersion();
private:
DISALLOW_COPY_AND_ASSIGN (SymbolVendorELF);
};
#endif // liblldb_SymbolVendorELF_h_

View File

@ -83,7 +83,7 @@ UUIDsMatch(Module *module, ObjectFile *ofile, lldb_private::Stream *feedback_str
return false;
}
static void
static bool
ReplaceDSYMSectionsWithExecutableSections (ObjectFile *exec_objfile, ObjectFile *dsym_objfile)
{
// We need both the executable and the dSYM to live off of the
@ -123,7 +123,9 @@ ReplaceDSYMSectionsWithExecutableSections (ObjectFile *exec_objfile, ObjectFile
}
dsym_section_list->Finalize(); // Now that we're done adding sections, finalize to build fast-lookup caches
return true;
}
return false;
}
void
@ -169,6 +171,15 @@ SymbolVendorMacOSX::CreateInstance (const lldb::ModuleSP &module_sp, lldb_privat
if (!module_sp)
return NULL;
ObjectFile * obj_file = module_sp->GetObjectFile();
if (!obj_file)
return NULL;
static ConstString obj_file_macho("mach-o");
ConstString obj_name = obj_file->GetPluginName();
if (obj_name != obj_file_macho)
return NULL;
Timer scoped_timer (__PRETTY_FUNCTION__,
"SymbolVendorMacOSX::CreateInstance (module = %s)",
module_sp->GetFileSpec().GetPath().c_str());
@ -179,119 +190,115 @@ SymbolVendorMacOSX::CreateInstance (const lldb::ModuleSP &module_sp, lldb_privat
path[0] = '\0';
// Try and locate the dSYM file on Mac OS X
ObjectFile * obj_file = module_sp->GetObjectFile();
if (obj_file)
{
Timer scoped_timer2 ("SymbolVendorMacOSX::CreateInstance () locate dSYM",
"SymbolVendorMacOSX::CreateInstance (module = %s) locate dSYM",
module_sp->GetFileSpec().GetPath().c_str());
Timer scoped_timer2 ("SymbolVendorMacOSX::CreateInstance () locate dSYM",
"SymbolVendorMacOSX::CreateInstance (module = %s) locate dSYM",
module_sp->GetFileSpec().GetPath().c_str());
// First check to see if the module has a symbol file in mind already.
// If it does, then we MUST use that.
FileSpec dsym_fspec (module_sp->GetSymbolFileFileSpec());
// First check to see if the module has a symbol file in mind already.
// If it does, then we MUST use that.
FileSpec dsym_fspec (module_sp->GetSymbolFileFileSpec());
ObjectFileSP dsym_objfile_sp;
if (!dsym_fspec)
{
// No symbol file was specified in the module, lets try and find
// one ourselves.
FileSpec file_spec = obj_file->GetFileSpec();
if (!file_spec)
file_spec = module_sp->GetFileSpec();
ObjectFileSP dsym_objfile_sp;
if (!dsym_fspec)
{
// No symbol file was specified in the module, lets try and find
// one ourselves.
FileSpec file_spec = obj_file->GetFileSpec();
if (!file_spec)
file_spec = module_sp->GetFileSpec();
ModuleSpec module_spec(file_spec, module_sp->GetArchitecture());
module_spec.GetUUID() = module_sp->GetUUID();
dsym_fspec = Symbols::LocateExecutableSymbolFile (module_spec);
if (module_spec.GetSourceMappingList().GetSize())
module_sp->GetSourceMappingList().Append (module_spec.GetSourceMappingList (), true);
}
ModuleSpec module_spec(file_spec, module_sp->GetArchitecture());
module_spec.GetUUID() = module_sp->GetUUID();
dsym_fspec = Symbols::LocateExecutableSymbolFile (module_spec);
if (module_spec.GetSourceMappingList().GetSize())
module_sp->GetSourceMappingList().Append (module_spec.GetSourceMappingList (), true);
}
if (dsym_fspec)
if (dsym_fspec)
{
DataBufferSP dsym_file_data_sp;
lldb::offset_t dsym_file_data_offset = 0;
dsym_objfile_sp = ObjectFile::FindPlugin(module_sp, &dsym_fspec, 0, dsym_fspec.GetByteSize(), dsym_file_data_sp, dsym_file_data_offset);
if (UUIDsMatch(module_sp.get(), dsym_objfile_sp.get(), feedback_strm))
{
DataBufferSP dsym_file_data_sp;
lldb::offset_t dsym_file_data_offset = 0;
dsym_objfile_sp = ObjectFile::FindPlugin(module_sp, &dsym_fspec, 0, dsym_fspec.GetByteSize(), dsym_file_data_sp, dsym_file_data_offset);
if (UUIDsMatch(module_sp.get(), dsym_objfile_sp.get(), feedback_strm))
char dsym_path[PATH_MAX];
if (module_sp->GetSourceMappingList().IsEmpty() && dsym_fspec.GetPath(dsym_path, sizeof(dsym_path)))
{
char dsym_path[PATH_MAX];
if (module_sp->GetSourceMappingList().IsEmpty() && dsym_fspec.GetPath(dsym_path, sizeof(dsym_path)))
lldb_private::UUID dsym_uuid;
if (dsym_objfile_sp->GetUUID(&dsym_uuid))
{
lldb_private::UUID dsym_uuid;
if (dsym_objfile_sp->GetUUID(&dsym_uuid))
std::string uuid_str = dsym_uuid.GetAsString ();
if (!uuid_str.empty())
{
std::string uuid_str = dsym_uuid.GetAsString ();
if (!uuid_str.empty())
char *resources = strstr (dsym_path, "/Contents/Resources/");
if (resources)
{
char *resources = strstr (dsym_path, "/Contents/Resources/");
if (resources)
char dsym_uuid_plist_path[PATH_MAX];
resources[strlen("/Contents/Resources/")] = '\0';
snprintf(dsym_uuid_plist_path, sizeof(dsym_uuid_plist_path), "%s%s.plist", dsym_path, uuid_str.c_str());
FileSpec dsym_uuid_plist_spec(dsym_uuid_plist_path, false);
if (dsym_uuid_plist_spec.Exists())
{
char dsym_uuid_plist_path[PATH_MAX];
resources[strlen("/Contents/Resources/")] = '\0';
snprintf(dsym_uuid_plist_path, sizeof(dsym_uuid_plist_path), "%s%s.plist", dsym_path, uuid_str.c_str());
FileSpec dsym_uuid_plist_spec(dsym_uuid_plist_path, false);
if (dsym_uuid_plist_spec.Exists())
xmlDoc *doc = ::xmlReadFile (dsym_uuid_plist_path, NULL, 0);
if (doc)
{
xmlDoc *doc = ::xmlReadFile (dsym_uuid_plist_path, NULL, 0);
if (doc)
char DBGBuildSourcePath[PATH_MAX];
char DBGSourcePath[PATH_MAX];
DBGBuildSourcePath[0] = '\0';
DBGSourcePath[0] = '\0';
for (xmlNode *node = doc->children; node; node = node ? node->next : NULL)
{
char DBGBuildSourcePath[PATH_MAX];
char DBGSourcePath[PATH_MAX];
DBGBuildSourcePath[0] = '\0';
DBGSourcePath[0] = '\0';
for (xmlNode *node = doc->children; node; node = node ? node->next : NULL)
if (node->type == XML_ELEMENT_NODE)
{
if (node->type == XML_ELEMENT_NODE)
if (node->name && strcmp((const char*)node->name, "plist") == 0)
{
if (node->name && strcmp((const char*)node->name, "plist") == 0)
xmlNode *dict_node = node->children;
while (dict_node && dict_node->type != XML_ELEMENT_NODE)
dict_node = dict_node->next;
if (dict_node && dict_node->name && strcmp((const char *)dict_node->name, "dict") == 0)
{
xmlNode *dict_node = node->children;
while (dict_node && dict_node->type != XML_ELEMENT_NODE)
dict_node = dict_node->next;
if (dict_node && dict_node->name && strcmp((const char *)dict_node->name, "dict") == 0)
for (xmlNode *key_node = dict_node->children; key_node; key_node = key_node->next)
{
for (xmlNode *key_node = dict_node->children; key_node; key_node = key_node->next)
if (key_node && key_node->type == XML_ELEMENT_NODE && key_node->name)
{
if (key_node && key_node->type == XML_ELEMENT_NODE && key_node->name)
if (strcmp((const char *)key_node->name, "key") == 0)
{
if (strcmp((const char *)key_node->name, "key") == 0)
const char *key_name = (const char *)::xmlNodeGetContent(key_node);
if (strcmp(key_name, "DBGBuildSourcePath") == 0)
{
const char *key_name = (const char *)::xmlNodeGetContent(key_node);
if (strcmp(key_name, "DBGBuildSourcePath") == 0)
xmlNode *value_node = key_node->next;
while (value_node && value_node->type != XML_ELEMENT_NODE)
value_node = value_node->next;
if (value_node && value_node->name)
{
xmlNode *value_node = key_node->next;
while (value_node && value_node->type != XML_ELEMENT_NODE)
value_node = value_node->next;
if (value_node && value_node->name)
if (strcmp((const char *)value_node->name, "string") == 0)
{
if (strcmp((const char *)value_node->name, "string") == 0)
const char *node_content = (const char *)::xmlNodeGetContent(value_node);
if (node_content)
{
const char *node_content = (const char *)::xmlNodeGetContent(value_node);
if (node_content)
{
strncpy(DBGBuildSourcePath, node_content, sizeof(DBGBuildSourcePath));
}
strncpy(DBGBuildSourcePath, node_content, sizeof(DBGBuildSourcePath));
}
key_node = value_node;
}
key_node = value_node;
}
else if (strcmp(key_name, "DBGSourcePath") == 0)
}
else if (strcmp(key_name, "DBGSourcePath") == 0)
{
xmlNode *value_node = key_node->next;
while (value_node && value_node->type != XML_ELEMENT_NODE)
value_node = value_node->next;
if (value_node && value_node->name)
{
xmlNode *value_node = key_node->next;
while (value_node && value_node->type != XML_ELEMENT_NODE)
value_node = value_node->next;
if (value_node && value_node->name)
if (strcmp((const char *)value_node->name, "string") == 0)
{
if (strcmp((const char *)value_node->name, "string") == 0)
const char *node_content = (const char *)::xmlNodeGetContent(value_node);
if (node_content)
{
const char *node_content = (const char *)::xmlNodeGetContent(value_node);
if (node_content)
{
FileSpec resolved_source_path(node_content, true);
resolved_source_path.GetPath(DBGSourcePath, sizeof(DBGSourcePath));
}
FileSpec resolved_source_path(node_content, true);
resolved_source_path.GetPath(DBGSourcePath, sizeof(DBGSourcePath));
}
key_node = value_node;
}
key_node = value_node;
}
}
}
@ -300,30 +307,39 @@ SymbolVendorMacOSX::CreateInstance (const lldb::ModuleSP &module_sp, lldb_privat
}
}
}
::xmlFreeDoc (doc);
}
::xmlFreeDoc (doc);
if (DBGBuildSourcePath[0] && DBGSourcePath[0])
{
module_sp->GetSourceMappingList().Append (ConstString(DBGBuildSourcePath), ConstString(DBGSourcePath), true);
}
if (DBGBuildSourcePath[0] && DBGSourcePath[0])
{
module_sp->GetSourceMappingList().Append (ConstString(DBGBuildSourcePath), ConstString(DBGSourcePath), true);
}
}
}
}
}
}
ReplaceDSYMSectionsWithExecutableSections (obj_file, dsym_objfile_sp.get());
symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp);
return symbol_vendor;
}
}
// Just create our symbol vendor using the current objfile as this is either
// an executable with no dSYM (that we could locate), an executable with
// a dSYM that has a UUID that doesn't match.
symbol_vendor->AddSymbolFileRepresentation(obj_file->shared_from_this());
if (ReplaceDSYMSectionsWithExecutableSections (obj_file, dsym_objfile_sp.get()))
{
SectionList *section_list = dsym_objfile_sp.get()->GetSectionList();
if (section_list)
{
section_list->Copy (module_sp->GetUnifiedSectionList());
section_list->Finalize ();
}
}
symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp);
return symbol_vendor;
}
}
// Just create our symbol vendor using the current objfile as this is either
// an executable with no dSYM (that we could locate), an executable with
// a dSYM that has a UUID that doesn't match.
symbol_vendor->AddSymbolFileRepresentation(obj_file->shared_from_this());
}
return symbol_vendor;
}

View File

@ -568,9 +568,9 @@ Function::GetPrologueByteSize ()
// Check the first few instructions and look for one that has
// is_prologue_end set to true.
const uint32_t last_line_entry_idx = first_line_entry_idx + 6;
LineEntry line_entry;
for (uint32_t idx = first_line_entry_idx + 1; idx < last_line_entry_idx; ++idx)
{
LineEntry line_entry;
if (line_table->GetLineEntryAtIndex (idx, line_entry))
{
if (line_entry.is_prologue_end)
@ -581,12 +581,31 @@ Function::GetPrologueByteSize ()
}
}
}
// If we didn't find the end of the prologue in the line tables,
// then just use the end address of the first line table entry
if (prologue_end_file_addr == LLDB_INVALID_ADDRESS)
{
prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress() + first_line_entry.range.GetByteSize();
// Check the first few instructions and look for one that has
// a line number that's different than the first entry.
const uint32_t last_line_entry_idx = first_line_entry_idx + 6;
for (uint32_t idx = first_line_entry_idx + 1; idx < last_line_entry_idx; ++idx)
{
LineEntry line_entry;
if (line_table->GetLineEntryAtIndex (idx, line_entry))
{
if (line_entry.line != first_line_entry.line)
{
prologue_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress();
break;
}
}
}
if (prologue_end_file_addr == LLDB_INVALID_ADDRESS)
{
prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress() + first_line_entry.range.GetByteSize();
}
}
const addr_t func_start_file_addr = m_range.GetBaseAddress().GetFileAddress();
const addr_t func_end_file_addr = func_start_file_addr + m_range.GetByteSize();

View File

@ -244,7 +244,9 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp,
m_process_wp(),
m_memory_addr (LLDB_INVALID_ADDRESS),
m_sections_ap (),
m_symtab_ap ()
m_symtab_ap (),
m_symtab_unified_ap (),
m_symtab_unified_revisionid (0)
{
if (file_spec_ptr)
m_file = *file_spec_ptr;
@ -291,7 +293,9 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp,
m_process_wp (process_sp),
m_memory_addr (header_addr),
m_sections_ap (),
m_symtab_ap ()
m_symtab_ap (),
m_symtab_unified_ap (),
m_symtab_unified_revisionid (0)
{
if (header_data_sp)
m_data.SetData (header_data_sp, 0, header_data_sp->GetByteSize());
@ -327,7 +331,7 @@ ObjectFile::SetModulesArchitecture (const ArchSpec &new_arch)
AddressClass
ObjectFile::GetAddressClass (addr_t file_addr)
{
Symtab *symtab = GetSymtab();
Symtab *symtab = GetSymtab(ObjectFile::eSymtabFromUnifiedSectionList);
if (symtab)
{
Symbol *symbol = symtab->FindSymbolContainingFileAddress(file_addr);
@ -374,6 +378,10 @@ ObjectFile::GetAddressClass (addr_t file_addr)
case eSectionTypeDWARFAppleObjC:
return eAddressClassDebug;
case eSectionTypeEHFrame: return eAddressClassRuntime;
case eSectionTypeELFSymbolTable:
case eSectionTypeELFDynamicSymbols:
case eSectionTypeELFRelocationEntries:
case eSectionTypeELFDynamicLinkInfo:
case eSectionTypeOther: return eAddressClassUnknown;
}
}
@ -453,6 +461,10 @@ ObjectFile::CopyData (off_t offset, size_t length, void *dst) const
size_t
ObjectFile::ReadSectionData (const Section *section, off_t section_offset, void *dst, size_t dst_len) const
{
// If some other objectfile owns this data, pass this to them.
if (section->GetObjectFile() != this)
return section->GetObjectFile()->ReadSectionData (section, section_offset, dst, dst_len);
if (IsInMemory())
{
ProcessSP process_sp (m_process_wp.lock());
@ -498,6 +510,10 @@ ObjectFile::ReadSectionData (const Section *section, off_t section_offset, void
size_t
ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data) const
{
// If some other objectfile owns this data, pass this to them.
if (section->GetObjectFile() != this)
return section->GetObjectFile()->ReadSectionData (section, section_data);
if (IsInMemory())
{
ProcessSP process_sp (m_process_wp.lock());
@ -529,6 +545,10 @@ ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data
size_t
ObjectFile::MemoryMapSectionData (const Section *section, DataExtractor& section_data) const
{
// If some other objectfile owns this data, pass this to them.
if (section->GetObjectFile() != this)
return section->GetObjectFile()->MemoryMapSectionData (section, section_data);
if (IsInMemory())
{
return ReadSectionData (section, section_data);
@ -566,19 +586,29 @@ ObjectFile::SplitArchivePathWithObject (const char *path_with_object, FileSpec &
}
void
ObjectFile::ClearSymtab ()
ObjectFile::ClearSymtab (uint32_t flags)
{
ModuleSP module_sp(GetModule());
if (module_sp)
{
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
bool unified_section_list = !!(flags & ObjectFile::eSymtabFromUnifiedSectionList);
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
{
log->Printf ("%p ObjectFile::ClearSymtab () symtab = %p",
log->Printf ("%p ObjectFile::ClearSymtab (%s) symtab = %p",
this,
m_symtab_ap.get());
unified_section_list ? "unified" : "",
unified_section_list ? m_symtab_unified_ap.get() : m_symtab_ap.get());
}
if (unified_section_list)
{
m_symtab_unified_ap.reset();
m_symtab_unified_revisionid = 0;
}
else
{
m_symtab_ap.reset();
}
m_symtab_ap.reset();
}
}

View File

@ -16,6 +16,7 @@
#include "lldb/Symbol/Symtab.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Symbol/SymbolVendor.h"
using namespace lldb;
using namespace lldb_private;
@ -288,22 +289,59 @@ Symbol::GetPrologueByteSize ()
m_type_data_resolved = true;
ModuleSP module_sp (m_addr_range.GetBaseAddress().GetModule());
SymbolContext sc;
if (module_sp && module_sp->ResolveSymbolContextForAddress (m_addr_range.GetBaseAddress(),
eSymbolContextLineEntry,
sc))
if (module_sp)
{
m_type_data = sc.line_entry.range.GetByteSize();
// Sanity check - this may be a function in the middle of code that has debug information, but
// not for this symbol. So the line entries surrounding us won't lie inside our function.
// In that case, the line entry will be bigger than we are, so we do that quick check and
// if that is true, we just return 0.
if (m_type_data >= m_addr_range.GetByteSize())
uint32_t resolved_flags = module_sp->ResolveSymbolContextForAddress (m_addr_range.GetBaseAddress(),
eSymbolContextLineEntry,
sc);
if (resolved_flags & eSymbolContextLineEntry)
{
// Default to the end of the first line entry.
m_type_data = sc.line_entry.range.GetByteSize();
// Set address for next line.
Address addr (m_addr_range.GetBaseAddress());
addr.Slide (m_type_data);
// Check the first few instructions and look for one that has a line number that is
// different than the first entry. This is also done in Function::GetPrologueByteSize().
uint16_t total_offset = m_type_data;
for (int idx = 0; idx < 6; ++idx)
{
SymbolContext sc_temp;
resolved_flags = module_sp->ResolveSymbolContextForAddress (addr, eSymbolContextLineEntry, sc_temp);
// Make sure we got line number information...
if (!(resolved_flags & eSymbolContextLineEntry))
break;
// If this line number is different than our first one, use it and we're done.
if (sc_temp.line_entry.line != sc.line_entry.line)
{
m_type_data = total_offset;
break;
}
// Slide addr up to the next line address.
addr.Slide (sc_temp.line_entry.range.GetByteSize());
total_offset += sc_temp.line_entry.range.GetByteSize();
// If we've gone too far, bail out.
if (total_offset >= m_addr_range.GetByteSize())
break;
}
// Sanity check - this may be a function in the middle of code that has debug information, but
// not for this symbol. So the line entries surrounding us won't lie inside our function.
// In that case, the line entry will be bigger than we are, so we do that quick check and
// if that is true, we just return 0.
if (m_type_data >= m_addr_range.GetByteSize())
m_type_data = 0;
}
else
{
// TODO: expose something in Process to figure out the
// size of a function prologue.
m_type_data = 0;
}
else
{
// TODO: expose something in Process to figure out the
// size of a function prologue.
}
}
}
return m_type_data;
@ -418,10 +456,10 @@ Symbol::GetByteSize () const
ModuleSP module_sp (GetAddress().GetModule());
if (module_sp)
{
ObjectFile *objfile = module_sp->GetObjectFile();
if (objfile)
SymbolVendor *sym_vendor = module_sp->GetSymbolVendor();
if (sym_vendor)
{
Symtab *symtab = objfile->GetSymtab();
Symtab *symtab = sym_vendor->GetSymtab();
if (symtab)
{
const_cast<Symbol*>(this)->SetByteSize (symtab->CalculateSymbolSize (const_cast<Symbol *>(this)));

View File

@ -35,21 +35,14 @@ SymbolVendor*
SymbolVendor::FindPlugin (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm)
{
std::unique_ptr<SymbolVendor> instance_ap;
//----------------------------------------------------------------------
// We currently only have one debug symbol parser...
//----------------------------------------------------------------------
SymbolVendorCreateInstance create_callback;
for (size_t idx = 0; (create_callback = PluginManager::GetSymbolVendorCreateCallbackAtIndex(idx)) != NULL; ++idx)
{
instance_ap.reset(create_callback(module_sp, feedback_strm));
if (instance_ap.get())
{
// TODO: make sure this symbol vendor is what we want. We
// currently are just returning the first one we find, but
// we may want to call this function only when we have our
// main executable module and then give all symbol vendor
// plug-ins a chance to compete for who wins.
return instance_ap.release();
}
}
@ -84,7 +77,7 @@ SymbolVendor::~SymbolVendor()
}
//----------------------------------------------------------------------
// Add a represantion given an object file.
// Add a represention given an object file.
//----------------------------------------------------------------------
void
SymbolVendor::AddSymbolFileRepresentation(const ObjectFileSP &objfile_sp)
@ -444,6 +437,36 @@ SymbolVendor::GetCompileUnitAtIndex(size_t idx)
return cu_sp;
}
Symtab *
SymbolVendor::GetSymtab ()
{
ModuleSP module_sp(GetModule());
if (module_sp)
{
ObjectFile *objfile = module_sp->GetObjectFile();
if (objfile)
{
// Get symbol table from unified section list.
return objfile->GetSymtab (ObjectFile::eSymtabFromUnifiedSectionList);
}
}
return NULL;
}
void
SymbolVendor::ClearSymtab()
{
ModuleSP module_sp(GetModule());
if (module_sp)
{
ObjectFile *objfile = module_sp->GetObjectFile();
if (objfile)
{
// Clear symbol table from unified section list.
objfile->ClearSymtab (ObjectFile::eSymtabFromUnifiedSectionList);
}
}
}
//------------------------------------------------------------------
// PluginInterface protocol

View File

@ -1775,6 +1775,15 @@ Target::GetDefaultExecutableSearchPaths ()
return FileSpecList();
}
FileSpecList
Target::GetDefaultDebugFileSearchPaths ()
{
TargetPropertiesSP properties_sp(Target::GetGlobalProperties());
if (properties_sp)
return properties_sp->GetDebugFileSearchPaths();
return FileSpecList();
}
ArchSpec
Target::GetDefaultArchitecture ()
{
@ -2305,6 +2314,7 @@ g_properties[] =
"and the second is where the remainder of the original build hierarchy is rooted on the local system. "
"Each element of the array is checked in order and the first one that results in a match wins." },
{ "exec-search-paths" , OptionValue::eTypeFileSpecList, false, 0 , NULL, NULL, "Executable search paths to use when locating executable files whose paths don't match the local file system." },
{ "debug-file-search-paths" , OptionValue::eTypeFileSpecList, false, 0 , NULL, NULL, "List of directories to be searched when locating debug symbol files." },
{ "max-children-count" , OptionValue::eTypeSInt64 , false, 256 , NULL, NULL, "Maximum number of children to expand in any level of depth." },
{ "max-string-summary-length" , OptionValue::eTypeSInt64 , false, 1024 , NULL, NULL, "Maximum number of characters to show when using %s in summary strings." },
{ "max-memory-read-size" , OptionValue::eTypeSInt64 , false, 1024 , NULL, NULL, "Maximum number of bytes that 'memory read' will fetch before --force must be specified." },
@ -2340,6 +2350,7 @@ enum
ePropertySkipPrologue,
ePropertySourceMap,
ePropertyExecutableSearchPaths,
ePropertyDebugFileSearchPaths,
ePropertyMaxChildrenCount,
ePropertyMaxSummaryLength,
ePropertyMaxMemReadSize,
@ -2617,6 +2628,15 @@ TargetProperties::GetExecutableSearchPaths ()
return option_value->GetCurrentValue();
}
FileSpecList &
TargetProperties::GetDebugFileSearchPaths ()
{
const uint32_t idx = ePropertyDebugFileSearchPaths;
OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList (NULL, false, idx);
assert(option_value);
return option_value->GetCurrentValue();
}
bool
TargetProperties::GetEnableSyntheticValue () const
{

View File

@ -30,6 +30,7 @@
#include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h"
#include "Plugins/Instruction/ARM/EmulateInstructionARM.h"
#include "Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h"
#include "Plugins/SymbolVendor/ELF/SymbolVendorELF.h"
#include "Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h"
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
@ -98,6 +99,7 @@ lldb_private::Initialize ()
DisassemblerLLVMC::Initialize();
ObjectContainerBSDArchive::Initialize();
ObjectFileELF::Initialize();
SymbolVendorELF::Initialize();
SymbolFileDWARF::Initialize();
SymbolFileSymtab::Initialize();
UnwindAssemblyInstEmulation::Initialize();
@ -177,6 +179,7 @@ lldb_private::Terminate ()
DisassemblerLLVMC::Terminate();
ObjectContainerBSDArchive::Terminate();
ObjectFileELF::Terminate();
SymbolVendorELF::Terminate();
SymbolFileDWARF::Terminate();
SymbolFileSymtab::Terminate();
UnwindAssembly_x86::Terminate();
@ -361,6 +364,10 @@ lldb_private::GetSectionTypeAsCString (SectionType sect_type)
case eSectionTypeDWARFDebugPubTypes: return "dwarf-pubtypes";
case eSectionTypeDWARFDebugRanges: return "dwarf-ranges";
case eSectionTypeDWARFDebugStr: return "dwarf-str";
case eSectionTypeELFSymbolTable: return "elf-symbol-table";
case eSectionTypeELFDynamicSymbols: return "elf-dynamic-symbols";
case eSectionTypeELFRelocationEntries: return "elf-relocation-entries";
case eSectionTypeELFDynamicLinkInfo: return "elf-dynamic-link-info";
case eSectionTypeDWARFAppleNames: return "apple-names";
case eSectionTypeDWARFAppleTypes: return "apple-types";
case eSectionTypeDWARFAppleNamespaces: return "apple-namespaces";