2013-08-23 13:46:38 -04:00
//===-- SymbolFileDWARFDebugMap.cpp ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "SymbolFileDWARFDebugMap.h"
# include "DWARFDebugAranges.h"
# include "lldb/Core/RangeMap.h"
# include "lldb/Core/Module.h"
# include "lldb/Core/ModuleList.h"
# include "lldb/Core/PluginManager.h"
# include "lldb/Core/RegularExpression.h"
# include "lldb/Core/Section.h"
//#define DEBUG_OSO_DMAP // DO NOT CHECKIN WITH THIS NOT COMMENTED OUT
# if defined(DEBUG_OSO_DMAP)
# include "lldb/Core/StreamFile.h"
# endif
# include "lldb/Core/Timer.h"
# include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"
# include "lldb/Symbol/CompileUnit.h"
# include "lldb/Symbol/LineTable.h"
# include "lldb/Symbol/ObjectFile.h"
# include "lldb/Symbol/SymbolVendor.h"
# include "lldb/Symbol/VariableList.h"
# include "LogChannelDWARF.h"
# include "SymbolFileDWARF.h"
using namespace lldb ;
using namespace lldb_private ;
// Subclass lldb_private::Module so we can intercept the "Module::GetObjectFile()"
// (so we can fixup the object file sections) and also for "Module::GetSymbolVendor()"
// (so we can fixup the symbol file id.
const SymbolFileDWARFDebugMap : : FileRangeMap &
SymbolFileDWARFDebugMap : : CompileUnitInfo : : GetFileRangeMap ( SymbolFileDWARFDebugMap * exe_symfile )
{
if ( file_range_map_valid )
return file_range_map ;
file_range_map_valid = true ;
Module * oso_module = exe_symfile - > GetModuleByCompUnitInfo ( this ) ;
if ( ! oso_module )
return file_range_map ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
ObjectFile * oso_objfile = oso_module - > GetObjectFile ( ) ;
if ( ! oso_objfile )
return file_range_map ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
Log * log ( LogChannelDWARF : : GetLogIfAll ( DWARF_LOG_DEBUG_MAP ) ) ;
if ( log )
{
ConstString object_name ( oso_module - > GetObjectName ( ) ) ;
log - > Printf ( " %p: SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap ('%s') " ,
2014-11-25 16:00:58 -05:00
static_cast < void * > ( this ) ,
2013-08-23 13:46:38 -04:00
oso_module - > GetSpecificationDescription ( ) . c_str ( ) ) ;
}
std : : vector < SymbolFileDWARFDebugMap : : CompileUnitInfo * > cu_infos ;
if ( exe_symfile - > GetCompUnitInfosForModule ( oso_module , cu_infos ) )
{
for ( auto comp_unit_info : cu_infos )
{
Symtab * exe_symtab = exe_symfile - > GetObjectFile ( ) - > GetSymtab ( ) ;
ModuleSP oso_module_sp ( oso_objfile - > GetModule ( ) ) ;
Symtab * oso_symtab = oso_objfile - > GetSymtab ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
///const uint32_t fun_resolve_flags = SymbolContext::Module | eSymbolContextCompUnit | eSymbolContextFunction;
//SectionList *oso_sections = oso_objfile->Sections();
// Now we need to make sections that map from zero based object
2014-11-25 16:00:58 -05:00
// file addresses to where things ended up in the main executable.
2013-08-23 13:46:38 -04:00
assert ( comp_unit_info - > first_symbol_index ! = UINT32_MAX ) ;
// End index is one past the last valid symbol index
const uint32_t oso_end_idx = comp_unit_info - > last_symbol_index + 1 ;
for ( uint32_t idx = comp_unit_info - > first_symbol_index + 2 ; // Skip the N_SO and N_OSO
idx < oso_end_idx ;
+ + idx )
{
Symbol * exe_symbol = exe_symtab - > SymbolAtIndex ( idx ) ;
if ( exe_symbol )
{
if ( exe_symbol - > IsDebug ( ) = = false )
continue ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
switch ( exe_symbol - > GetType ( ) )
{
default :
break ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
case eSymbolTypeCode :
{
// For each N_FUN, or function that we run into in the debug map
// we make a new section that we add to the sections found in the
// .o file. This new section has the file address set to what the
// addresses are in the .o file, and the load address is adjusted
// to match where it ended up in the final executable! We do this
// before we parse any dwarf info so that when it goes get parsed
// all section/offset addresses that get registered will resolve
// correctly to the new addresses in the main executable.
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
// First we find the original symbol in the .o file's symbol table
2015-09-06 10:32:30 -04:00
Symbol * oso_fun_symbol = oso_symtab - > FindFirstSymbolWithNameAndType ( exe_symbol - > GetMangled ( ) . GetName ( lldb : : eLanguageTypeUnknown , Mangled : : ePreferMangled ) ,
2013-08-23 13:46:38 -04:00
eSymbolTypeCode ,
Symtab : : eDebugNo ,
Symtab : : eVisibilityAny ) ;
if ( oso_fun_symbol )
{
// Add the inverse OSO file address to debug map entry mapping
exe_symfile - > AddOSOFileRange ( this ,
2015-07-03 12:57:06 -04:00
exe_symbol - > GetAddressRef ( ) . GetFileAddress ( ) ,
oso_fun_symbol - > GetAddressRef ( ) . GetFileAddress ( ) ,
2013-08-23 13:46:38 -04:00
std : : min < addr_t > ( exe_symbol - > GetByteSize ( ) , oso_fun_symbol - > GetByteSize ( ) ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
}
}
break ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
case eSymbolTypeData :
{
// For each N_GSYM we remap the address for the global by making
// a new section that we add to the sections found in the .o file.
// This new section has the file address set to what the
// addresses are in the .o file, and the load address is adjusted
// to match where it ended up in the final executable! We do this
// before we parse any dwarf info so that when it goes get parsed
// all section/offset addresses that get registered will resolve
// correctly to the new addresses in the main executable. We
// initially set the section size to be 1 byte, but will need to
// fix up these addresses further after all globals have been
// parsed to span the gaps, or we can find the global variable
// sizes from the DWARF info as we are parsing.
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
// Next we find the non-stab entry that corresponds to the N_GSYM in the .o file
2015-09-06 10:32:30 -04:00
Symbol * oso_gsym_symbol = oso_symtab - > FindFirstSymbolWithNameAndType ( exe_symbol - > GetMangled ( ) . GetName ( lldb : : eLanguageTypeUnknown , Mangled : : ePreferMangled ) ,
2013-08-23 13:46:38 -04:00
eSymbolTypeData ,
Symtab : : eDebugNo ,
Symtab : : eVisibilityAny ) ;
if ( exe_symbol & & oso_gsym_symbol & &
exe_symbol - > ValueIsAddress ( ) & &
oso_gsym_symbol - > ValueIsAddress ( ) )
{
// Add the inverse OSO file address to debug map entry mapping
exe_symfile - > AddOSOFileRange ( this ,
2015-07-03 12:57:06 -04:00
exe_symbol - > GetAddressRef ( ) . GetFileAddress ( ) ,
oso_gsym_symbol - > GetAddressRef ( ) . GetFileAddress ( ) ,
2013-08-23 13:46:38 -04:00
std : : min < addr_t > ( exe_symbol - > GetByteSize ( ) , oso_gsym_symbol - > GetByteSize ( ) ) ) ;
}
}
break ;
}
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
exe_symfile - > FinalizeOSOFileRanges ( this ) ;
// We don't need the symbols anymore for the .o files
oso_objfile - > ClearSymtab ( ) ;
}
}
return file_range_map ;
}
class DebugMapModule : public Module
{
public :
DebugMapModule ( const ModuleSP & exe_module_sp ,
uint32_t cu_idx ,
const FileSpec & file_spec ,
const ArchSpec & arch ,
const ConstString * object_name ,
off_t object_offset ,
const TimeValue * object_mod_time_ptr ) :
Module ( file_spec , arch , object_name , object_offset , object_mod_time_ptr ) ,
m_exe_module_wp ( exe_module_sp ) ,
m_cu_idx ( cu_idx )
{
}
virtual
~ DebugMapModule ( )
{
}
virtual SymbolVendor *
GetSymbolVendor ( bool can_create = true , lldb_private : : Stream * feedback_strm = NULL )
{
// Scope for locker
if ( m_symfile_ap . get ( ) | | can_create = = false )
return m_symfile_ap . get ( ) ;
ModuleSP exe_module_sp ( m_exe_module_wp . lock ( ) ) ;
if ( exe_module_sp )
{
// Now get the object file outside of a locking scope
ObjectFile * oso_objfile = GetObjectFile ( ) ;
if ( oso_objfile )
{
Mutex : : Locker locker ( m_mutex ) ;
SymbolVendor * symbol_vendor = Module : : GetSymbolVendor ( can_create , feedback_strm ) ;
if ( symbol_vendor )
{
2014-11-25 16:00:58 -05:00
// Set a pointer to this class to set our OSO DWARF file know
2013-08-23 13:46:38 -04:00
// that the DWARF is being used along with a debug map and that
// it will have the remapped sections that we do below.
SymbolFileDWARF * oso_symfile = SymbolFileDWARFDebugMap : : GetSymbolFileAsSymbolFileDWARF ( symbol_vendor - > GetSymbolFile ( ) ) ;
if ( ! oso_symfile )
return NULL ;
ObjectFile * exe_objfile = exe_module_sp - > GetObjectFile ( ) ;
SymbolVendor * exe_sym_vendor = exe_module_sp - > GetSymbolVendor ( ) ;
if ( exe_objfile & & exe_sym_vendor )
{
2015-07-03 12:57:06 -04:00
oso_symfile - > SetDebugMapModule ( exe_module_sp ) ;
// Set the ID of the symbol file DWARF to the index of the OSO
// shifted left by 32 bits to provide a unique prefix for any
// UserID's that get created in the symbol file.
oso_symfile - > SetID ( ( ( uint64_t ) m_cu_idx + 1ull ) < < 32ull ) ;
2013-08-23 13:46:38 -04:00
}
return symbol_vendor ;
}
}
}
return NULL ;
}
protected :
ModuleWP m_exe_module_wp ;
const uint32_t m_cu_idx ;
} ;
void
SymbolFileDWARFDebugMap : : Initialize ( )
{
PluginManager : : RegisterPlugin ( GetPluginNameStatic ( ) ,
GetPluginDescriptionStatic ( ) ,
CreateInstance ) ;
}
void
SymbolFileDWARFDebugMap : : Terminate ( )
{
PluginManager : : UnregisterPlugin ( CreateInstance ) ;
}
lldb_private : : ConstString
SymbolFileDWARFDebugMap : : GetPluginNameStatic ( )
{
static ConstString g_name ( " dwarf-debugmap " ) ;
return g_name ;
}
const char *
SymbolFileDWARFDebugMap : : GetPluginDescriptionStatic ( )
{
return " DWARF and DWARF3 debug symbol file reader (debug map). " ;
}
SymbolFile *
SymbolFileDWARFDebugMap : : CreateInstance ( ObjectFile * obj_file )
{
return new SymbolFileDWARFDebugMap ( obj_file ) ;
}
SymbolFileDWARFDebugMap : : SymbolFileDWARFDebugMap ( ObjectFile * ofile ) :
SymbolFile ( ofile ) ,
m_flags ( ) ,
m_compile_unit_infos ( ) ,
m_func_indexes ( ) ,
m_glob_indexes ( ) ,
m_supports_DW_AT_APPLE_objc_complete_type ( eLazyBoolCalculate )
{
}
SymbolFileDWARFDebugMap : : ~ SymbolFileDWARFDebugMap ( )
{
}
void
SymbolFileDWARFDebugMap : : InitializeObject ( )
{
// Install our external AST source callbacks so we can complete Clang types.
2014-11-25 16:00:58 -05:00
llvm : : IntrusiveRefCntPtr < clang : : ExternalASTSource > ast_source_ap (
2013-08-23 13:46:38 -04:00
new ClangExternalASTSourceCallbacks ( SymbolFileDWARFDebugMap : : CompleteTagDecl ,
SymbolFileDWARFDebugMap : : CompleteObjCInterfaceDecl ,
NULL ,
SymbolFileDWARFDebugMap : : LayoutRecordType ,
this ) ) ;
GetClangASTContext ( ) . SetExternalSource ( ast_source_ap ) ;
}
void
SymbolFileDWARFDebugMap : : InitOSO ( )
{
if ( m_flags . test ( kHaveInitializedOSOs ) )
return ;
m_flags . set ( kHaveInitializedOSOs ) ;
// If the object file has been stripped, there is no sense in looking further
// as all of the debug symbols for the debug map will not be available
if ( m_obj_file - > IsStripped ( ) )
return ;
// Also make sure the file type is some sort of executable. Core files, debug
// info files (dSYM), object files (.o files), and stub libraries all can
switch ( m_obj_file - > GetType ( ) )
{
case ObjectFile : : eTypeInvalid :
case ObjectFile : : eTypeCoreFile :
case ObjectFile : : eTypeDebugInfo :
case ObjectFile : : eTypeObjectFile :
case ObjectFile : : eTypeStubLibrary :
case ObjectFile : : eTypeUnknown :
2014-11-25 16:00:58 -05:00
case ObjectFile : : eTypeJIT :
2013-08-23 13:46:38 -04:00
return ;
case ObjectFile : : eTypeExecutable :
case ObjectFile : : eTypeDynamicLinker :
case ObjectFile : : eTypeSharedLibrary :
break ;
}
// In order to get the abilities of this plug-in, we look at the list of
// N_OSO entries (object files) from the symbol table and make sure that
// 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 ( ) ;
if ( symtab )
{
Log * log ( LogChannelDWARF : : GetLogIfAll ( DWARF_LOG_DEBUG_MAP ) ) ;
std : : vector < uint32_t > oso_indexes ;
// When a mach-o symbol is encoded, the n_type field is encoded in bits
// 23:16, and the n_desc field is encoded in bits 15:0.
//
// To find all N_OSO entries that are part of the DWARF + debug map
// we find only object file symbols with the flags value as follows:
// bits 23:16 == 0x66 (N_OSO)
// bits 15: 0 == 0x0001 (specifies this is a debug map object file)
const uint32_t k_oso_symbol_flags_value = 0x660001u ;
const uint32_t oso_index_count = symtab - > AppendSymbolIndexesWithTypeAndFlagsValue ( eSymbolTypeObjectFile , k_oso_symbol_flags_value , oso_indexes ) ;
if ( oso_index_count > 0 )
{
symtab - > AppendSymbolIndexesWithType ( eSymbolTypeCode , Symtab : : eDebugYes , Symtab : : eVisibilityAny , m_func_indexes ) ;
symtab - > AppendSymbolIndexesWithType ( eSymbolTypeData , Symtab : : eDebugYes , Symtab : : eVisibilityAny , m_glob_indexes ) ;
symtab - > SortSymbolIndexesByValue ( m_func_indexes , true ) ;
symtab - > SortSymbolIndexesByValue ( m_glob_indexes , true ) ;
for ( uint32_t sym_idx : m_func_indexes )
{
const Symbol * symbol = symtab - > SymbolAtIndex ( sym_idx ) ;
2015-07-03 12:57:06 -04:00
lldb : : addr_t file_addr = symbol - > GetAddressRef ( ) . GetFileAddress ( ) ;
2013-08-23 13:46:38 -04:00
lldb : : addr_t byte_size = symbol - > GetByteSize ( ) ;
DebugMap : : Entry debug_map_entry ( file_addr , byte_size , OSOEntry ( sym_idx , LLDB_INVALID_ADDRESS ) ) ;
m_debug_map . Append ( debug_map_entry ) ;
}
for ( uint32_t sym_idx : m_glob_indexes )
{
const Symbol * symbol = symtab - > SymbolAtIndex ( sym_idx ) ;
2015-07-03 12:57:06 -04:00
lldb : : addr_t file_addr = symbol - > GetAddressRef ( ) . GetFileAddress ( ) ;
2013-08-23 13:46:38 -04:00
lldb : : addr_t byte_size = symbol - > GetByteSize ( ) ;
DebugMap : : Entry debug_map_entry ( file_addr , byte_size , OSOEntry ( sym_idx , LLDB_INVALID_ADDRESS ) ) ;
m_debug_map . Append ( debug_map_entry ) ;
}
m_debug_map . Sort ( ) ;
m_compile_unit_infos . resize ( oso_index_count ) ;
for ( uint32_t i = 0 ; i < oso_index_count ; + + i )
{
const uint32_t so_idx = oso_indexes [ i ] - 1 ;
const uint32_t oso_idx = oso_indexes [ i ] ;
const Symbol * so_symbol = symtab - > SymbolAtIndex ( so_idx ) ;
const Symbol * oso_symbol = symtab - > SymbolAtIndex ( oso_idx ) ;
if ( so_symbol & &
oso_symbol & &
so_symbol - > GetType ( ) = = eSymbolTypeSourceFile & &
oso_symbol - > GetType ( ) = = eSymbolTypeObjectFile )
{
m_compile_unit_infos [ i ] . so_file . SetFile ( so_symbol - > GetName ( ) . AsCString ( ) , false ) ;
m_compile_unit_infos [ i ] . oso_path = oso_symbol - > GetName ( ) ;
TimeValue oso_mod_time ;
2015-07-03 12:57:06 -04:00
oso_mod_time . OffsetWithSeconds ( oso_symbol - > GetIntegerValue ( 0 ) ) ;
2013-08-23 13:46:38 -04:00
m_compile_unit_infos [ i ] . oso_mod_time = oso_mod_time ;
uint32_t sibling_idx = so_symbol - > GetSiblingIndex ( ) ;
// The sibling index can't be less that or equal to the current index "i"
2015-07-03 12:57:06 -04:00
if ( sibling_idx = = UINT32_MAX )
2013-08-23 13:46:38 -04:00
{
m_obj_file - > GetModule ( ) - > ReportError ( " N_SO in symbol with UID %u has invalid sibling in debug map, please file a bug and attach the binary listed in this error " , so_symbol - > GetID ( ) ) ;
}
else
{
const Symbol * last_symbol = symtab - > SymbolAtIndex ( sibling_idx - 1 ) ;
m_compile_unit_infos [ i ] . first_symbol_index = so_idx ;
m_compile_unit_infos [ i ] . last_symbol_index = sibling_idx - 1 ;
m_compile_unit_infos [ i ] . first_symbol_id = so_symbol - > GetID ( ) ;
m_compile_unit_infos [ i ] . last_symbol_id = last_symbol - > GetID ( ) ;
if ( log )
log - > Printf ( " Initialized OSO 0x%8.8x: file=%s " , i , oso_symbol - > GetName ( ) . GetCString ( ) ) ;
}
}
else
{
if ( oso_symbol = = NULL )
m_obj_file - > GetModule ( ) - > ReportError ( " N_OSO symbol[%u] can't be found, please file a bug and attach the binary listed in this error " , oso_idx ) ;
else if ( so_symbol = = NULL )
m_obj_file - > GetModule ( ) - > ReportError ( " N_SO not found for N_OSO symbol[%u], please file a bug and attach the binary listed in this error " , oso_idx ) ;
else if ( so_symbol - > GetType ( ) ! = eSymbolTypeSourceFile )
m_obj_file - > GetModule ( ) - > ReportError ( " N_SO has incorrect symbol type (%u) for N_OSO symbol[%u], please file a bug and attach the binary listed in this error " , so_symbol - > GetType ( ) , oso_idx ) ;
else if ( oso_symbol - > GetType ( ) ! = eSymbolTypeSourceFile )
m_obj_file - > GetModule ( ) - > ReportError ( " N_OSO has incorrect symbol type (%u) for N_OSO symbol[%u], please file a bug and attach the binary listed in this error " , oso_symbol - > GetType ( ) , oso_idx ) ;
}
}
}
}
}
Module *
SymbolFileDWARFDebugMap : : GetModuleByOSOIndex ( uint32_t oso_idx )
{
const uint32_t cu_count = GetNumCompileUnits ( ) ;
if ( oso_idx < cu_count )
return GetModuleByCompUnitInfo ( & m_compile_unit_infos [ oso_idx ] ) ;
return NULL ;
}
Module *
SymbolFileDWARFDebugMap : : GetModuleByCompUnitInfo ( CompileUnitInfo * comp_unit_info )
{
if ( ! comp_unit_info - > oso_sp )
{
auto pos = m_oso_map . find ( comp_unit_info - > oso_path ) ;
if ( pos ! = m_oso_map . end ( ) )
{
comp_unit_info - > oso_sp = pos - > second ;
}
else
{
ObjectFile * obj_file = GetObjectFile ( ) ;
comp_unit_info - > oso_sp . reset ( new OSOInfo ( ) ) ;
m_oso_map [ comp_unit_info - > oso_path ] = comp_unit_info - > oso_sp ;
const char * oso_path = comp_unit_info - > oso_path . GetCString ( ) ;
FileSpec oso_file ( oso_path , false ) ;
ConstString oso_object ;
if ( oso_file . Exists ( ) )
{
TimeValue oso_mod_time ( oso_file . GetModificationTime ( ) ) ;
if ( oso_mod_time ! = comp_unit_info - > oso_mod_time )
{
obj_file - > GetModule ( ) - > ReportError ( " debug map object file '%s' has changed (actual time is 0x% " PRIx64 " , debug map time is 0x% " PRIx64 " ) since this executable was linked, file will be ignored " ,
oso_file . GetPath ( ) . c_str ( ) ,
oso_mod_time . GetAsSecondsSinceJan1_1970 ( ) ,
comp_unit_info - > oso_mod_time . GetAsSecondsSinceJan1_1970 ( ) ) ;
return NULL ;
}
}
else
{
const bool must_exist = true ;
if ( ! ObjectFile : : SplitArchivePathWithObject ( oso_path ,
oso_file ,
oso_object ,
must_exist ) )
{
return NULL ;
}
}
// Always create a new module for .o files. Why? Because we
// use the debug map, to add new sections to each .o file and
// even though a .o file might not have changed, the sections
// that get added to the .o file can change.
2014-11-25 16:00:58 -05:00
ArchSpec oso_arch ;
// Only adopt the architecture from the module (not the vendor or OS)
// since .o files for "i386-apple-ios" will historically show up as "i386-apple-macosx"
// due to the lack of a LC_VERSION_MIN_MACOSX or LC_VERSION_MIN_IPHONEOS
// load command...
oso_arch . SetTriple ( m_obj_file - > GetModule ( ) - > GetArchitecture ( ) . GetTriple ( ) . getArchName ( ) . str ( ) . c_str ( ) ) ;
2013-08-23 13:46:38 -04:00
comp_unit_info - > oso_sp - > module_sp . reset ( new DebugMapModule ( obj_file - > GetModule ( ) ,
GetCompUnitInfoIndex ( comp_unit_info ) ,
oso_file ,
2014-11-25 16:00:58 -05:00
oso_arch ,
2013-08-23 13:46:38 -04:00
oso_object ? & oso_object : NULL ,
0 ,
oso_object ? & comp_unit_info - > oso_mod_time : NULL ) ) ;
}
}
if ( comp_unit_info - > oso_sp )
return comp_unit_info - > oso_sp - > module_sp . get ( ) ;
return NULL ;
}
bool
SymbolFileDWARFDebugMap : : GetFileSpecForSO ( uint32_t oso_idx , FileSpec & file_spec )
{
if ( oso_idx < m_compile_unit_infos . size ( ) )
{
if ( m_compile_unit_infos [ oso_idx ] . so_file )
{
file_spec = m_compile_unit_infos [ oso_idx ] . so_file ;
return true ;
}
}
return false ;
}
ObjectFile *
SymbolFileDWARFDebugMap : : GetObjectFileByOSOIndex ( uint32_t oso_idx )
{
Module * oso_module = GetModuleByOSOIndex ( oso_idx ) ;
if ( oso_module )
return oso_module - > GetObjectFile ( ) ;
return NULL ;
}
SymbolFileDWARF *
SymbolFileDWARFDebugMap : : GetSymbolFile ( const SymbolContext & sc )
{
CompileUnitInfo * comp_unit_info = GetCompUnitInfo ( sc ) ;
if ( comp_unit_info )
return GetSymbolFileByCompUnitInfo ( comp_unit_info ) ;
return NULL ;
}
ObjectFile *
SymbolFileDWARFDebugMap : : GetObjectFileByCompUnitInfo ( CompileUnitInfo * comp_unit_info )
{
Module * oso_module = GetModuleByCompUnitInfo ( comp_unit_info ) ;
if ( oso_module )
return oso_module - > GetObjectFile ( ) ;
return NULL ;
}
uint32_t
SymbolFileDWARFDebugMap : : GetCompUnitInfoIndex ( const CompileUnitInfo * comp_unit_info )
{
if ( ! m_compile_unit_infos . empty ( ) )
{
const CompileUnitInfo * first_comp_unit_info = & m_compile_unit_infos . front ( ) ;
const CompileUnitInfo * last_comp_unit_info = & m_compile_unit_infos . back ( ) ;
if ( first_comp_unit_info < = comp_unit_info & & comp_unit_info < = last_comp_unit_info )
return comp_unit_info - first_comp_unit_info ;
}
return UINT32_MAX ;
}
SymbolFileDWARF *
SymbolFileDWARFDebugMap : : GetSymbolFileByOSOIndex ( uint32_t oso_idx )
{
if ( oso_idx < m_compile_unit_infos . size ( ) )
return GetSymbolFileByCompUnitInfo ( & m_compile_unit_infos [ oso_idx ] ) ;
return NULL ;
}
SymbolFileDWARF *
SymbolFileDWARFDebugMap : : GetSymbolFileAsSymbolFileDWARF ( SymbolFile * sym_file )
{
if ( sym_file & & sym_file - > GetPluginName ( ) = = SymbolFileDWARF : : GetPluginNameStatic ( ) )
return ( SymbolFileDWARF * ) sym_file ;
return NULL ;
}
SymbolFileDWARF *
SymbolFileDWARFDebugMap : : GetSymbolFileByCompUnitInfo ( CompileUnitInfo * comp_unit_info )
{
Module * oso_module = GetModuleByCompUnitInfo ( comp_unit_info ) ;
if ( oso_module )
{
SymbolVendor * sym_vendor = oso_module - > GetSymbolVendor ( ) ;
if ( sym_vendor )
return GetSymbolFileAsSymbolFileDWARF ( sym_vendor - > GetSymbolFile ( ) ) ;
}
return NULL ;
}
uint32_t
SymbolFileDWARFDebugMap : : CalculateAbilities ( )
{
// In order to get the abilities of this plug-in, we look at the list of
// N_OSO entries (object files) from the symbol table and make sure that
// 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.
const uint32_t oso_index_count = GetNumCompileUnits ( ) ;
if ( oso_index_count > 0 )
{
InitOSO ( ) ;
if ( ! m_compile_unit_infos . empty ( ) )
{
return SymbolFile : : CompileUnits |
SymbolFile : : Functions |
SymbolFile : : Blocks |
SymbolFile : : GlobalVariables |
SymbolFile : : LocalVariables |
SymbolFile : : VariableTypes |
SymbolFile : : LineTables ;
}
}
return 0 ;
}
uint32_t
SymbolFileDWARFDebugMap : : GetNumCompileUnits ( )
{
InitOSO ( ) ;
return m_compile_unit_infos . size ( ) ;
}
CompUnitSP
SymbolFileDWARFDebugMap : : ParseCompileUnitAtIndex ( uint32_t cu_idx )
{
CompUnitSP comp_unit_sp ;
const uint32_t cu_count = GetNumCompileUnits ( ) ;
if ( cu_idx < cu_count )
{
Module * oso_module = GetModuleByCompUnitInfo ( & m_compile_unit_infos [ cu_idx ] ) ;
if ( oso_module )
{
FileSpec so_file_spec ;
if ( GetFileSpecForSO ( cu_idx , so_file_spec ) )
{
// User zero as the ID to match the compile unit at offset
// zero in each .o file since each .o file can only have
// one compile unit for now.
lldb : : user_id_t cu_id = 0 ;
m_compile_unit_infos [ cu_idx ] . compile_unit_sp . reset ( new CompileUnit ( m_obj_file - > GetModule ( ) ,
NULL ,
so_file_spec ,
cu_id ,
eLanguageTypeUnknown ) ) ;
if ( m_compile_unit_infos [ cu_idx ] . compile_unit_sp )
{
// Let our symbol vendor know about this compile unit
m_obj_file - > GetModule ( ) - > GetSymbolVendor ( ) - > SetCompileUnitAtIndex ( cu_idx , m_compile_unit_infos [ cu_idx ] . compile_unit_sp ) ;
}
}
}
comp_unit_sp = m_compile_unit_infos [ cu_idx ] . compile_unit_sp ;
}
return comp_unit_sp ;
}
SymbolFileDWARFDebugMap : : CompileUnitInfo *
SymbolFileDWARFDebugMap : : GetCompUnitInfo ( const SymbolContext & sc )
{
const uint32_t cu_count = GetNumCompileUnits ( ) ;
for ( uint32_t i = 0 ; i < cu_count ; + + i )
{
if ( sc . comp_unit = = m_compile_unit_infos [ i ] . compile_unit_sp . get ( ) )
return & m_compile_unit_infos [ i ] ;
}
return NULL ;
}
size_t
SymbolFileDWARFDebugMap : : GetCompUnitInfosForModule ( const lldb_private : : Module * module , std : : vector < CompileUnitInfo * > & cu_infos )
{
const uint32_t cu_count = GetNumCompileUnits ( ) ;
for ( uint32_t i = 0 ; i < cu_count ; + + i )
{
if ( module = = GetModuleByCompUnitInfo ( & m_compile_unit_infos [ i ] ) )
cu_infos . push_back ( & m_compile_unit_infos [ i ] ) ;
}
return cu_infos . size ( ) ;
}
lldb : : LanguageType
SymbolFileDWARFDebugMap : : ParseCompileUnitLanguage ( const SymbolContext & sc )
{
SymbolFileDWARF * oso_dwarf = GetSymbolFile ( sc ) ;
if ( oso_dwarf )
return oso_dwarf - > ParseCompileUnitLanguage ( sc ) ;
return eLanguageTypeUnknown ;
}
size_t
SymbolFileDWARFDebugMap : : ParseCompileUnitFunctions ( const SymbolContext & sc )
{
SymbolFileDWARF * oso_dwarf = GetSymbolFile ( sc ) ;
if ( oso_dwarf )
return oso_dwarf - > ParseCompileUnitFunctions ( sc ) ;
return 0 ;
}
bool
SymbolFileDWARFDebugMap : : ParseCompileUnitLineTable ( const SymbolContext & sc )
{
SymbolFileDWARF * oso_dwarf = GetSymbolFile ( sc ) ;
if ( oso_dwarf )
return oso_dwarf - > ParseCompileUnitLineTable ( sc ) ;
return false ;
}
bool
SymbolFileDWARFDebugMap : : ParseCompileUnitSupportFiles ( const SymbolContext & sc , FileSpecList & support_files )
{
SymbolFileDWARF * oso_dwarf = GetSymbolFile ( sc ) ;
if ( oso_dwarf )
return oso_dwarf - > ParseCompileUnitSupportFiles ( sc , support_files ) ;
return false ;
}
2015-07-03 12:57:06 -04:00
bool
SymbolFileDWARFDebugMap : : ParseImportedModules ( const SymbolContext & sc , std : : vector < ConstString > & imported_modules )
{
SymbolFileDWARF * oso_dwarf = GetSymbolFile ( sc ) ;
if ( oso_dwarf )
return oso_dwarf - > ParseImportedModules ( sc , imported_modules ) ;
return false ;
}
2013-08-23 13:46:38 -04:00
size_t
SymbolFileDWARFDebugMap : : ParseFunctionBlocks ( const SymbolContext & sc )
{
SymbolFileDWARF * oso_dwarf = GetSymbolFile ( sc ) ;
if ( oso_dwarf )
return oso_dwarf - > ParseFunctionBlocks ( sc ) ;
return 0 ;
}
size_t
SymbolFileDWARFDebugMap : : ParseTypes ( const SymbolContext & sc )
{
SymbolFileDWARF * oso_dwarf = GetSymbolFile ( sc ) ;
if ( oso_dwarf )
return oso_dwarf - > ParseTypes ( sc ) ;
return 0 ;
}
size_t
SymbolFileDWARFDebugMap : : ParseVariablesForContext ( const SymbolContext & sc )
{
SymbolFileDWARF * oso_dwarf = GetSymbolFile ( sc ) ;
if ( oso_dwarf )
return oso_dwarf - > ParseVariablesForContext ( sc ) ;
return 0 ;
}
Type *
SymbolFileDWARFDebugMap : : ResolveTypeUID ( lldb : : user_id_t type_uid )
{
const uint64_t oso_idx = GetOSOIndexFromUserID ( type_uid ) ;
SymbolFileDWARF * oso_dwarf = GetSymbolFileByOSOIndex ( oso_idx ) ;
if ( oso_dwarf )
return oso_dwarf - > ResolveTypeUID ( type_uid ) ;
return NULL ;
}
bool
SymbolFileDWARFDebugMap : : ResolveClangOpaqueTypeDefinition ( ClangASTType & clang_type )
{
// We have a struct/union/class/enum that needs to be fully resolved.
return false ;
}
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 ( ) ;
if ( symtab )
{
const addr_t exe_file_addr = exe_so_addr . GetFileAddress ( ) ;
const DebugMap : : Entry * debug_map_entry = m_debug_map . FindEntryThatContains ( exe_file_addr ) ;
if ( debug_map_entry )
{
sc . symbol = symtab - > SymbolAtIndex ( debug_map_entry - > data . GetExeSymbolIndex ( ) ) ;
if ( sc . symbol ! = NULL )
{
resolved_flags | = eSymbolContextSymbol ;
uint32_t oso_idx = 0 ;
CompileUnitInfo * comp_unit_info = GetCompileUnitInfoForSymbolWithID ( sc . symbol - > GetID ( ) , & oso_idx ) ;
if ( comp_unit_info )
{
comp_unit_info - > GetFileRangeMap ( this ) ;
Module * oso_module = GetModuleByCompUnitInfo ( comp_unit_info ) ;
if ( oso_module )
{
lldb : : addr_t oso_file_addr = exe_file_addr - debug_map_entry - > GetRangeBase ( ) + debug_map_entry - > data . GetOSOFileAddress ( ) ;
Address oso_so_addr ;
if ( oso_module - > ResolveFileAddress ( oso_file_addr , oso_so_addr ) )
{
resolved_flags | = oso_module - > GetSymbolVendor ( ) - > ResolveSymbolContext ( oso_so_addr , resolve_scope , sc ) ;
}
}
}
}
}
}
return resolved_flags ;
}
uint32_t
SymbolFileDWARFDebugMap : : ResolveSymbolContext ( const FileSpec & file_spec , uint32_t line , bool check_inlines , uint32_t resolve_scope , SymbolContextList & sc_list )
{
const uint32_t initial = sc_list . GetSize ( ) ;
const uint32_t cu_count = GetNumCompileUnits ( ) ;
for ( uint32_t i = 0 ; i < cu_count ; + + i )
{
// If we are checking for inlines, then we need to look through all
// compile units no matter if "file_spec" matches.
bool resolve = check_inlines ;
if ( ! resolve )
{
FileSpec so_file_spec ;
if ( GetFileSpecForSO ( i , so_file_spec ) )
{
// Match the full path if the incoming file_spec has a directory (not just a basename)
2013-11-06 11:48:53 -05:00
const bool full_match = ( bool ) file_spec . GetDirectory ( ) ;
2013-08-23 13:46:38 -04:00
resolve = FileSpec : : Equal ( file_spec , so_file_spec , full_match ) ;
}
}
if ( resolve )
{
SymbolFileDWARF * oso_dwarf = GetSymbolFileByOSOIndex ( i ) ;
if ( oso_dwarf )
oso_dwarf - > ResolveSymbolContext ( file_spec , line , check_inlines , resolve_scope , sc_list ) ;
}
}
return sc_list . GetSize ( ) - initial ;
}
uint32_t
SymbolFileDWARFDebugMap : : PrivateFindGlobalVariables
(
const ConstString & name ,
const ClangNamespaceDecl * namespace_decl ,
const std : : vector < uint32_t > & indexes , // Indexes into the symbol table that match "name"
uint32_t max_matches ,
VariableList & variables
)
{
const uint32_t original_size = variables . GetSize ( ) ;
const size_t match_count = indexes . size ( ) ;
for ( size_t i = 0 ; i < match_count ; + + i )
{
uint32_t oso_idx ;
CompileUnitInfo * comp_unit_info = GetCompileUnitInfoForSymbolWithIndex ( indexes [ i ] , & oso_idx ) ;
if ( comp_unit_info )
{
SymbolFileDWARF * oso_dwarf = GetSymbolFileByOSOIndex ( oso_idx ) ;
if ( oso_dwarf )
{
if ( oso_dwarf - > FindGlobalVariables ( name , namespace_decl , true , max_matches , variables ) )
if ( variables . GetSize ( ) > max_matches )
break ;
}
}
}
return variables . GetSize ( ) - original_size ;
}
uint32_t
SymbolFileDWARFDebugMap : : FindGlobalVariables ( const ConstString & name , const ClangNamespaceDecl * namespace_decl , bool append , uint32_t max_matches , VariableList & variables )
{
// If we aren't appending the results to this list, then clear the list
if ( ! append )
variables . Clear ( ) ;
// Remember how many variables are in the list before we search in case
// we are appending the results to a variable list.
const uint32_t original_size = variables . GetSize ( ) ;
uint32_t total_matches = 0 ;
2015-07-03 12:57:06 -04:00
ForEachSymbolFile ( [ & ] ( SymbolFileDWARF * oso_dwarf ) - > bool {
2013-08-23 13:46:38 -04:00
const uint32_t oso_matches = oso_dwarf - > FindGlobalVariables ( name ,
namespace_decl ,
2015-07-03 12:57:06 -04:00
true ,
max_matches ,
2013-08-23 13:46:38 -04:00
variables ) ;
if ( oso_matches > 0 )
{
total_matches + = oso_matches ;
2015-07-03 12:57:06 -04:00
2013-08-23 13:46:38 -04:00
// Are we getting all matches?
if ( max_matches = = UINT32_MAX )
2015-07-03 12:57:06 -04:00
return false ; // Yep, continue getting everything
2013-08-23 13:46:38 -04:00
// If we have found enough matches, lets get out
if ( max_matches > = total_matches )
2015-07-03 12:57:06 -04:00
return true ;
2013-08-23 13:46:38 -04:00
// Update the max matches for any subsequent calls to find globals
// in any other object files with DWARF
max_matches - = oso_matches ;
}
2015-07-03 12:57:06 -04:00
return false ;
} ) ;
2013-08-23 13:46:38 -04:00
// Return the number of variable that were appended to the list
return variables . GetSize ( ) - original_size ;
}
uint32_t
SymbolFileDWARFDebugMap : : FindGlobalVariables ( const RegularExpression & regex , bool append , uint32_t max_matches , VariableList & variables )
{
// If we aren't appending the results to this list, then clear the list
if ( ! append )
variables . Clear ( ) ;
// Remember how many variables are in the list before we search in case
// we are appending the results to a variable list.
const uint32_t original_size = variables . GetSize ( ) ;
uint32_t total_matches = 0 ;
2015-07-03 12:57:06 -04:00
ForEachSymbolFile ( [ & ] ( SymbolFileDWARF * oso_dwarf ) - > bool {
const uint32_t oso_matches = oso_dwarf - > FindGlobalVariables ( regex ,
2013-08-23 13:46:38 -04:00
true ,
max_matches ,
variables ) ;
if ( oso_matches > 0 )
{
total_matches + = oso_matches ;
// Are we getting all matches?
if ( max_matches = = UINT32_MAX )
2015-07-03 12:57:06 -04:00
return false ; // Yep, continue getting everything
2013-08-23 13:46:38 -04:00
// If we have found enough matches, lets get out
if ( max_matches > = total_matches )
2015-07-03 12:57:06 -04:00
return true ;
2013-08-23 13:46:38 -04:00
// Update the max matches for any subsequent calls to find globals
// in any other object files with DWARF
max_matches - = oso_matches ;
}
2015-07-03 12:57:06 -04:00
return false ;
} ) ;
2013-08-23 13:46:38 -04:00
// Return the number of variable that were appended to the list
return variables . GetSize ( ) - original_size ;
}
int
SymbolFileDWARFDebugMap : : SymbolContainsSymbolWithIndex ( uint32_t * symbol_idx_ptr , const CompileUnitInfo * comp_unit_info )
{
const uint32_t symbol_idx = * symbol_idx_ptr ;
if ( symbol_idx < comp_unit_info - > first_symbol_index )
return - 1 ;
if ( symbol_idx < = comp_unit_info - > last_symbol_index )
return 0 ;
return 1 ;
}
int
SymbolFileDWARFDebugMap : : SymbolContainsSymbolWithID ( user_id_t * symbol_idx_ptr , const CompileUnitInfo * comp_unit_info )
{
const user_id_t symbol_id = * symbol_idx_ptr ;
if ( symbol_id < comp_unit_info - > first_symbol_id )
return - 1 ;
if ( symbol_id < = comp_unit_info - > last_symbol_id )
return 0 ;
return 1 ;
}
SymbolFileDWARFDebugMap : : CompileUnitInfo *
SymbolFileDWARFDebugMap : : GetCompileUnitInfoForSymbolWithIndex ( uint32_t symbol_idx , uint32_t * oso_idx_ptr )
{
const uint32_t oso_index_count = m_compile_unit_infos . size ( ) ;
CompileUnitInfo * comp_unit_info = NULL ;
if ( oso_index_count )
{
comp_unit_info = ( CompileUnitInfo * ) bsearch ( & symbol_idx ,
& m_compile_unit_infos [ 0 ] ,
m_compile_unit_infos . size ( ) ,
sizeof ( CompileUnitInfo ) ,
( ComparisonFunction ) SymbolContainsSymbolWithIndex ) ;
}
if ( oso_idx_ptr )
{
if ( comp_unit_info ! = NULL )
* oso_idx_ptr = comp_unit_info - & m_compile_unit_infos [ 0 ] ;
else
* oso_idx_ptr = UINT32_MAX ;
}
return comp_unit_info ;
}
SymbolFileDWARFDebugMap : : CompileUnitInfo *
SymbolFileDWARFDebugMap : : GetCompileUnitInfoForSymbolWithID ( user_id_t symbol_id , uint32_t * oso_idx_ptr )
{
const uint32_t oso_index_count = m_compile_unit_infos . size ( ) ;
CompileUnitInfo * comp_unit_info = NULL ;
if ( oso_index_count )
{
comp_unit_info = ( CompileUnitInfo * ) : : bsearch ( & symbol_id ,
& m_compile_unit_infos [ 0 ] ,
m_compile_unit_infos . size ( ) ,
sizeof ( CompileUnitInfo ) ,
( ComparisonFunction ) SymbolContainsSymbolWithID ) ;
}
if ( oso_idx_ptr )
{
if ( comp_unit_info ! = NULL )
* oso_idx_ptr = comp_unit_info - & m_compile_unit_infos [ 0 ] ;
else
* oso_idx_ptr = UINT32_MAX ;
}
return comp_unit_info ;
}
static void
RemoveFunctionsWithModuleNotEqualTo ( const ModuleSP & module_sp , SymbolContextList & sc_list , uint32_t start_idx )
{
// We found functions in .o files. Not all functions in the .o files
// will have made it into the final output file. The ones that did
// make it into the final output file will have a section whose module
// matches the module from the ObjectFile for this SymbolFile. When
// the modules don't match, then we have something that was in a
// .o file, but doesn't map to anything in the final executable.
uint32_t i = start_idx ;
while ( i < sc_list . GetSize ( ) )
{
SymbolContext sc ;
sc_list . GetContextAtIndex ( i , sc ) ;
if ( sc . function )
{
const SectionSP section_sp ( sc . function - > GetAddressRange ( ) . GetBaseAddress ( ) . GetSection ( ) ) ;
if ( section_sp - > GetModule ( ) ! = module_sp )
{
sc_list . RemoveContextAtIndex ( i ) ;
continue ;
}
}
+ + i ;
}
}
uint32_t
SymbolFileDWARFDebugMap : : FindFunctions ( const ConstString & name , const ClangNamespaceDecl * namespace_decl , uint32_t name_type_mask , bool include_inlines , bool append , SymbolContextList & sc_list )
{
Timer scoped_timer ( __PRETTY_FUNCTION__ ,
" SymbolFileDWARFDebugMap::FindFunctions (name = %s) " ,
name . GetCString ( ) ) ;
uint32_t initial_size = 0 ;
if ( append )
initial_size = sc_list . GetSize ( ) ;
else
sc_list . Clear ( ) ;
2015-07-03 12:57:06 -04:00
ForEachSymbolFile ( [ & ] ( SymbolFileDWARF * oso_dwarf ) - > bool {
2013-08-23 13:46:38 -04:00
uint32_t sc_idx = sc_list . GetSize ( ) ;
if ( oso_dwarf - > FindFunctions ( name , namespace_decl , name_type_mask , include_inlines , true , sc_list ) )
{
RemoveFunctionsWithModuleNotEqualTo ( m_obj_file - > GetModule ( ) , sc_list , sc_idx ) ;
}
2015-07-03 12:57:06 -04:00
return false ;
} ) ;
2013-08-23 13:46:38 -04:00
return sc_list . GetSize ( ) - initial_size ;
}
uint32_t
SymbolFileDWARFDebugMap : : FindFunctions ( const RegularExpression & regex , bool include_inlines , bool append , SymbolContextList & sc_list )
{
Timer scoped_timer ( __PRETTY_FUNCTION__ ,
" SymbolFileDWARFDebugMap::FindFunctions (regex = '%s') " ,
regex . GetText ( ) ) ;
uint32_t initial_size = 0 ;
if ( append )
initial_size = sc_list . GetSize ( ) ;
else
sc_list . Clear ( ) ;
2015-07-03 12:57:06 -04:00
ForEachSymbolFile ( [ & ] ( SymbolFileDWARF * oso_dwarf ) - > bool {
2013-08-23 13:46:38 -04:00
uint32_t sc_idx = sc_list . GetSize ( ) ;
if ( oso_dwarf - > FindFunctions ( regex , include_inlines , true , sc_list ) )
{
RemoveFunctionsWithModuleNotEqualTo ( m_obj_file - > GetModule ( ) , sc_list , sc_idx ) ;
}
2015-07-03 12:57:06 -04:00
return false ;
} ) ;
2013-08-23 13:46:38 -04:00
return sc_list . GetSize ( ) - initial_size ;
}
size_t
SymbolFileDWARFDebugMap : : GetTypes ( SymbolContextScope * sc_scope ,
uint32_t type_mask ,
TypeList & type_list )
{
Timer scoped_timer ( __PRETTY_FUNCTION__ ,
" SymbolFileDWARFDebugMap::GetTypes (type_mask = 0x%8.8x) " ,
type_mask ) ;
uint32_t initial_size = type_list . GetSize ( ) ;
SymbolFileDWARF * oso_dwarf = NULL ;
if ( sc_scope )
{
SymbolContext sc ;
sc_scope - > CalculateSymbolContext ( & sc ) ;
CompileUnitInfo * cu_info = GetCompUnitInfo ( sc ) ;
if ( cu_info )
{
oso_dwarf = GetSymbolFileByCompUnitInfo ( cu_info ) ;
if ( oso_dwarf )
oso_dwarf - > GetTypes ( sc_scope , type_mask , type_list ) ;
}
}
else
{
2015-07-03 12:57:06 -04:00
ForEachSymbolFile ( [ & ] ( SymbolFileDWARF * oso_dwarf ) - > bool {
2013-08-23 13:46:38 -04:00
oso_dwarf - > GetTypes ( sc_scope , type_mask , type_list ) ;
2015-07-03 12:57:06 -04:00
return false ;
} ) ;
2013-08-23 13:46:38 -04:00
}
return type_list . GetSize ( ) - initial_size ;
}
TypeSP
SymbolFileDWARFDebugMap : : FindDefinitionTypeForDWARFDeclContext ( const DWARFDeclContext & die_decl_ctx )
{
TypeSP type_sp ;
2015-07-03 12:57:06 -04:00
ForEachSymbolFile ( [ & ] ( SymbolFileDWARF * oso_dwarf ) - > bool {
2013-08-23 13:46:38 -04:00
type_sp = oso_dwarf - > FindDefinitionTypeForDWARFDeclContext ( die_decl_ctx ) ;
2015-07-03 12:57:06 -04:00
return ( ( bool ) type_sp ) ;
} ) ;
2013-08-23 13:46:38 -04:00
return type_sp ;
}
bool
SymbolFileDWARFDebugMap : : Supports_DW_AT_APPLE_objc_complete_type ( SymbolFileDWARF * skip_dwarf_oso )
{
if ( m_supports_DW_AT_APPLE_objc_complete_type = = eLazyBoolCalculate )
{
m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo ;
2015-07-03 12:57:06 -04:00
ForEachSymbolFile ( [ & ] ( SymbolFileDWARF * oso_dwarf ) - > bool {
2013-08-23 13:46:38 -04:00
if ( skip_dwarf_oso ! = oso_dwarf & & oso_dwarf - > Supports_DW_AT_APPLE_objc_complete_type ( NULL ) )
{
m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes ;
2015-07-03 12:57:06 -04:00
return true ;
2013-08-23 13:46:38 -04:00
}
2015-07-03 12:57:06 -04:00
return false ;
} ) ;
2013-08-23 13:46:38 -04:00
}
return m_supports_DW_AT_APPLE_objc_complete_type = = eLazyBoolYes ;
}
TypeSP
SymbolFileDWARFDebugMap : : FindCompleteObjCDefinitionTypeForDIE ( const DWARFDebugInfoEntry * die ,
const ConstString & type_name ,
bool must_be_implementation )
{
2015-07-03 12:57:06 -04:00
// If we have a debug map, we will have an Objective C symbol whose name is
// the type name and whose type is eSymbolTypeObjCClass. If we can find that
// symbol and find its containing parent, we can locate the .o file that will
// contain the implementation definition since it will be scoped inside the N_SO
// and we can then locate the SymbolFileDWARF that corresponds to that N_SO.
SymbolFileDWARF * oso_dwarf = NULL ;
2013-08-23 13:46:38 -04:00
TypeSP type_sp ;
2015-07-03 12:57:06 -04:00
ObjectFile * module_objfile = m_obj_file - > GetModule ( ) - > GetObjectFile ( ) ;
if ( module_objfile )
2013-08-23 13:46:38 -04:00
{
2015-07-03 12:57:06 -04:00
Symtab * symtab = module_objfile - > GetSymtab ( ) ;
if ( symtab )
{
Symbol * objc_class_symbol = symtab - > FindFirstSymbolWithNameAndType ( type_name , eSymbolTypeObjCClass , Symtab : : eDebugAny , Symtab : : eVisibilityAny ) ;
if ( objc_class_symbol )
{
// Get the N_SO symbol that contains the objective C class symbol as this
// should be the .o file that contains the real definition...
const Symbol * source_file_symbol = symtab - > GetParent ( objc_class_symbol ) ;
if ( source_file_symbol & & source_file_symbol - > GetType ( ) = = eSymbolTypeSourceFile )
{
const uint32_t source_file_symbol_idx = symtab - > GetIndexForSymbol ( source_file_symbol ) ;
if ( source_file_symbol_idx ! = UINT32_MAX )
{
CompileUnitInfo * compile_unit_info = GetCompileUnitInfoForSymbolWithIndex ( source_file_symbol_idx , NULL ) ;
if ( compile_unit_info )
{
oso_dwarf = GetSymbolFileByCompUnitInfo ( compile_unit_info ) ;
if ( oso_dwarf )
{
TypeSP type_sp ( oso_dwarf - > FindCompleteObjCDefinitionTypeForDIE ( die , type_name , must_be_implementation ) ) ;
if ( type_sp )
{
return type_sp ;
}
}
}
}
}
}
}
2013-08-23 13:46:38 -04:00
}
2015-07-03 12:57:06 -04:00
// Only search all .o files for the definition if we don't need the implementation
// because otherwise, with a valid debug map we should have the ObjC class symbol and
// the code above should have found it.
if ( must_be_implementation = = false )
{
TypeSP type_sp ;
ForEachSymbolFile ( [ & ] ( SymbolFileDWARF * oso_dwarf ) - > bool {
type_sp = oso_dwarf - > FindCompleteObjCDefinitionTypeForDIE ( die , type_name , must_be_implementation ) ;
return ( bool ) type_sp ;
} ) ;
return type_sp ;
}
return TypeSP ( ) ;
2013-08-23 13:46:38 -04:00
}
uint32_t
SymbolFileDWARFDebugMap : : FindTypes
(
const SymbolContext & sc ,
const ConstString & name ,
const ClangNamespaceDecl * namespace_decl ,
bool append ,
uint32_t max_matches ,
TypeList & types
)
{
if ( ! append )
types . Clear ( ) ;
const uint32_t initial_types_size = types . GetSize ( ) ;
SymbolFileDWARF * oso_dwarf ;
if ( sc . comp_unit )
{
oso_dwarf = GetSymbolFile ( sc ) ;
if ( oso_dwarf )
return oso_dwarf - > FindTypes ( sc , name , namespace_decl , append , max_matches , types ) ;
}
else
{
2015-07-03 12:57:06 -04:00
ForEachSymbolFile ( [ & ] ( SymbolFileDWARF * oso_dwarf ) - > bool {
2013-08-23 13:46:38 -04:00
oso_dwarf - > FindTypes ( sc , name , namespace_decl , append , max_matches , types ) ;
2015-07-03 12:57:06 -04:00
return false ;
} ) ;
2013-08-23 13:46:38 -04:00
}
return types . GetSize ( ) - initial_types_size ;
}
//
//uint32_t
//SymbolFileDWARFDebugMap::FindTypes (const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, Type::Encoding encoding, lldb::user_id_t udt_uid, TypeList& types)
//{
// SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
// if (oso_dwarf)
// return oso_dwarf->FindTypes (sc, regex, append, max_matches, encoding, udt_uid, types);
// return 0;
//}
ClangNamespaceDecl
SymbolFileDWARFDebugMap : : FindNamespace ( const lldb_private : : SymbolContext & sc ,
const lldb_private : : ConstString & name ,
const ClangNamespaceDecl * parent_namespace_decl )
{
ClangNamespaceDecl matching_namespace ;
SymbolFileDWARF * oso_dwarf ;
if ( sc . comp_unit )
{
oso_dwarf = GetSymbolFile ( sc ) ;
if ( oso_dwarf )
matching_namespace = oso_dwarf - > FindNamespace ( sc , name , parent_namespace_decl ) ;
}
else
{
2015-07-03 12:57:06 -04:00
ForEachSymbolFile ( [ & ] ( SymbolFileDWARF * oso_dwarf ) - > bool {
2013-08-23 13:46:38 -04:00
matching_namespace = oso_dwarf - > FindNamespace ( sc , name , parent_namespace_decl ) ;
2015-07-03 12:57:06 -04:00
return ( bool ) matching_namespace ;
} ) ;
2013-08-23 13:46:38 -04:00
}
return matching_namespace ;
}
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
lldb_private : : ConstString
SymbolFileDWARFDebugMap : : GetPluginName ( )
{
return GetPluginNameStatic ( ) ;
}
uint32_t
SymbolFileDWARFDebugMap : : GetPluginVersion ( )
{
return 1 ;
}
lldb : : CompUnitSP
SymbolFileDWARFDebugMap : : GetCompileUnit ( SymbolFileDWARF * oso_dwarf )
{
if ( oso_dwarf )
{
const uint32_t cu_count = GetNumCompileUnits ( ) ;
for ( uint32_t cu_idx = 0 ; cu_idx < cu_count ; + + cu_idx )
{
SymbolFileDWARF * oso_symfile = GetSymbolFileByCompUnitInfo ( & m_compile_unit_infos [ cu_idx ] ) ;
if ( oso_symfile = = oso_dwarf )
{
if ( ! m_compile_unit_infos [ cu_idx ] . compile_unit_sp )
m_compile_unit_infos [ cu_idx ] . compile_unit_sp = ParseCompileUnitAtIndex ( cu_idx ) ;
return m_compile_unit_infos [ cu_idx ] . compile_unit_sp ;
}
}
}
assert ( ! " this shouldn't happen " ) ;
return lldb : : CompUnitSP ( ) ;
}
SymbolFileDWARFDebugMap : : CompileUnitInfo *
SymbolFileDWARFDebugMap : : GetCompileUnitInfo ( SymbolFileDWARF * oso_dwarf )
{
if ( oso_dwarf )
{
const uint32_t cu_count = GetNumCompileUnits ( ) ;
for ( uint32_t cu_idx = 0 ; cu_idx < cu_count ; + + cu_idx )
{
SymbolFileDWARF * oso_symfile = GetSymbolFileByCompUnitInfo ( & m_compile_unit_infos [ cu_idx ] ) ;
if ( oso_symfile = = oso_dwarf )
{
return & m_compile_unit_infos [ cu_idx ] ;
}
}
}
return NULL ;
}
void
SymbolFileDWARFDebugMap : : SetCompileUnit ( SymbolFileDWARF * oso_dwarf , const CompUnitSP & cu_sp )
{
if ( oso_dwarf )
{
const uint32_t cu_count = GetNumCompileUnits ( ) ;
for ( uint32_t cu_idx = 0 ; cu_idx < cu_count ; + + cu_idx )
{
SymbolFileDWARF * oso_symfile = GetSymbolFileByCompUnitInfo ( & m_compile_unit_infos [ cu_idx ] ) ;
if ( oso_symfile = = oso_dwarf )
{
if ( m_compile_unit_infos [ cu_idx ] . compile_unit_sp )
{
assert ( m_compile_unit_infos [ cu_idx ] . compile_unit_sp . get ( ) = = cu_sp . get ( ) ) ;
}
else
{
m_compile_unit_infos [ cu_idx ] . compile_unit_sp = cu_sp ;
m_obj_file - > GetModule ( ) - > GetSymbolVendor ( ) - > SetCompileUnitAtIndex ( cu_idx , cu_sp ) ;
}
}
}
}
}
void
SymbolFileDWARFDebugMap : : CompleteTagDecl ( void * baton , clang : : TagDecl * decl )
{
SymbolFileDWARFDebugMap * symbol_file_dwarf = ( SymbolFileDWARFDebugMap * ) baton ;
ClangASTType clang_type = symbol_file_dwarf - > GetClangASTContext ( ) . GetTypeForDecl ( decl ) ;
if ( clang_type )
{
2015-07-03 12:57:06 -04:00
symbol_file_dwarf - > ForEachSymbolFile ( [ & ] ( SymbolFileDWARF * oso_dwarf ) - > bool {
2013-08-23 13:46:38 -04:00
if ( oso_dwarf - > HasForwardDeclForClangType ( clang_type ) )
{
oso_dwarf - > ResolveClangOpaqueTypeDefinition ( clang_type ) ;
2015-07-03 12:57:06 -04:00
return true ;
2013-08-23 13:46:38 -04:00
}
2015-07-03 12:57:06 -04:00
return false ;
} ) ;
2013-08-23 13:46:38 -04:00
}
}
void
SymbolFileDWARFDebugMap : : CompleteObjCInterfaceDecl ( void * baton , clang : : ObjCInterfaceDecl * decl )
{
SymbolFileDWARFDebugMap * symbol_file_dwarf = ( SymbolFileDWARFDebugMap * ) baton ;
ClangASTType clang_type = symbol_file_dwarf - > GetClangASTContext ( ) . GetTypeForDecl ( decl ) ;
if ( clang_type )
{
2015-07-03 12:57:06 -04:00
symbol_file_dwarf - > ForEachSymbolFile ( [ & ] ( SymbolFileDWARF * oso_dwarf ) - > bool {
2013-08-23 13:46:38 -04:00
if ( oso_dwarf - > HasForwardDeclForClangType ( clang_type ) )
{
oso_dwarf - > ResolveClangOpaqueTypeDefinition ( clang_type ) ;
2015-07-03 12:57:06 -04:00
return true ;
2013-08-23 13:46:38 -04:00
}
2015-07-03 12:57:06 -04:00
return false ;
} ) ;
2013-08-23 13:46:38 -04:00
}
}
2015-07-03 12:57:06 -04:00
bool
SymbolFileDWARFDebugMap : : LayoutRecordType ( void * baton , const clang : : RecordDecl * record_decl , uint64_t & size ,
uint64_t & alignment ,
llvm : : DenseMap < const clang : : FieldDecl * , uint64_t > & field_offsets ,
llvm : : DenseMap < const clang : : CXXRecordDecl * , clang : : CharUnits > & base_offsets ,
llvm : : DenseMap < const clang : : CXXRecordDecl * , clang : : CharUnits > & vbase_offsets )
2013-08-23 13:46:38 -04:00
{
SymbolFileDWARFDebugMap * symbol_file_dwarf = ( SymbolFileDWARFDebugMap * ) baton ;
2015-07-03 12:57:06 -04:00
bool laid_out = false ;
symbol_file_dwarf - > ForEachSymbolFile ( [ & ] ( SymbolFileDWARF * oso_dwarf ) - > bool {
return ( laid_out = oso_dwarf - > LayoutRecordType ( record_decl , size , alignment , field_offsets , base_offsets , vbase_offsets ) ) ;
} ) ;
return laid_out ;
2013-08-23 13:46:38 -04:00
}
clang : : DeclContext *
SymbolFileDWARFDebugMap : : GetClangDeclContextContainingTypeUID ( lldb : : user_id_t type_uid )
{
const uint64_t oso_idx = GetOSOIndexFromUserID ( type_uid ) ;
SymbolFileDWARF * oso_dwarf = GetSymbolFileByOSOIndex ( oso_idx ) ;
if ( oso_dwarf )
return oso_dwarf - > GetClangDeclContextContainingTypeUID ( type_uid ) ;
return NULL ;
}
clang : : DeclContext *
SymbolFileDWARFDebugMap : : GetClangDeclContextForTypeUID ( const lldb_private : : SymbolContext & sc , lldb : : user_id_t type_uid )
{
const uint64_t oso_idx = GetOSOIndexFromUserID ( type_uid ) ;
SymbolFileDWARF * oso_dwarf = GetSymbolFileByOSOIndex ( oso_idx ) ;
if ( oso_dwarf )
return oso_dwarf - > GetClangDeclContextForTypeUID ( sc , type_uid ) ;
return NULL ;
}
bool
SymbolFileDWARFDebugMap : : AddOSOFileRange ( CompileUnitInfo * cu_info ,
lldb : : addr_t exe_file_addr ,
lldb : : addr_t oso_file_addr ,
lldb : : addr_t oso_byte_size )
{
const uint32_t debug_map_idx = m_debug_map . FindEntryIndexThatContains ( exe_file_addr ) ;
if ( debug_map_idx ! = UINT32_MAX )
{
DebugMap : : Entry * debug_map_entry = m_debug_map . FindEntryThatContains ( exe_file_addr ) ;
debug_map_entry - > data . SetOSOFileAddress ( oso_file_addr ) ;
cu_info - > file_range_map . Append ( FileRangeMap : : Entry ( oso_file_addr , oso_byte_size , exe_file_addr ) ) ;
return true ;
}
return false ;
}
void
SymbolFileDWARFDebugMap : : FinalizeOSOFileRanges ( CompileUnitInfo * cu_info )
{
cu_info - > file_range_map . Sort ( ) ;
# if defined(DEBUG_OSO_DMAP)
const FileRangeMap & oso_file_range_map = cu_info - > GetFileRangeMap ( this ) ;
const size_t n = oso_file_range_map . GetSize ( ) ;
printf ( " SymbolFileDWARFDebugMap::FinalizeOSOFileRanges (cu_info = %p) %s \n " ,
cu_info ,
cu_info - > oso_sp - > module_sp - > GetFileSpec ( ) . GetPath ( ) . c_str ( ) ) ;
for ( size_t i = 0 ; i < n ; + + i )
{
const FileRangeMap : : Entry & entry = oso_file_range_map . GetEntryRef ( i ) ;
printf ( " oso [0x%16.16 " PRIx64 " - 0x%16.16 " PRIx64 " ) ==> exe [0x%16.16 " PRIx64 " - 0x%16.16 " PRIx64 " ) \n " ,
entry . GetRangeBase ( ) , entry . GetRangeEnd ( ) ,
entry . data , entry . data + entry . GetByteSize ( ) ) ;
}
# endif
}
lldb : : addr_t
SymbolFileDWARFDebugMap : : LinkOSOFileAddress ( SymbolFileDWARF * oso_symfile , lldb : : addr_t oso_file_addr )
{
CompileUnitInfo * cu_info = GetCompileUnitInfo ( oso_symfile ) ;
if ( cu_info )
{
const FileRangeMap : : Entry * oso_range_entry = cu_info - > GetFileRangeMap ( this ) . FindEntryThatContains ( oso_file_addr ) ;
if ( oso_range_entry )
{
const DebugMap : : Entry * debug_map_entry = m_debug_map . FindEntryThatContains ( oso_range_entry - > data ) ;
if ( debug_map_entry )
{
const lldb : : addr_t offset = oso_file_addr - oso_range_entry - > GetRangeBase ( ) ;
const lldb : : addr_t exe_file_addr = debug_map_entry - > GetRangeBase ( ) + offset ;
return exe_file_addr ;
}
}
}
return LLDB_INVALID_ADDRESS ;
}
bool
SymbolFileDWARFDebugMap : : LinkOSOAddress ( Address & addr )
{
// Make sure this address hasn't been fixed already
Module * exe_module = GetObjectFile ( ) - > GetModule ( ) . get ( ) ;
Module * addr_module = addr . GetModule ( ) . get ( ) ;
if ( addr_module = = exe_module )
return true ; // Address is already in terms of the main executable module
CompileUnitInfo * cu_info = GetCompileUnitInfo ( GetSymbolFileAsSymbolFileDWARF ( addr_module - > GetSymbolVendor ( ) - > GetSymbolFile ( ) ) ) ;
if ( cu_info )
{
const lldb : : addr_t oso_file_addr = addr . GetFileAddress ( ) ;
const FileRangeMap : : Entry * oso_range_entry = cu_info - > GetFileRangeMap ( this ) . FindEntryThatContains ( oso_file_addr ) ;
if ( oso_range_entry )
{
const DebugMap : : Entry * debug_map_entry = m_debug_map . FindEntryThatContains ( oso_range_entry - > data ) ;
if ( debug_map_entry )
{
const lldb : : addr_t offset = oso_file_addr - oso_range_entry - > GetRangeBase ( ) ;
const lldb : : addr_t exe_file_addr = debug_map_entry - > GetRangeBase ( ) + offset ;
return exe_module - > ResolveFileAddress ( exe_file_addr , addr ) ;
}
}
}
return true ;
}
LineTable *
SymbolFileDWARFDebugMap : : LinkOSOLineTable ( SymbolFileDWARF * oso_dwarf , LineTable * line_table )
{
CompileUnitInfo * cu_info = GetCompileUnitInfo ( oso_dwarf ) ;
if ( cu_info )
return line_table - > LinkLineTable ( cu_info - > GetFileRangeMap ( this ) ) ;
return NULL ;
}
size_t
SymbolFileDWARFDebugMap : : AddOSOARanges ( SymbolFileDWARF * dwarf2Data , DWARFDebugAranges * debug_aranges )
{
size_t num_line_entries_added = 0 ;
if ( debug_aranges & & dwarf2Data )
{
CompileUnitInfo * compile_unit_info = GetCompileUnitInfo ( dwarf2Data ) ;
if ( compile_unit_info )
{
const FileRangeMap & file_range_map = compile_unit_info - > GetFileRangeMap ( this ) ;
for ( size_t idx = 0 ;
idx < file_range_map . GetSize ( ) ;
idx + + )
{
const FileRangeMap : : Entry * entry = file_range_map . GetEntryAtIndex ( idx ) ;
if ( entry )
{
printf ( " [0x%16.16 " PRIx64 " - 0x%16.16 " PRIx64 " ) \n " , entry - > GetRangeBase ( ) , entry - > GetRangeEnd ( ) ) ;
debug_aranges - > AppendRange ( dwarf2Data - > GetID ( ) , entry - > GetRangeBase ( ) , entry - > GetRangeEnd ( ) ) ;
num_line_entries_added + + ;
}
}
}
}
return num_line_entries_added ;
}