2013-08-23 13:46:38 -04:00
//===-- SymbolFileDWARF.cpp ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "SymbolFileDWARF.h"
// Other libraries and framework includes
# include "clang/AST/ASTConsumer.h"
# include "clang/AST/ASTContext.h"
# include "clang/AST/Decl.h"
# include "clang/AST/DeclGroup.h"
# include "clang/AST/DeclObjC.h"
# include "clang/AST/DeclTemplate.h"
# include "clang/Basic/Builtins.h"
# include "clang/Basic/IdentifierTable.h"
# include "clang/Basic/LangOptions.h"
# include "clang/Basic/SourceManager.h"
# include "clang/Basic/TargetInfo.h"
# include "clang/Basic/Specifiers.h"
# include "clang/Sema/DeclSpec.h"
# include "llvm/Support/Casting.h"
2015-07-03 12:57:06 -04:00
# include "lldb/Core/ArchSpec.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Core/Module.h"
2015-07-03 12:57:06 -04:00
# include "lldb/Core/ModuleList.h"
# include "lldb/Core/ModuleSpec.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Core/PluginManager.h"
# include "lldb/Core/RegularExpression.h"
# include "lldb/Core/Scalar.h"
# include "lldb/Core/Section.h"
# include "lldb/Core/StreamFile.h"
# include "lldb/Core/StreamString.h"
# include "lldb/Core/Timer.h"
# include "lldb/Core/Value.h"
2015-07-03 12:57:06 -04:00
# include "lldb/Expression/ClangModulesDeclVendor.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Host/Host.h"
# include "lldb/Symbol/Block.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 "lldb/Target/ObjCLanguageRuntime.h"
# include "lldb/Target/CPPLanguageRuntime.h"
# include "DWARFCompileUnit.h"
# include "DWARFDebugAbbrev.h"
# include "DWARFDebugAranges.h"
# include "DWARFDebugInfo.h"
# include "DWARFDebugInfoEntry.h"
# include "DWARFDebugLine.h"
# include "DWARFDebugPubnames.h"
# include "DWARFDebugRanges.h"
# include "DWARFDeclContext.h"
# include "DWARFDIECollection.h"
# include "DWARFFormValue.h"
# include "DWARFLocationList.h"
# include "LogChannelDWARF.h"
# include "SymbolFileDWARFDebugMap.h"
# include <map>
2014-11-25 16:00:58 -05:00
# include <ctype.h>
# include <string.h>
2013-08-23 13:46:38 -04:00
//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
# ifdef ENABLE_DEBUG_PRINTF
# include <stdio.h>
2013-11-06 11:48:53 -05:00
# define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
2013-08-23 13:46:38 -04:00
# else
# define DEBUG_PRINTF(fmt, ...)
# endif
# define DIE_IS_BEING_PARSED ((lldb_private::Type*)1)
using namespace lldb ;
using namespace lldb_private ;
//static inline bool
//child_requires_parent_class_union_or_struct_to_be_completed (dw_tag_t tag)
//{
// switch (tag)
// {
// default:
// break;
// case DW_TAG_subprogram:
// case DW_TAG_inlined_subroutine:
// case DW_TAG_class_type:
// case DW_TAG_structure_type:
// case DW_TAG_union_type:
// return true;
// }
// return false;
//}
//
static AccessType
DW_ACCESS_to_AccessType ( uint32_t dwarf_accessibility )
{
switch ( dwarf_accessibility )
{
case DW_ACCESS_public : return eAccessPublic ;
case DW_ACCESS_private : return eAccessPrivate ;
case DW_ACCESS_protected : return eAccessProtected ;
default : break ;
}
return eAccessNone ;
}
2014-11-25 16:00:58 -05:00
static const char *
removeHostnameFromPathname ( const char * path_from_dwarf )
{
if ( ! path_from_dwarf | | ! path_from_dwarf [ 0 ] )
{
return path_from_dwarf ;
}
const char * colon_pos = strchr ( path_from_dwarf , ' : ' ) ;
if ( ! colon_pos )
{
return path_from_dwarf ;
}
// check whether we have a windows path, and so the first character
// is a drive-letter not a hostname.
if (
colon_pos = = path_from_dwarf + 1 & &
isalpha ( * path_from_dwarf ) & &
strlen ( path_from_dwarf ) > 2 & &
' \\ ' = = path_from_dwarf [ 2 ] )
{
return path_from_dwarf ;
}
return colon_pos + 1 ;
}
# if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
2013-08-23 13:46:38 -04:00
class DIEStack
{
public :
void Push ( DWARFCompileUnit * cu , const DWARFDebugInfoEntry * die )
{
m_dies . push_back ( DIEInfo ( cu , die ) ) ;
}
void LogDIEs ( Log * log , SymbolFileDWARF * dwarf )
{
StreamString log_strm ;
const size_t n = m_dies . size ( ) ;
log_strm . Printf ( " DIEStack[% " PRIu64 " ]: \n " , ( uint64_t ) n ) ;
for ( size_t i = 0 ; i < n ; i + + )
{
DWARFCompileUnit * cu = m_dies [ i ] . cu ;
const DWARFDebugInfoEntry * die = m_dies [ i ] . die ;
std : : string qualified_name ;
die - > GetQualifiedName ( dwarf , cu , qualified_name ) ;
log_strm . Printf ( " [% " PRIu64 " ] 0x%8.8x: %s name='%s' \n " ,
( uint64_t ) i ,
die - > GetOffset ( ) ,
DW_TAG_value_to_name ( die - > Tag ( ) ) ,
qualified_name . c_str ( ) ) ;
}
log - > PutCString ( log_strm . GetData ( ) ) ;
}
void Pop ( )
{
m_dies . pop_back ( ) ;
}
class ScopedPopper
{
public :
ScopedPopper ( DIEStack & die_stack ) :
m_die_stack ( die_stack ) ,
m_valid ( false )
{
}
void
Push ( DWARFCompileUnit * cu , const DWARFDebugInfoEntry * die )
{
m_valid = true ;
m_die_stack . Push ( cu , die ) ;
}
~ ScopedPopper ( )
{
if ( m_valid )
m_die_stack . Pop ( ) ;
}
protected :
DIEStack & m_die_stack ;
bool m_valid ;
} ;
protected :
struct DIEInfo {
DIEInfo ( DWARFCompileUnit * c , const DWARFDebugInfoEntry * d ) :
cu ( c ) ,
die ( d )
{
}
DWARFCompileUnit * cu ;
const DWARFDebugInfoEntry * die ;
} ;
typedef std : : vector < DIEInfo > Stack ;
Stack m_dies ;
} ;
# endif
void
SymbolFileDWARF : : Initialize ( )
{
LogChannelDWARF : : Initialize ( ) ;
PluginManager : : RegisterPlugin ( GetPluginNameStatic ( ) ,
GetPluginDescriptionStatic ( ) ,
CreateInstance ) ;
}
void
SymbolFileDWARF : : Terminate ( )
{
PluginManager : : UnregisterPlugin ( CreateInstance ) ;
LogChannelDWARF : : Initialize ( ) ;
}
lldb_private : : ConstString
SymbolFileDWARF : : GetPluginNameStatic ( )
{
static ConstString g_name ( " dwarf " ) ;
return g_name ;
}
const char *
SymbolFileDWARF : : GetPluginDescriptionStatic ( )
{
return " DWARF and DWARF3 debug symbol file reader. " ;
}
SymbolFile *
SymbolFileDWARF : : CreateInstance ( ObjectFile * obj_file )
{
return new SymbolFileDWARF ( obj_file ) ;
}
TypeList *
SymbolFileDWARF : : GetTypeList ( )
{
if ( GetDebugMapSymfile ( ) )
return m_debug_map_symfile - > GetTypeList ( ) ;
return m_obj_file - > GetModule ( ) - > GetTypeList ( ) ;
}
void
SymbolFileDWARF : : GetTypes ( DWARFCompileUnit * cu ,
const DWARFDebugInfoEntry * die ,
dw_offset_t min_die_offset ,
dw_offset_t max_die_offset ,
uint32_t type_mask ,
TypeSet & type_set )
{
if ( cu )
{
if ( die )
{
const dw_offset_t die_offset = die - > GetOffset ( ) ;
if ( die_offset > = max_die_offset )
return ;
if ( die_offset > = min_die_offset )
{
const dw_tag_t tag = die - > Tag ( ) ;
bool add_type = false ;
switch ( tag )
{
case DW_TAG_array_type : add_type = ( type_mask & eTypeClassArray ) ! = 0 ; break ;
case DW_TAG_unspecified_type :
case DW_TAG_base_type : add_type = ( type_mask & eTypeClassBuiltin ) ! = 0 ; break ;
case DW_TAG_class_type : add_type = ( type_mask & eTypeClassClass ) ! = 0 ; break ;
case DW_TAG_structure_type : add_type = ( type_mask & eTypeClassStruct ) ! = 0 ; break ;
case DW_TAG_union_type : add_type = ( type_mask & eTypeClassUnion ) ! = 0 ; break ;
case DW_TAG_enumeration_type : add_type = ( type_mask & eTypeClassEnumeration ) ! = 0 ; break ;
case DW_TAG_subroutine_type :
case DW_TAG_subprogram :
case DW_TAG_inlined_subroutine : add_type = ( type_mask & eTypeClassFunction ) ! = 0 ; break ;
case DW_TAG_pointer_type : add_type = ( type_mask & eTypeClassPointer ) ! = 0 ; break ;
case DW_TAG_rvalue_reference_type :
case DW_TAG_reference_type : add_type = ( type_mask & eTypeClassReference ) ! = 0 ; break ;
case DW_TAG_typedef : add_type = ( type_mask & eTypeClassTypedef ) ! = 0 ; break ;
case DW_TAG_ptr_to_member_type : add_type = ( type_mask & eTypeClassMemberPointer ) ! = 0 ; break ;
}
if ( add_type )
{
const bool assert_not_being_parsed = true ;
Type * type = ResolveTypeUID ( cu , die , assert_not_being_parsed ) ;
if ( type )
{
if ( type_set . find ( type ) = = type_set . end ( ) )
type_set . insert ( type ) ;
}
}
}
for ( const DWARFDebugInfoEntry * child_die = die - > GetFirstChild ( ) ;
child_die ! = NULL ;
child_die = child_die - > GetSibling ( ) )
{
GetTypes ( cu , child_die , min_die_offset , max_die_offset , type_mask , type_set ) ;
}
}
}
}
size_t
SymbolFileDWARF : : GetTypes ( SymbolContextScope * sc_scope ,
uint32_t type_mask ,
TypeList & type_list )
{
TypeSet type_set ;
CompileUnit * comp_unit = NULL ;
DWARFCompileUnit * dwarf_cu = NULL ;
if ( sc_scope )
comp_unit = sc_scope - > CalculateSymbolContextCompileUnit ( ) ;
if ( comp_unit )
{
dwarf_cu = GetDWARFCompileUnit ( comp_unit ) ;
if ( dwarf_cu = = 0 )
return 0 ;
GetTypes ( dwarf_cu ,
dwarf_cu - > DIE ( ) ,
dwarf_cu - > GetOffset ( ) ,
dwarf_cu - > GetNextCompileUnitOffset ( ) ,
type_mask ,
type_set ) ;
}
else
{
DWARFDebugInfo * info = DebugInfo ( ) ;
if ( info )
{
const size_t num_cus = info - > GetNumCompileUnits ( ) ;
for ( size_t cu_idx = 0 ; cu_idx < num_cus ; + + cu_idx )
{
dwarf_cu = info - > GetCompileUnitAtIndex ( cu_idx ) ;
if ( dwarf_cu )
{
GetTypes ( dwarf_cu ,
dwarf_cu - > DIE ( ) ,
0 ,
UINT32_MAX ,
type_mask ,
type_set ) ;
}
}
}
}
// if (m_using_apple_tables)
// {
// DWARFMappedHash::MemoryTable *apple_types = m_apple_types_ap.get();
// if (apple_types)
// {
// apple_types->ForEach([this, &type_set, apple_types, type_mask](const DWARFMappedHash::DIEInfoArray &die_info_array) -> bool {
//
// for (auto die_info: die_info_array)
// {
// bool add_type = TagMatchesTypeMask (type_mask, 0);
// if (!add_type)
// {
// dw_tag_t tag = die_info.tag;
// if (tag == 0)
// {
// const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtr(die_info.offset, NULL);
// tag = die->Tag();
// }
// add_type = TagMatchesTypeMask (type_mask, tag);
// }
// if (add_type)
// {
// Type *type = ResolveTypeUID(die_info.offset);
//
// if (type_set.find(type) == type_set.end())
// type_set.insert(type);
// }
// }
// return true; // Keep iterating
// });
// }
// }
// else
// {
// if (!m_indexed)
// Index ();
//
// m_type_index.ForEach([this, &type_set, type_mask](const char *name, uint32_t die_offset) -> bool {
//
// bool add_type = TagMatchesTypeMask (type_mask, 0);
//
// if (!add_type)
// {
// const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtr(die_offset, NULL);
// if (die)
// {
// const dw_tag_t tag = die->Tag();
// add_type = TagMatchesTypeMask (type_mask, tag);
// }
// }
//
// if (add_type)
// {
// Type *type = ResolveTypeUID(die_offset);
//
// if (type_set.find(type) == type_set.end())
// type_set.insert(type);
// }
// return true; // Keep iterating
// });
// }
std : : set < ClangASTType > clang_type_set ;
size_t num_types_added = 0 ;
for ( Type * type : type_set )
{
ClangASTType clang_type = type - > GetClangForwardType ( ) ;
if ( clang_type_set . find ( clang_type ) = = clang_type_set . end ( ) )
{
clang_type_set . insert ( clang_type ) ;
type_list . Insert ( type - > shared_from_this ( ) ) ;
+ + num_types_added ;
}
}
return num_types_added ;
}
//----------------------------------------------------------------------
// Gets the first parent that is a lexical block, function or inlined
// subroutine, or compile unit.
//----------------------------------------------------------------------
static const DWARFDebugInfoEntry *
GetParentSymbolContextDIE ( const DWARFDebugInfoEntry * child_die )
{
const DWARFDebugInfoEntry * die ;
for ( die = child_die - > GetParent ( ) ; die ! = NULL ; die = die - > GetParent ( ) )
{
dw_tag_t tag = die - > Tag ( ) ;
switch ( tag )
{
case DW_TAG_compile_unit :
case DW_TAG_subprogram :
case DW_TAG_inlined_subroutine :
case DW_TAG_lexical_block :
return die ;
}
}
return NULL ;
}
SymbolFileDWARF : : SymbolFileDWARF ( ObjectFile * objfile ) :
SymbolFile ( objfile ) ,
UserID ( 0 ) , // Used by SymbolFileDWARFDebugMap to when this class parses .o files to contain the .o file index/ID
m_debug_map_module_wp ( ) ,
m_debug_map_symfile ( NULL ) ,
m_clang_tu_decl ( NULL ) ,
m_flags ( ) ,
m_data_debug_abbrev ( ) ,
m_data_debug_aranges ( ) ,
m_data_debug_frame ( ) ,
m_data_debug_info ( ) ,
m_data_debug_line ( ) ,
m_data_debug_loc ( ) ,
m_data_debug_ranges ( ) ,
m_data_debug_str ( ) ,
m_data_apple_names ( ) ,
m_data_apple_types ( ) ,
m_data_apple_namespaces ( ) ,
m_abbr ( ) ,
m_info ( ) ,
m_line ( ) ,
m_apple_names_ap ( ) ,
m_apple_types_ap ( ) ,
m_apple_namespaces_ap ( ) ,
m_apple_objc_ap ( ) ,
m_function_basename_index ( ) ,
m_function_fullname_index ( ) ,
m_function_method_index ( ) ,
m_function_selector_index ( ) ,
m_objc_class_selectors_index ( ) ,
m_global_index ( ) ,
m_type_index ( ) ,
m_namespace_index ( ) ,
m_indexed ( false ) ,
m_is_external_ast_source ( false ) ,
m_using_apple_tables ( false ) ,
2015-07-03 12:57:06 -04:00
m_fetched_external_modules ( false ) ,
2013-08-23 13:46:38 -04:00
m_supports_DW_AT_APPLE_objc_complete_type ( eLazyBoolCalculate ) ,
m_ranges ( ) ,
m_unique_ast_type_map ( )
{
}
SymbolFileDWARF : : ~ SymbolFileDWARF ( )
{
if ( m_is_external_ast_source )
{
ModuleSP module_sp ( m_obj_file - > GetModule ( ) ) ;
if ( module_sp )
module_sp - > GetClangASTContext ( ) . RemoveExternalSource ( ) ;
}
}
static const ConstString &
GetDWARFMachOSegmentName ( )
{
static ConstString g_dwarf_section_name ( " __DWARF " ) ;
return g_dwarf_section_name ;
}
UniqueDWARFASTTypeMap &
SymbolFileDWARF : : GetUniqueDWARFASTTypeMap ( )
{
if ( GetDebugMapSymfile ( ) )
return m_debug_map_symfile - > GetUniqueDWARFASTTypeMap ( ) ;
return m_unique_ast_type_map ;
}
ClangASTContext &
SymbolFileDWARF : : GetClangASTContext ( )
{
if ( GetDebugMapSymfile ( ) )
return m_debug_map_symfile - > GetClangASTContext ( ) ;
ClangASTContext & ast = m_obj_file - > GetModule ( ) - > GetClangASTContext ( ) ;
if ( ! m_is_external_ast_source )
{
m_is_external_ast_source = true ;
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 ( SymbolFileDWARF : : CompleteTagDecl ,
SymbolFileDWARF : : CompleteObjCInterfaceDecl ,
SymbolFileDWARF : : FindExternalVisibleDeclsByName ,
SymbolFileDWARF : : LayoutRecordType ,
this ) ) ;
ast . SetExternalSource ( ast_source_ap ) ;
}
return ast ;
}
void
SymbolFileDWARF : : InitializeObject ( )
{
// Install our external AST source callbacks so we can complete Clang types.
ModuleSP module_sp ( m_obj_file - > GetModule ( ) ) ;
if ( module_sp )
{
const SectionList * section_list = module_sp - > GetSectionList ( ) ;
const Section * section = section_list - > FindSectionByName ( GetDWARFMachOSegmentName ( ) ) . get ( ) ;
// Memory map the DWARF mach-o segment so we have everything mmap'ed
// to keep our heap memory usage down.
if ( section )
m_obj_file - > MemoryMapSectionData ( section , m_dwarf_data ) ;
}
get_apple_names_data ( ) ;
if ( m_data_apple_names . GetByteSize ( ) > 0 )
{
m_apple_names_ap . reset ( new DWARFMappedHash : : MemoryTable ( m_data_apple_names , get_debug_str_data ( ) , " .apple_names " ) ) ;
if ( m_apple_names_ap - > IsValid ( ) )
m_using_apple_tables = true ;
else
m_apple_names_ap . reset ( ) ;
}
get_apple_types_data ( ) ;
if ( m_data_apple_types . GetByteSize ( ) > 0 )
{
m_apple_types_ap . reset ( new DWARFMappedHash : : MemoryTable ( m_data_apple_types , get_debug_str_data ( ) , " .apple_types " ) ) ;
if ( m_apple_types_ap - > IsValid ( ) )
m_using_apple_tables = true ;
else
m_apple_types_ap . reset ( ) ;
}
get_apple_namespaces_data ( ) ;
if ( m_data_apple_namespaces . GetByteSize ( ) > 0 )
{
m_apple_namespaces_ap . reset ( new DWARFMappedHash : : MemoryTable ( m_data_apple_namespaces , get_debug_str_data ( ) , " .apple_namespaces " ) ) ;
if ( m_apple_namespaces_ap - > IsValid ( ) )
m_using_apple_tables = true ;
else
m_apple_namespaces_ap . reset ( ) ;
}
get_apple_objc_data ( ) ;
if ( m_data_apple_objc . GetByteSize ( ) > 0 )
{
m_apple_objc_ap . reset ( new DWARFMappedHash : : MemoryTable ( m_data_apple_objc , get_debug_str_data ( ) , " .apple_objc " ) ) ;
if ( m_apple_objc_ap - > IsValid ( ) )
m_using_apple_tables = true ;
else
m_apple_objc_ap . reset ( ) ;
}
}
bool
SymbolFileDWARF : : SupportedVersion ( uint16_t version )
{
return version = = 2 | | version = = 3 | | version = = 4 ;
}
uint32_t
SymbolFileDWARF : : CalculateAbilities ( )
{
uint32_t abilities = 0 ;
if ( m_obj_file ! = NULL )
{
const Section * section = NULL ;
const SectionList * section_list = m_obj_file - > GetSectionList ( ) ;
if ( section_list = = NULL )
return 0 ;
uint64_t debug_abbrev_file_size = 0 ;
uint64_t debug_info_file_size = 0 ;
uint64_t debug_line_file_size = 0 ;
section = section_list - > FindSectionByName ( GetDWARFMachOSegmentName ( ) ) . get ( ) ;
if ( section )
section_list = & section - > GetChildren ( ) ;
section = section_list - > FindSectionByType ( eSectionTypeDWARFDebugInfo , true ) . get ( ) ;
if ( section ! = NULL )
{
debug_info_file_size = section - > GetFileSize ( ) ;
section = section_list - > FindSectionByType ( eSectionTypeDWARFDebugAbbrev , true ) . get ( ) ;
if ( section )
debug_abbrev_file_size = section - > GetFileSize ( ) ;
else
m_flags . Set ( flagsGotDebugAbbrevData ) ;
section = section_list - > FindSectionByType ( eSectionTypeDWARFDebugAranges , true ) . get ( ) ;
if ( ! section )
m_flags . Set ( flagsGotDebugArangesData ) ;
section = section_list - > FindSectionByType ( eSectionTypeDWARFDebugFrame , true ) . get ( ) ;
if ( ! section )
m_flags . Set ( flagsGotDebugFrameData ) ;
section = section_list - > FindSectionByType ( eSectionTypeDWARFDebugLine , true ) . get ( ) ;
if ( section )
debug_line_file_size = section - > GetFileSize ( ) ;
else
m_flags . Set ( flagsGotDebugLineData ) ;
section = section_list - > FindSectionByType ( eSectionTypeDWARFDebugLoc , true ) . get ( ) ;
if ( ! section )
m_flags . Set ( flagsGotDebugLocData ) ;
section = section_list - > FindSectionByType ( eSectionTypeDWARFDebugMacInfo , true ) . get ( ) ;
if ( ! section )
m_flags . Set ( flagsGotDebugMacInfoData ) ;
section = section_list - > FindSectionByType ( eSectionTypeDWARFDebugPubNames , true ) . get ( ) ;
if ( ! section )
m_flags . Set ( flagsGotDebugPubNamesData ) ;
section = section_list - > FindSectionByType ( eSectionTypeDWARFDebugPubTypes , true ) . get ( ) ;
if ( ! section )
m_flags . Set ( flagsGotDebugPubTypesData ) ;
section = section_list - > FindSectionByType ( eSectionTypeDWARFDebugRanges , true ) . get ( ) ;
if ( ! section )
m_flags . Set ( flagsGotDebugRangesData ) ;
section = section_list - > FindSectionByType ( eSectionTypeDWARFDebugStr , true ) . get ( ) ;
if ( ! section )
m_flags . Set ( flagsGotDebugStrData ) ;
}
else
{
const char * symfile_dir_cstr = m_obj_file - > GetFileSpec ( ) . GetDirectory ( ) . GetCString ( ) ;
if ( symfile_dir_cstr )
{
if ( strcasestr ( symfile_dir_cstr , " .dsym " ) )
{
if ( m_obj_file - > GetType ( ) = = ObjectFile : : eTypeDebugInfo )
{
// We have a dSYM file that didn't have a any debug info.
// If the string table has a size of 1, then it was made from
// an executable with no debug info, or from an executable that
// was stripped.
section = section_list - > FindSectionByType ( eSectionTypeDWARFDebugStr , true ) . get ( ) ;
if ( section & & section - > GetFileSize ( ) = = 1 )
{
m_obj_file - > GetModule ( ) - > ReportWarning ( " empty dSYM file detected, dSYM was created with an executable with no debug info. " ) ;
}
}
}
}
}
if ( debug_abbrev_file_size > 0 & & debug_info_file_size > 0 )
abilities | = CompileUnits | Functions | Blocks | GlobalVariables | LocalVariables | VariableTypes ;
if ( debug_line_file_size > 0 )
abilities | = LineTables ;
}
return abilities ;
}
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor &
SymbolFileDWARF : : GetCachedSectionData ( uint32_t got_flag , SectionType sect_type , DWARFDataExtractor & data )
2013-08-23 13:46:38 -04:00
{
if ( m_flags . IsClear ( got_flag ) )
{
ModuleSP module_sp ( m_obj_file - > GetModule ( ) ) ;
m_flags . Set ( got_flag ) ;
const SectionList * section_list = module_sp - > GetSectionList ( ) ;
if ( section_list )
{
SectionSP section_sp ( section_list - > FindSectionByType ( sect_type , true ) ) ;
if ( section_sp )
{
// See if we memory mapped the DWARF segment?
if ( m_dwarf_data . GetByteSize ( ) )
{
data . SetData ( m_dwarf_data , section_sp - > GetOffset ( ) , section_sp - > GetFileSize ( ) ) ;
}
else
{
if ( m_obj_file - > ReadSectionData ( section_sp . get ( ) , data ) = = 0 )
data . Clear ( ) ;
}
}
}
}
return data ;
}
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor &
2013-08-23 13:46:38 -04:00
SymbolFileDWARF : : get_debug_abbrev_data ( )
{
return GetCachedSectionData ( flagsGotDebugAbbrevData , eSectionTypeDWARFDebugAbbrev , m_data_debug_abbrev ) ;
}
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor &
2013-08-23 13:46:38 -04:00
SymbolFileDWARF : : get_debug_aranges_data ( )
{
return GetCachedSectionData ( flagsGotDebugArangesData , eSectionTypeDWARFDebugAranges , m_data_debug_aranges ) ;
}
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor &
2013-08-23 13:46:38 -04:00
SymbolFileDWARF : : get_debug_frame_data ( )
{
return GetCachedSectionData ( flagsGotDebugFrameData , eSectionTypeDWARFDebugFrame , m_data_debug_frame ) ;
}
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor &
2013-08-23 13:46:38 -04:00
SymbolFileDWARF : : get_debug_info_data ( )
{
return GetCachedSectionData ( flagsGotDebugInfoData , eSectionTypeDWARFDebugInfo , m_data_debug_info ) ;
}
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor &
2013-08-23 13:46:38 -04:00
SymbolFileDWARF : : get_debug_line_data ( )
{
return GetCachedSectionData ( flagsGotDebugLineData , eSectionTypeDWARFDebugLine , m_data_debug_line ) ;
}
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor &
2013-08-23 13:46:38 -04:00
SymbolFileDWARF : : get_debug_loc_data ( )
{
return GetCachedSectionData ( flagsGotDebugLocData , eSectionTypeDWARFDebugLoc , m_data_debug_loc ) ;
}
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor &
2013-08-23 13:46:38 -04:00
SymbolFileDWARF : : get_debug_ranges_data ( )
{
return GetCachedSectionData ( flagsGotDebugRangesData , eSectionTypeDWARFDebugRanges , m_data_debug_ranges ) ;
}
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor &
2013-08-23 13:46:38 -04:00
SymbolFileDWARF : : get_debug_str_data ( )
{
return GetCachedSectionData ( flagsGotDebugStrData , eSectionTypeDWARFDebugStr , m_data_debug_str ) ;
}
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor &
2013-08-23 13:46:38 -04:00
SymbolFileDWARF : : get_apple_names_data ( )
{
return GetCachedSectionData ( flagsGotAppleNamesData , eSectionTypeDWARFAppleNames , m_data_apple_names ) ;
}
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor &
2013-08-23 13:46:38 -04:00
SymbolFileDWARF : : get_apple_types_data ( )
{
return GetCachedSectionData ( flagsGotAppleTypesData , eSectionTypeDWARFAppleTypes , m_data_apple_types ) ;
}
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor &
2013-08-23 13:46:38 -04:00
SymbolFileDWARF : : get_apple_namespaces_data ( )
{
return GetCachedSectionData ( flagsGotAppleNamespacesData , eSectionTypeDWARFAppleNamespaces , m_data_apple_namespaces ) ;
}
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor &
2013-08-23 13:46:38 -04:00
SymbolFileDWARF : : get_apple_objc_data ( )
{
return GetCachedSectionData ( flagsGotAppleObjCData , eSectionTypeDWARFAppleObjC , m_data_apple_objc ) ;
}
DWARFDebugAbbrev *
SymbolFileDWARF : : DebugAbbrev ( )
{
if ( m_abbr . get ( ) = = NULL )
{
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor & debug_abbrev_data = get_debug_abbrev_data ( ) ;
2013-08-23 13:46:38 -04:00
if ( debug_abbrev_data . GetByteSize ( ) > 0 )
{
m_abbr . reset ( new DWARFDebugAbbrev ( ) ) ;
if ( m_abbr . get ( ) )
m_abbr - > Parse ( debug_abbrev_data ) ;
}
}
return m_abbr . get ( ) ;
}
const DWARFDebugAbbrev *
SymbolFileDWARF : : DebugAbbrev ( ) const
{
return m_abbr . get ( ) ;
}
DWARFDebugInfo *
SymbolFileDWARF : : DebugInfo ( )
{
if ( m_info . get ( ) = = NULL )
{
2014-11-25 16:00:58 -05:00
Timer scoped_timer ( __PRETTY_FUNCTION__ , " %s this = %p " ,
__PRETTY_FUNCTION__ , static_cast < void * > ( this ) ) ;
2013-08-23 13:46:38 -04:00
if ( get_debug_info_data ( ) . GetByteSize ( ) > 0 )
{
m_info . reset ( new DWARFDebugInfo ( ) ) ;
if ( m_info . get ( ) )
{
m_info - > SetDwarfData ( this ) ;
}
}
}
return m_info . get ( ) ;
}
const DWARFDebugInfo *
SymbolFileDWARF : : DebugInfo ( ) const
{
return m_info . get ( ) ;
}
DWARFCompileUnit *
SymbolFileDWARF : : GetDWARFCompileUnit ( lldb_private : : CompileUnit * comp_unit )
{
DWARFDebugInfo * info = DebugInfo ( ) ;
if ( info )
{
if ( GetDebugMapSymfile ( ) )
{
// The debug map symbol file made the compile units for this DWARF
// file which is .o file with DWARF in it, and we should have
// only 1 compile unit which is at offset zero in the DWARF.
// TODO: modify to support LTO .o files where each .o file might
// have multiple DW_TAG_compile_unit tags.
2015-02-08 20:44:09 -05:00
DWARFCompileUnit * dwarf_cu = info - > GetCompileUnit ( 0 ) . get ( ) ;
if ( dwarf_cu & & dwarf_cu - > GetUserData ( ) = = NULL )
dwarf_cu - > SetUserData ( comp_unit ) ;
return dwarf_cu ;
2013-08-23 13:46:38 -04:00
}
else
{
// Just a normal DWARF file whose user ID for the compile unit is
// the DWARF offset itself
2015-02-08 20:44:09 -05:00
DWARFCompileUnit * dwarf_cu = info - > GetCompileUnit ( ( dw_offset_t ) comp_unit - > GetID ( ) ) . get ( ) ;
if ( dwarf_cu & & dwarf_cu - > GetUserData ( ) = = NULL )
dwarf_cu - > SetUserData ( comp_unit ) ;
return dwarf_cu ;
2013-08-23 13:46:38 -04:00
}
}
return NULL ;
}
DWARFDebugRanges *
SymbolFileDWARF : : DebugRanges ( )
{
if ( m_ranges . get ( ) = = NULL )
{
2014-11-25 16:00:58 -05:00
Timer scoped_timer ( __PRETTY_FUNCTION__ , " %s this = %p " ,
__PRETTY_FUNCTION__ , static_cast < void * > ( this ) ) ;
2013-08-23 13:46:38 -04:00
if ( get_debug_ranges_data ( ) . GetByteSize ( ) > 0 )
{
m_ranges . reset ( new DWARFDebugRanges ( ) ) ;
if ( m_ranges . get ( ) )
m_ranges - > Extract ( this ) ;
}
}
return m_ranges . get ( ) ;
}
const DWARFDebugRanges *
SymbolFileDWARF : : DebugRanges ( ) const
{
return m_ranges . get ( ) ;
}
lldb : : CompUnitSP
SymbolFileDWARF : : ParseCompileUnit ( DWARFCompileUnit * dwarf_cu , uint32_t cu_idx )
{
CompUnitSP cu_sp ;
if ( dwarf_cu )
{
CompileUnit * comp_unit = ( CompileUnit * ) dwarf_cu - > GetUserData ( ) ;
if ( comp_unit )
{
// We already parsed this compile unit, had out a shared pointer to it
cu_sp = comp_unit - > shared_from_this ( ) ;
}
else
{
if ( GetDebugMapSymfile ( ) )
{
// Let the debug map create the compile unit
cu_sp = m_debug_map_symfile - > GetCompileUnit ( this ) ;
dwarf_cu - > SetUserData ( cu_sp . get ( ) ) ;
}
else
{
ModuleSP module_sp ( m_obj_file - > GetModule ( ) ) ;
if ( module_sp )
{
const DWARFDebugInfoEntry * cu_die = dwarf_cu - > GetCompileUnitDIEOnly ( ) ;
if ( cu_die )
{
2015-07-03 12:57:06 -04:00
FileSpec cu_file_spec { cu_die - > GetName ( this , dwarf_cu ) , false } ;
if ( cu_file_spec )
2013-08-23 13:46:38 -04:00
{
2015-07-03 12:57:06 -04:00
// If we have a full path to the compile unit, we don't need to resolve
// the file. This can be expensive e.g. when the source files are NFS mounted.
if ( cu_file_spec . IsRelative ( ) )
2013-08-23 13:46:38 -04:00
{
2014-11-25 16:00:58 -05:00
// DWARF2/3 suggests the form hostname:pathname for compilation directory.
// Remove the host part if present.
2015-07-03 12:57:06 -04:00
const char * cu_comp_dir { cu_die - > GetAttributeValueAsString ( this , dwarf_cu , DW_AT_comp_dir , nullptr ) } ;
cu_file_spec . PrependPathComponent ( removeHostnameFromPathname ( cu_comp_dir ) ) ;
2013-08-23 13:46:38 -04:00
}
2015-07-03 12:57:06 -04:00
std : : string remapped_file ;
if ( module_sp - > RemapSourceFile ( cu_file_spec . GetCString ( ) , remapped_file ) )
cu_file_spec . SetFile ( remapped_file , false ) ;
2015-09-06 10:32:30 -04:00
}
2015-07-03 12:57:06 -04:00
2015-09-06 10:32:30 -04:00
LanguageType cu_language = DWARFCompileUnit : : LanguageTypeFromDWARF ( cu_die - > GetAttributeValueAsUnsigned ( this , dwarf_cu , DW_AT_language , 0 ) ) ;
2015-07-03 12:57:06 -04:00
2015-09-06 10:32:30 -04:00
cu_sp . reset ( new CompileUnit ( module_sp ,
dwarf_cu ,
cu_file_spec ,
MakeUserID ( dwarf_cu - > GetOffset ( ) ) ,
cu_language ) ) ;
if ( cu_sp )
{
// If we just created a compile unit with an invalid file spec, try and get the
// first entry in the supports files from the line table as that should be the
// compile unit.
if ( ! cu_file_spec )
2013-08-23 13:46:38 -04:00
{
2015-09-06 10:32:30 -04:00
cu_file_spec = cu_sp - > GetSupportFiles ( ) . GetFileSpecAtIndex ( 1 ) ;
if ( cu_file_spec )
{
( FileSpec & ) ( * cu_sp ) = cu_file_spec ;
// Also fix the invalid file spec which was copied from the compile unit.
cu_sp - > GetSupportFiles ( ) . Replace ( 0 , cu_file_spec ) ;
}
2013-08-23 13:46:38 -04:00
}
2015-09-06 10:32:30 -04:00
dwarf_cu - > SetUserData ( cu_sp . get ( ) ) ;
// Figure out the compile unit index if we weren't given one
if ( cu_idx = = UINT32_MAX )
DebugInfo ( ) - > GetCompileUnit ( dwarf_cu - > GetOffset ( ) , & cu_idx ) ;
m_obj_file - > GetModule ( ) - > GetSymbolVendor ( ) - > SetCompileUnitAtIndex ( cu_idx , cu_sp ) ;
2013-08-23 13:46:38 -04:00
}
}
}
}
}
}
return cu_sp ;
}
uint32_t
SymbolFileDWARF : : GetNumCompileUnits ( )
{
DWARFDebugInfo * info = DebugInfo ( ) ;
if ( info )
return info - > GetNumCompileUnits ( ) ;
return 0 ;
}
CompUnitSP
SymbolFileDWARF : : ParseCompileUnitAtIndex ( uint32_t cu_idx )
{
CompUnitSP cu_sp ;
DWARFDebugInfo * info = DebugInfo ( ) ;
if ( info )
{
DWARFCompileUnit * dwarf_cu = info - > GetCompileUnitAtIndex ( cu_idx ) ;
if ( dwarf_cu )
cu_sp = ParseCompileUnit ( dwarf_cu , cu_idx ) ;
}
return cu_sp ;
}
Function *
SymbolFileDWARF : : ParseCompileUnitFunction ( const SymbolContext & sc , DWARFCompileUnit * dwarf_cu , const DWARFDebugInfoEntry * die )
{
DWARFDebugRanges : : RangeList func_ranges ;
const char * name = NULL ;
const char * mangled = NULL ;
int decl_file = 0 ;
int decl_line = 0 ;
int decl_column = 0 ;
int call_file = 0 ;
int call_line = 0 ;
int call_column = 0 ;
DWARFExpression frame_base ;
assert ( die - > Tag ( ) = = DW_TAG_subprogram ) ;
if ( die - > Tag ( ) ! = DW_TAG_subprogram )
return NULL ;
if ( die - > GetDIENamesAndRanges ( this ,
dwarf_cu ,
name ,
mangled ,
func_ranges ,
decl_file ,
decl_line ,
decl_column ,
call_file ,
call_line ,
call_column ,
& frame_base ) )
{
// Union of all ranges in the function DIE (if the function is discontiguous)
AddressRange func_range ;
lldb : : addr_t lowest_func_addr = func_ranges . GetMinRangeBase ( 0 ) ;
lldb : : addr_t highest_func_addr = func_ranges . GetMaxRangeEnd ( 0 ) ;
if ( lowest_func_addr ! = LLDB_INVALID_ADDRESS & & lowest_func_addr < = highest_func_addr )
{
ModuleSP module_sp ( m_obj_file - > GetModule ( ) ) ;
func_range . GetBaseAddress ( ) . ResolveAddressUsingFileSections ( lowest_func_addr , module_sp - > GetSectionList ( ) ) ;
if ( func_range . GetBaseAddress ( ) . IsValid ( ) )
func_range . SetByteSize ( highest_func_addr - lowest_func_addr ) ;
}
if ( func_range . GetBaseAddress ( ) . IsValid ( ) )
{
Mangled func_name ;
if ( mangled )
func_name . SetValue ( ConstString ( mangled ) , true ) ;
2015-07-03 12:57:06 -04:00
else if ( die - > GetParent ( ) - > Tag ( ) = = DW_TAG_compile_unit & &
LanguageRuntime : : LanguageIsCPlusPlus ( dwarf_cu - > GetLanguageType ( ) ) & &
name & & strcmp ( name , " main " ) ! = 0 )
{
// If the mangled name is not present in the DWARF, generate the demangled name
// using the decl context. We skip if the function is "main" as its name is
// never mangled.
bool is_static = false ;
bool is_variadic = false ;
unsigned type_quals = 0 ;
std : : vector < ClangASTType > param_types ;
std : : vector < clang : : ParmVarDecl * > param_decls ;
const DWARFDebugInfoEntry * decl_ctx_die = NULL ;
DWARFDeclContext decl_ctx ;
StreamString sstr ;
die - > GetDWARFDeclContext ( this , dwarf_cu , decl_ctx ) ;
sstr < < decl_ctx . GetQualifiedName ( ) ;
clang : : DeclContext * containing_decl_ctx = GetClangDeclContextContainingDIE ( dwarf_cu ,
die ,
& decl_ctx_die ) ;
ParseChildParameters ( sc ,
containing_decl_ctx ,
dwarf_cu ,
die ,
true ,
is_static ,
is_variadic ,
param_types ,
param_decls ,
type_quals ) ;
sstr < < " ( " ;
for ( size_t i = 0 ; i < param_types . size ( ) ; i + + )
{
if ( i > 0 )
sstr < < " , " ;
sstr < < param_types [ i ] . GetTypeName ( ) ;
}
if ( is_variadic )
sstr < < " , ... " ;
sstr < < " ) " ;
if ( type_quals & clang : : Qualifiers : : Const )
sstr < < " const " ;
func_name . SetValue ( ConstString ( sstr . GetData ( ) ) , false ) ;
}
else
2013-08-23 13:46:38 -04:00
func_name . SetValue ( ConstString ( name ) , false ) ;
FunctionSP func_sp ;
std : : unique_ptr < Declaration > decl_ap ;
if ( decl_file ! = 0 | | decl_line ! = 0 | | decl_column ! = 0 )
decl_ap . reset ( new Declaration ( sc . comp_unit - > GetSupportFiles ( ) . GetFileSpecAtIndex ( decl_file ) ,
decl_line ,
decl_column ) ) ;
// Supply the type _only_ if it has already been parsed
Type * func_type = m_die_to_type . lookup ( die ) ;
assert ( func_type = = NULL | | func_type ! = DIE_IS_BEING_PARSED ) ;
if ( FixupAddress ( func_range . GetBaseAddress ( ) ) )
{
const user_id_t func_user_id = MakeUserID ( die - > GetOffset ( ) ) ;
func_sp . reset ( new Function ( sc . comp_unit ,
MakeUserID ( func_user_id ) , // UserID is the DIE offset
MakeUserID ( func_user_id ) ,
func_name ,
func_type ,
func_range ) ) ; // first address range
if ( func_sp . get ( ) ! = NULL )
{
if ( frame_base . IsValid ( ) )
func_sp - > GetFrameBaseExpression ( ) = frame_base ;
sc . comp_unit - > AddFunction ( func_sp ) ;
return func_sp . get ( ) ;
}
}
}
}
return NULL ;
}
bool
SymbolFileDWARF : : FixupAddress ( Address & addr )
{
SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile ( ) ;
if ( debug_map_symfile )
{
return debug_map_symfile - > LinkOSOAddress ( addr ) ;
}
// This is a normal DWARF file, no address fixups need to happen
return true ;
}
lldb : : LanguageType
SymbolFileDWARF : : ParseCompileUnitLanguage ( const SymbolContext & sc )
{
assert ( sc . comp_unit ) ;
DWARFCompileUnit * dwarf_cu = GetDWARFCompileUnit ( sc . comp_unit ) ;
if ( dwarf_cu )
{
const DWARFDebugInfoEntry * die = dwarf_cu - > GetCompileUnitDIEOnly ( ) ;
if ( die )
2015-07-03 12:57:06 -04:00
return DWARFCompileUnit : : LanguageTypeFromDWARF ( die - > GetAttributeValueAsUnsigned ( this , dwarf_cu , DW_AT_language , 0 ) ) ;
2013-08-23 13:46:38 -04:00
}
return eLanguageTypeUnknown ;
}
size_t
SymbolFileDWARF : : ParseCompileUnitFunctions ( const SymbolContext & sc )
{
assert ( sc . comp_unit ) ;
size_t functions_added = 0 ;
DWARFCompileUnit * dwarf_cu = GetDWARFCompileUnit ( sc . comp_unit ) ;
if ( dwarf_cu )
{
DWARFDIECollection function_dies ;
const size_t num_functions = dwarf_cu - > AppendDIEsWithTag ( DW_TAG_subprogram , function_dies ) ;
size_t func_idx ;
for ( func_idx = 0 ; func_idx < num_functions ; + + func_idx )
{
const DWARFDebugInfoEntry * die = function_dies . GetDIEPtrAtIndex ( func_idx ) ;
if ( sc . comp_unit - > FindFunctionByUID ( MakeUserID ( die - > GetOffset ( ) ) ) . get ( ) = = NULL )
{
if ( ParseCompileUnitFunction ( sc , dwarf_cu , die ) )
+ + functions_added ;
}
}
//FixupTypes();
}
return functions_added ;
}
bool
SymbolFileDWARF : : ParseCompileUnitSupportFiles ( const SymbolContext & sc , FileSpecList & support_files )
{
assert ( sc . comp_unit ) ;
DWARFCompileUnit * dwarf_cu = GetDWARFCompileUnit ( sc . comp_unit ) ;
if ( dwarf_cu )
{
const DWARFDebugInfoEntry * cu_die = dwarf_cu - > GetCompileUnitDIEOnly ( ) ;
if ( cu_die )
{
const char * cu_comp_dir = cu_die - > GetAttributeValueAsString ( this , dwarf_cu , DW_AT_comp_dir , NULL ) ;
2014-11-25 16:00:58 -05:00
// DWARF2/3 suggests the form hostname:pathname for compilation directory.
// Remove the host part if present.
cu_comp_dir = removeHostnameFromPathname ( cu_comp_dir ) ;
2013-08-23 13:46:38 -04:00
dw_offset_t stmt_list = cu_die - > GetAttributeValueAsUnsigned ( this , dwarf_cu , DW_AT_stmt_list , DW_INVALID_OFFSET ) ;
// All file indexes in DWARF are one based and a file of index zero is
// supposed to be the compile unit itself.
support_files . Append ( * sc . comp_unit ) ;
return DWARFDebugLine : : ParseSupportFiles ( sc . comp_unit - > GetModule ( ) , get_debug_line_data ( ) , cu_comp_dir , stmt_list , support_files ) ;
}
}
return false ;
}
2015-07-03 12:57:06 -04:00
bool
SymbolFileDWARF : : ParseImportedModules ( const lldb_private : : SymbolContext & sc , std : : vector < lldb_private : : ConstString > & imported_modules )
{
assert ( sc . comp_unit ) ;
DWARFCompileUnit * dwarf_cu = GetDWARFCompileUnit ( sc . comp_unit ) ;
if ( dwarf_cu )
{
if ( ClangModulesDeclVendor : : LanguageSupportsClangModules ( sc . comp_unit - > GetLanguage ( ) ) )
{
UpdateExternalModuleListIfNeeded ( ) ;
for ( const std : : pair < uint64_t , const ClangModuleInfo > & external_type_module : m_external_type_modules )
{
imported_modules . push_back ( external_type_module . second . m_name ) ;
}
}
}
return false ;
}
2013-08-23 13:46:38 -04:00
struct ParseDWARFLineTableCallbackInfo
{
LineTable * line_table ;
std : : unique_ptr < LineSequence > sequence_ap ;
} ;
//----------------------------------------------------------------------
// ParseStatementTableCallback
//----------------------------------------------------------------------
static void
ParseDWARFLineTableCallback ( dw_offset_t offset , const DWARFDebugLine : : State & state , void * userData )
{
if ( state . row = = DWARFDebugLine : : State : : StartParsingLineTable )
{
// Just started parsing the line table
}
else if ( state . row = = DWARFDebugLine : : State : : DoneParsingLineTable )
{
// Done parsing line table, nothing to do for the cleanup
}
else
{
ParseDWARFLineTableCallbackInfo * info = ( ParseDWARFLineTableCallbackInfo * ) userData ;
LineTable * line_table = info - > line_table ;
// If this is our first time here, we need to create a
// sequence container.
if ( ! info - > sequence_ap . get ( ) )
{
info - > sequence_ap . reset ( line_table - > CreateLineSequenceContainer ( ) ) ;
assert ( info - > sequence_ap . get ( ) ) ;
}
line_table - > AppendLineEntryToSequence ( info - > sequence_ap . get ( ) ,
state . address ,
state . line ,
state . column ,
state . file ,
state . is_stmt ,
state . basic_block ,
state . prologue_end ,
state . epilogue_begin ,
state . end_sequence ) ;
if ( state . end_sequence )
{
// First, put the current sequence into the line table.
line_table - > InsertSequence ( info - > sequence_ap . get ( ) ) ;
// Then, empty it to prepare for the next sequence.
info - > sequence_ap - > Clear ( ) ;
}
}
}
bool
SymbolFileDWARF : : ParseCompileUnitLineTable ( const SymbolContext & sc )
{
assert ( sc . comp_unit ) ;
if ( sc . comp_unit - > GetLineTable ( ) ! = NULL )
return true ;
DWARFCompileUnit * dwarf_cu = GetDWARFCompileUnit ( sc . comp_unit ) ;
if ( dwarf_cu )
{
const DWARFDebugInfoEntry * dwarf_cu_die = dwarf_cu - > GetCompileUnitDIEOnly ( ) ;
if ( dwarf_cu_die )
{
const dw_offset_t cu_line_offset = dwarf_cu_die - > GetAttributeValueAsUnsigned ( this , dwarf_cu , DW_AT_stmt_list , DW_INVALID_OFFSET ) ;
if ( cu_line_offset ! = DW_INVALID_OFFSET )
{
std : : unique_ptr < LineTable > line_table_ap ( new LineTable ( sc . comp_unit ) ) ;
if ( line_table_ap . get ( ) )
{
ParseDWARFLineTableCallbackInfo info ;
info . line_table = line_table_ap . get ( ) ;
lldb : : offset_t offset = cu_line_offset ;
DWARFDebugLine : : ParseStatementTable ( get_debug_line_data ( ) , & offset , ParseDWARFLineTableCallback , & info ) ;
if ( m_debug_map_symfile )
{
// We have an object file that has a line table with addresses
// that are not linked. We need to link the line table and convert
// the addresses that are relative to the .o file into addresses
// for the main executable.
sc . comp_unit - > SetLineTable ( m_debug_map_symfile - > LinkOSOLineTable ( this , line_table_ap . get ( ) ) ) ;
}
else
{
sc . comp_unit - > SetLineTable ( line_table_ap . release ( ) ) ;
return true ;
}
}
}
}
}
return false ;
}
size_t
SymbolFileDWARF : : ParseFunctionBlocks
(
const SymbolContext & sc ,
Block * parent_block ,
DWARFCompileUnit * dwarf_cu ,
const DWARFDebugInfoEntry * die ,
addr_t subprogram_low_pc ,
uint32_t depth
)
{
size_t blocks_added = 0 ;
while ( die ! = NULL )
{
dw_tag_t tag = die - > Tag ( ) ;
switch ( tag )
{
case DW_TAG_inlined_subroutine :
case DW_TAG_subprogram :
case DW_TAG_lexical_block :
{
Block * block = NULL ;
if ( tag = = DW_TAG_subprogram )
{
// Skip any DW_TAG_subprogram DIEs that are inside
// of a normal or inlined functions. These will be
// parsed on their own as separate entities.
if ( depth > 0 )
break ;
block = parent_block ;
}
else
{
BlockSP block_sp ( new Block ( MakeUserID ( die - > GetOffset ( ) ) ) ) ;
parent_block - > AddChild ( block_sp ) ;
block = block_sp . get ( ) ;
}
DWARFDebugRanges : : RangeList ranges ;
const char * name = NULL ;
const char * mangled_name = NULL ;
int decl_file = 0 ;
int decl_line = 0 ;
int decl_column = 0 ;
int call_file = 0 ;
int call_line = 0 ;
int call_column = 0 ;
if ( die - > GetDIENamesAndRanges ( this ,
dwarf_cu ,
name ,
mangled_name ,
ranges ,
decl_file , decl_line , decl_column ,
call_file , call_line , call_column ) )
{
if ( tag = = DW_TAG_subprogram )
{
assert ( subprogram_low_pc = = LLDB_INVALID_ADDRESS ) ;
subprogram_low_pc = ranges . GetMinRangeBase ( 0 ) ;
}
else if ( tag = = DW_TAG_inlined_subroutine )
{
// We get called here for inlined subroutines in two ways.
// The first time is when we are making the Function object
// for this inlined concrete instance. Since we're creating a top level block at
// here, the subprogram_low_pc will be LLDB_INVALID_ADDRESS. So we need to
// adjust the containing address.
// The second time is when we are parsing the blocks inside the function that contains
// the inlined concrete instance. Since these will be blocks inside the containing "real"
// function the offset will be for that function.
if ( subprogram_low_pc = = LLDB_INVALID_ADDRESS )
{
subprogram_low_pc = ranges . GetMinRangeBase ( 0 ) ;
}
}
2015-02-08 20:44:09 -05:00
const size_t num_ranges = ranges . GetSize ( ) ;
for ( size_t i = 0 ; i < num_ranges ; + + i )
{
const DWARFDebugRanges : : Range & range = ranges . GetEntryRef ( i ) ;
const addr_t range_base = range . GetRangeBase ( ) ;
if ( range_base > = subprogram_low_pc )
block - > AddRange ( Block : : Range ( range_base - subprogram_low_pc , range . GetByteSize ( ) ) ) ;
else
{
GetObjectFile ( ) - > GetModule ( ) - > ReportError ( " 0x%8.8 " PRIx64 " : adding range [0x% " PRIx64 " -0x% " PRIx64 " ) which has a base that is less than the function's low PC 0x% " PRIx64 " . Please file a bug and attach the file at the start of this error message " ,
block - > GetID ( ) ,
range_base ,
range . GetRangeEnd ( ) ,
subprogram_low_pc ) ;
}
}
block - > FinalizeRanges ( ) ;
2013-08-23 13:46:38 -04:00
if ( tag ! = DW_TAG_subprogram & & ( name ! = NULL | | mangled_name ! = NULL ) )
{
std : : unique_ptr < Declaration > decl_ap ;
if ( decl_file ! = 0 | | decl_line ! = 0 | | decl_column ! = 0 )
decl_ap . reset ( new Declaration ( sc . comp_unit - > GetSupportFiles ( ) . GetFileSpecAtIndex ( decl_file ) ,
decl_line , decl_column ) ) ;
std : : unique_ptr < Declaration > call_ap ;
if ( call_file ! = 0 | | call_line ! = 0 | | call_column ! = 0 )
call_ap . reset ( new Declaration ( sc . comp_unit - > GetSupportFiles ( ) . GetFileSpecAtIndex ( call_file ) ,
call_line , call_column ) ) ;
block - > SetInlinedFunctionInfo ( name , mangled_name , decl_ap . get ( ) , call_ap . get ( ) ) ;
}
+ + blocks_added ;
if ( die - > HasChildren ( ) )
{
blocks_added + = ParseFunctionBlocks ( sc ,
block ,
dwarf_cu ,
die - > GetFirstChild ( ) ,
subprogram_low_pc ,
depth + 1 ) ;
}
}
}
break ;
default :
break ;
}
// Only parse siblings of the block if we are not at depth zero. A depth
// of zero indicates we are currently parsing the top level
// DW_TAG_subprogram DIE
if ( depth = = 0 )
die = NULL ;
else
die = die - > GetSibling ( ) ;
}
return blocks_added ;
}
bool
SymbolFileDWARF : : ParseTemplateDIE ( DWARFCompileUnit * dwarf_cu ,
const DWARFDebugInfoEntry * die ,
ClangASTContext : : TemplateParameterInfos & template_param_infos )
{
const dw_tag_t tag = die - > Tag ( ) ;
switch ( tag )
{
case DW_TAG_template_type_parameter :
case DW_TAG_template_value_parameter :
{
2015-02-06 16:38:51 -05:00
const uint8_t * fixed_form_sizes = DWARFFormValue : : GetFixedFormSizesForAddressSize ( dwarf_cu - > GetAddressByteSize ( ) , dwarf_cu - > IsDWARF64 ( ) ) ;
2013-08-23 13:46:38 -04:00
DWARFDebugInfoEntry : : Attributes attributes ;
const size_t num_attributes = die - > GetAttributes ( this ,
dwarf_cu ,
fixed_form_sizes ,
attributes ) ;
const char * name = NULL ;
Type * lldb_type = NULL ;
ClangASTType clang_type ;
uint64_t uval64 = 0 ;
bool uval64_valid = false ;
if ( num_attributes > 0 )
{
DWARFFormValue form_value ;
for ( size_t i = 0 ; i < num_attributes ; + + i )
{
const dw_attr_t attr = attributes . AttributeAtIndex ( i ) ;
switch ( attr )
{
case DW_AT_name :
if ( attributes . ExtractFormValueAtIndex ( this , i , form_value ) )
name = form_value . AsCString ( & get_debug_str_data ( ) ) ;
break ;
case DW_AT_type :
if ( attributes . ExtractFormValueAtIndex ( this , i , form_value ) )
{
2015-02-06 16:38:51 -05:00
const dw_offset_t type_die_offset = form_value . Reference ( ) ;
2013-08-23 13:46:38 -04:00
lldb_type = ResolveTypeUID ( type_die_offset ) ;
if ( lldb_type )
clang_type = lldb_type - > GetClangForwardType ( ) ;
}
break ;
case DW_AT_const_value :
if ( attributes . ExtractFormValueAtIndex ( this , i , form_value ) )
{
uval64_valid = true ;
uval64 = form_value . Unsigned ( ) ;
}
break ;
default :
break ;
}
}
clang : : ASTContext * ast = GetClangASTContext ( ) . getASTContext ( ) ;
if ( ! clang_type )
clang_type = GetClangASTContext ( ) . GetBasicType ( eBasicTypeVoid ) ;
if ( clang_type )
{
bool is_signed = false ;
if ( name & & name [ 0 ] )
template_param_infos . names . push_back ( name ) ;
else
template_param_infos . names . push_back ( NULL ) ;
if ( tag = = DW_TAG_template_value_parameter & &
lldb_type ! = NULL & &
clang_type . IsIntegerType ( is_signed ) & &
uval64_valid )
{
llvm : : APInt apint ( lldb_type - > GetByteSize ( ) * 8 , uval64 , is_signed ) ;
template_param_infos . args . push_back ( clang : : TemplateArgument ( * ast ,
llvm : : APSInt ( apint ) ,
clang_type . GetQualType ( ) ) ) ;
}
else
{
template_param_infos . args . push_back ( clang : : TemplateArgument ( clang_type . GetQualType ( ) ) ) ;
}
}
else
{
return false ;
}
}
}
return true ;
default :
break ;
}
return false ;
}
bool
SymbolFileDWARF : : ParseTemplateParameterInfos ( DWARFCompileUnit * dwarf_cu ,
const DWARFDebugInfoEntry * parent_die ,
ClangASTContext : : TemplateParameterInfos & template_param_infos )
{
if ( parent_die = = NULL )
return false ;
Args template_parameter_names ;
for ( const DWARFDebugInfoEntry * die = parent_die - > GetFirstChild ( ) ;
die ! = NULL ;
die = die - > GetSibling ( ) )
{
const dw_tag_t tag = die - > Tag ( ) ;
switch ( tag )
{
case DW_TAG_template_type_parameter :
case DW_TAG_template_value_parameter :
ParseTemplateDIE ( dwarf_cu , die , template_param_infos ) ;
break ;
default :
break ;
}
}
if ( template_param_infos . args . empty ( ) )
return false ;
return template_param_infos . args . size ( ) = = template_param_infos . names . size ( ) ;
}
clang : : ClassTemplateDecl *
SymbolFileDWARF : : ParseClassTemplateDecl ( clang : : DeclContext * decl_ctx ,
lldb : : AccessType access_type ,
const char * parent_name ,
int tag_decl_kind ,
const ClangASTContext : : TemplateParameterInfos & template_param_infos )
{
if ( template_param_infos . IsValid ( ) )
{
std : : string template_basename ( parent_name ) ;
template_basename . erase ( template_basename . find ( ' < ' ) ) ;
ClangASTContext & ast = GetClangASTContext ( ) ;
return ast . CreateClassTemplateDecl ( decl_ctx ,
access_type ,
template_basename . c_str ( ) ,
tag_decl_kind ,
template_param_infos ) ;
}
return NULL ;
}
class SymbolFileDWARF : : DelayedAddObjCClassProperty
{
public :
DelayedAddObjCClassProperty
(
const ClangASTType & class_opaque_type ,
const char * property_name ,
const ClangASTType & property_opaque_type , // The property type is only required if you don't have an ivar decl
clang : : ObjCIvarDecl * ivar_decl ,
const char * property_setter_name ,
const char * property_getter_name ,
uint32_t property_attributes ,
const ClangASTMetadata * metadata
) :
m_class_opaque_type ( class_opaque_type ) ,
m_property_name ( property_name ) ,
m_property_opaque_type ( property_opaque_type ) ,
m_ivar_decl ( ivar_decl ) ,
m_property_setter_name ( property_setter_name ) ,
m_property_getter_name ( property_getter_name ) ,
m_property_attributes ( property_attributes )
{
if ( metadata ! = NULL )
{
m_metadata_ap . reset ( new ClangASTMetadata ( ) ) ;
* m_metadata_ap = * metadata ;
}
}
DelayedAddObjCClassProperty ( const DelayedAddObjCClassProperty & rhs )
{
* this = rhs ;
}
DelayedAddObjCClassProperty & operator = ( const DelayedAddObjCClassProperty & rhs )
{
m_class_opaque_type = rhs . m_class_opaque_type ;
m_property_name = rhs . m_property_name ;
m_property_opaque_type = rhs . m_property_opaque_type ;
m_ivar_decl = rhs . m_ivar_decl ;
m_property_setter_name = rhs . m_property_setter_name ;
m_property_getter_name = rhs . m_property_getter_name ;
m_property_attributes = rhs . m_property_attributes ;
if ( rhs . m_metadata_ap . get ( ) )
{
m_metadata_ap . reset ( new ClangASTMetadata ( ) ) ;
* m_metadata_ap = * rhs . m_metadata_ap ;
}
return * this ;
}
bool
Finalize ( )
{
return m_class_opaque_type . AddObjCClassProperty ( m_property_name ,
m_property_opaque_type ,
m_ivar_decl ,
m_property_setter_name ,
m_property_getter_name ,
m_property_attributes ,
m_metadata_ap . get ( ) ) ;
}
private :
ClangASTType m_class_opaque_type ;
const char * m_property_name ;
ClangASTType m_property_opaque_type ;
clang : : ObjCIvarDecl * m_ivar_decl ;
const char * m_property_setter_name ;
const char * m_property_getter_name ;
uint32_t m_property_attributes ;
std : : unique_ptr < ClangASTMetadata > m_metadata_ap ;
} ;
struct BitfieldInfo
{
uint64_t bit_size ;
uint64_t bit_offset ;
BitfieldInfo ( ) :
bit_size ( LLDB_INVALID_ADDRESS ) ,
bit_offset ( LLDB_INVALID_ADDRESS )
{
}
2014-02-18 11:23:10 -05:00
void
Clear ( )
{
bit_size = LLDB_INVALID_ADDRESS ;
bit_offset = LLDB_INVALID_ADDRESS ;
}
2013-08-23 13:46:38 -04:00
bool IsValid ( )
{
return ( bit_size ! = LLDB_INVALID_ADDRESS ) & &
( bit_offset ! = LLDB_INVALID_ADDRESS ) ;
}
} ;
bool
SymbolFileDWARF : : ClassOrStructIsVirtual ( DWARFCompileUnit * dwarf_cu ,
const DWARFDebugInfoEntry * parent_die )
{
if ( parent_die )
{
for ( const DWARFDebugInfoEntry * die = parent_die - > GetFirstChild ( ) ; die ! = NULL ; die = die - > GetSibling ( ) )
{
dw_tag_t tag = die - > Tag ( ) ;
bool check_virtuality = false ;
switch ( tag )
{
case DW_TAG_inheritance :
case DW_TAG_subprogram :
check_virtuality = true ;
break ;
default :
break ;
}
if ( check_virtuality )
{
if ( die - > GetAttributeValueAsUnsigned ( this , dwarf_cu , DW_AT_virtuality , 0 ) ! = 0 )
return true ;
}
}
}
return false ;
}
size_t
SymbolFileDWARF : : ParseChildMembers
(
const SymbolContext & sc ,
DWARFCompileUnit * dwarf_cu ,
const DWARFDebugInfoEntry * parent_die ,
ClangASTType & class_clang_type ,
const LanguageType class_language ,
std : : vector < clang : : CXXBaseSpecifier * > & base_classes ,
std : : vector < int > & member_accessibilities ,
DWARFDIECollection & member_function_dies ,
DelayedPropertyList & delayed_properties ,
AccessType & default_accessibility ,
bool & is_a_class ,
LayoutInfo & layout_info
)
{
if ( parent_die = = NULL )
return 0 ;
size_t count = 0 ;
const DWARFDebugInfoEntry * die ;
2015-02-06 16:38:51 -05:00
const uint8_t * fixed_form_sizes = DWARFFormValue : : GetFixedFormSizesForAddressSize ( dwarf_cu - > GetAddressByteSize ( ) , dwarf_cu - > IsDWARF64 ( ) ) ;
2013-08-23 13:46:38 -04:00
uint32_t member_idx = 0 ;
BitfieldInfo last_field_info ;
2013-11-06 11:48:53 -05:00
ModuleSP module = GetObjectFile ( ) - > GetModule ( ) ;
2013-08-23 13:46:38 -04:00
for ( die = parent_die - > GetFirstChild ( ) ; die ! = NULL ; die = die - > GetSibling ( ) )
{
dw_tag_t tag = die - > Tag ( ) ;
switch ( tag )
{
case DW_TAG_member :
case DW_TAG_APPLE_property :
{
DWARFDebugInfoEntry : : Attributes attributes ;
const size_t num_attributes = die - > GetAttributes ( this ,
dwarf_cu ,
fixed_form_sizes ,
attributes ) ;
if ( num_attributes > 0 )
{
Declaration decl ;
//DWARFExpression location;
const char * name = NULL ;
const char * prop_name = NULL ;
const char * prop_getter_name = NULL ;
const char * prop_setter_name = NULL ;
uint32_t prop_attributes = 0 ;
bool is_artificial = false ;
lldb : : user_id_t encoding_uid = LLDB_INVALID_UID ;
AccessType accessibility = eAccessNone ;
uint32_t member_byte_offset = UINT32_MAX ;
size_t byte_size = 0 ;
size_t bit_offset = 0 ;
size_t bit_size = 0 ;
bool is_external = false ; // On DW_TAG_members, this means the member is static
uint32_t i ;
for ( i = 0 ; i < num_attributes & & ! is_artificial ; + + i )
{
const dw_attr_t attr = attributes . AttributeAtIndex ( i ) ;
DWARFFormValue form_value ;
if ( attributes . ExtractFormValueAtIndex ( this , i , form_value ) )
{
switch ( attr )
{
case DW_AT_decl_file : decl . SetFile ( sc . comp_unit - > GetSupportFiles ( ) . GetFileSpecAtIndex ( form_value . Unsigned ( ) ) ) ; break ;
case DW_AT_decl_line : decl . SetLine ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_decl_column : decl . SetColumn ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_name : name = form_value . AsCString ( & get_debug_str_data ( ) ) ; break ;
2015-02-06 16:38:51 -05:00
case DW_AT_type : encoding_uid = form_value . Reference ( ) ; break ;
2013-08-23 13:46:38 -04:00
case DW_AT_bit_offset : bit_offset = form_value . Unsigned ( ) ; break ;
case DW_AT_bit_size : bit_size = form_value . Unsigned ( ) ; break ;
case DW_AT_byte_size : byte_size = form_value . Unsigned ( ) ; break ;
case DW_AT_data_member_location :
if ( form_value . BlockData ( ) )
{
Value initialValue ( 0 ) ;
Value memberOffset ( 0 ) ;
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor & debug_info_data = get_debug_info_data ( ) ;
2013-08-23 13:46:38 -04:00
uint32_t block_length = form_value . Unsigned ( ) ;
uint32_t block_offset = form_value . BlockData ( ) - debug_info_data . GetDataStart ( ) ;
if ( DWARFExpression : : Evaluate ( NULL , // ExecutionContext *
NULL , // ClangExpressionVariableList *
NULL , // ClangExpressionDeclMap *
NULL , // RegisterContext *
2013-11-06 11:48:53 -05:00
module ,
2013-08-23 13:46:38 -04:00
debug_info_data ,
block_offset ,
block_length ,
eRegisterKindDWARF ,
& initialValue ,
memberOffset ,
NULL ) )
{
member_byte_offset = memberOffset . ResolveValue ( NULL ) . UInt ( ) ;
}
}
else
{
// With DWARF 3 and later, if the value is an integer constant,
// this form value is the offset in bytes from the beginning
// of the containing entity.
member_byte_offset = form_value . Unsigned ( ) ;
}
break ;
case DW_AT_accessibility : accessibility = DW_ACCESS_to_AccessType ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_artificial : is_artificial = form_value . Boolean ( ) ; break ;
case DW_AT_APPLE_property_name : prop_name = form_value . AsCString ( & get_debug_str_data ( ) ) ; break ;
case DW_AT_APPLE_property_getter : prop_getter_name = form_value . AsCString ( & get_debug_str_data ( ) ) ; break ;
case DW_AT_APPLE_property_setter : prop_setter_name = form_value . AsCString ( & get_debug_str_data ( ) ) ; break ;
case DW_AT_APPLE_property_attribute : prop_attributes = form_value . Unsigned ( ) ; break ;
case DW_AT_external : is_external = form_value . Boolean ( ) ; break ;
default :
case DW_AT_declaration :
case DW_AT_description :
case DW_AT_mutable :
case DW_AT_visibility :
case DW_AT_sibling :
break ;
}
}
}
if ( prop_name )
{
ConstString fixed_getter ;
ConstString fixed_setter ;
// Check if the property getter/setter were provided as full
// names. We want basenames, so we extract them.
if ( prop_getter_name & & prop_getter_name [ 0 ] = = ' - ' )
{
ObjCLanguageRuntime : : MethodName prop_getter_method ( prop_getter_name , true ) ;
prop_getter_name = prop_getter_method . GetSelector ( ) . GetCString ( ) ;
}
if ( prop_setter_name & & prop_setter_name [ 0 ] = = ' - ' )
{
ObjCLanguageRuntime : : MethodName prop_setter_method ( prop_setter_name , true ) ;
prop_setter_name = prop_setter_method . GetSelector ( ) . GetCString ( ) ;
}
// If the names haven't been provided, they need to be
// filled in.
if ( ! prop_getter_name )
{
prop_getter_name = prop_name ;
}
if ( ! prop_setter_name & & prop_name [ 0 ] & & ! ( prop_attributes & DW_APPLE_PROPERTY_readonly ) )
{
StreamString ss ;
ss . Printf ( " set%c%s: " ,
toupper ( prop_name [ 0 ] ) ,
& prop_name [ 1 ] ) ;
fixed_setter . SetCString ( ss . GetData ( ) ) ;
prop_setter_name = fixed_setter . GetCString ( ) ;
}
}
// Clang has a DWARF generation bug where sometimes it
// represents fields that are references with bad byte size
// and bit size/offset information such as:
//
// DW_AT_byte_size( 0x00 )
// DW_AT_bit_size( 0x40 )
// DW_AT_bit_offset( 0xffffffffffffffc0 )
//
// So check the bit offset to make sure it is sane, and if
// the values are not sane, remove them. If we don't do this
// then we will end up with a crash if we try to use this
// type in an expression when clang becomes unhappy with its
// recycled debug info.
if ( bit_offset > 128 )
{
bit_size = 0 ;
bit_offset = 0 ;
}
// FIXME: Make Clang ignore Objective-C accessibility for expressions
if ( class_language = = eLanguageTypeObjC | |
class_language = = eLanguageTypeObjC_plus_plus )
accessibility = eAccessNone ;
if ( member_idx = = 0 & & ! is_artificial & & name & & ( strstr ( name , " _vptr$ " ) = = name ) )
{
// Not all compilers will mark the vtable pointer
// member as artificial (llvm-gcc). We can't have
// the virtual members in our classes otherwise it
// throws off all child offsets since we end up
// having and extra pointer sized member in our
// class layouts.
is_artificial = true ;
}
// Handle static members
if ( is_external & & member_byte_offset = = UINT32_MAX )
{
Type * var_type = ResolveTypeUID ( encoding_uid ) ;
if ( var_type )
{
if ( accessibility = = eAccessNone )
accessibility = eAccessPublic ;
class_clang_type . AddVariableToRecordType ( name ,
var_type - > GetClangLayoutType ( ) ,
accessibility ) ;
}
break ;
}
if ( is_artificial = = false )
{
Type * member_type = ResolveTypeUID ( encoding_uid ) ;
clang : : FieldDecl * field_decl = NULL ;
if ( tag = = DW_TAG_member )
{
if ( member_type )
{
if ( accessibility = = eAccessNone )
accessibility = default_accessibility ;
member_accessibilities . push_back ( accessibility ) ;
2014-02-18 11:23:10 -05:00
uint64_t field_bit_offset = ( member_byte_offset = = UINT32_MAX ? 0 : ( member_byte_offset * 8 ) ) ;
if ( bit_size > 0 )
2013-08-23 13:46:38 -04:00
{
2014-02-18 11:23:10 -05:00
BitfieldInfo this_field_info ;
this_field_info . bit_offset = field_bit_offset ;
this_field_info . bit_size = bit_size ;
2013-08-23 13:46:38 -04:00
/////////////////////////////////////////////////////////////
// How to locate a field given the DWARF debug information
//
// AT_byte_size indicates the size of the word in which the
// bit offset must be interpreted.
//
// AT_data_member_location indicates the byte offset of the
// word from the base address of the structure.
//
// AT_bit_offset indicates how many bits into the word
// (according to the host endianness) the low-order bit of
// the field starts. AT_bit_offset can be negative.
//
// AT_bit_size indicates the size of the field in bits.
/////////////////////////////////////////////////////////////
2014-02-18 11:23:10 -05:00
if ( byte_size = = 0 )
byte_size = member_type - > GetByteSize ( ) ;
2013-08-23 13:46:38 -04:00
if ( GetObjectFile ( ) - > GetByteOrder ( ) = = eByteOrderLittle )
{
this_field_info . bit_offset + = byte_size * 8 ;
this_field_info . bit_offset - = ( bit_offset + bit_size ) ;
}
else
{
this_field_info . bit_offset + = bit_offset ;
}
2014-02-18 11:23:10 -05:00
// Update the field bit offset we will report for layout
field_bit_offset = this_field_info . bit_offset ;
2013-08-23 13:46:38 -04:00
2014-02-18 11:23:10 -05:00
// If the member to be emitted did not start on a character boundary and there is
// empty space between the last field and this one, then we need to emit an
// anonymous member filling up the space up to its start. There are three cases
// here:
//
// 1 If the previous member ended on a character boundary, then we can emit an
// anonymous member starting at the most recent character boundary.
//
// 2 If the previous member did not end on a character boundary and the distance
// from the end of the previous member to the current member is less than a
// word width, then we can emit an anonymous member starting right after the
// previous member and right before this member.
//
// 3 If the previous member did not end on a character boundary and the distance
// from the end of the previous member to the current member is greater than
// or equal a word width, then we act as in Case 1.
const uint64_t character_width = 8 ;
const uint64_t word_width = 32 ;
2013-08-23 13:46:38 -04:00
// Objective-C has invalid DW_AT_bit_offset values in older versions
2014-11-25 16:00:58 -05:00
// of clang, so we have to be careful and only insert unnamed bitfields
2013-08-23 13:46:38 -04:00
// if we have a new enough clang.
bool detect_unnamed_bitfields = true ;
if ( class_language = = eLanguageTypeObjC | | class_language = = eLanguageTypeObjC_plus_plus )
detect_unnamed_bitfields = dwarf_cu - > Supports_unnamed_objc_bitfields ( ) ;
if ( detect_unnamed_bitfields )
{
BitfieldInfo anon_field_info ;
if ( ( this_field_info . bit_offset % character_width ) ! = 0 ) // not char aligned
{
uint64_t last_field_end = 0 ;
if ( last_field_info . IsValid ( ) )
last_field_end = last_field_info . bit_offset + last_field_info . bit_size ;
if ( this_field_info . bit_offset ! = last_field_end )
{
if ( ( ( last_field_end % character_width ) = = 0 ) | | // case 1
( this_field_info . bit_offset - last_field_end > = word_width ) ) // case 3
{
anon_field_info . bit_size = this_field_info . bit_offset % character_width ;
anon_field_info . bit_offset = this_field_info . bit_offset - anon_field_info . bit_size ;
}
else // case 2
{
anon_field_info . bit_size = this_field_info . bit_offset - last_field_end ;
anon_field_info . bit_offset = last_field_end ;
}
}
}
if ( anon_field_info . IsValid ( ) )
{
clang : : FieldDecl * unnamed_bitfield_decl = class_clang_type . AddFieldToRecordType ( NULL ,
GetClangASTContext ( ) . GetBuiltinTypeForEncodingAndBitSize ( eEncodingSint , word_width ) ,
accessibility ,
anon_field_info . bit_size ) ;
2015-07-03 12:57:06 -04:00
layout_info . field_offsets . insert (
std : : make_pair ( unnamed_bitfield_decl , anon_field_info . bit_offset ) ) ;
2013-08-23 13:46:38 -04:00
}
}
2014-02-18 11:23:10 -05:00
last_field_info = this_field_info ;
}
else
{
last_field_info . Clear ( ) ;
2013-08-23 13:46:38 -04:00
}
ClangASTType member_clang_type = member_type - > GetClangLayoutType ( ) ;
{
// Older versions of clang emit array[0] and array[1] in the same way (<rdar://problem/12566646>).
// If the current field is at the end of the structure, then there is definitely no room for extra
// elements and we override the type to array[0].
ClangASTType member_array_element_type ;
uint64_t member_array_size ;
bool member_array_is_incomplete ;
if ( member_clang_type . IsArrayType ( & member_array_element_type ,
& member_array_size ,
& member_array_is_incomplete ) & &
! member_array_is_incomplete )
{
uint64_t parent_byte_size = parent_die - > GetAttributeValueAsUnsigned ( this , dwarf_cu , DW_AT_byte_size , UINT64_MAX ) ;
if ( member_byte_offset > = parent_byte_size )
{
if ( member_array_size ! = 1 )
{
GetObjectFile ( ) - > GetModule ( ) - > ReportError ( " 0x%8.8 " PRIx64 " : DW_TAG_member '%s' refers to type 0x%8.8 " PRIx64 " which extends beyond the bounds of 0x%8.8 " PRIx64 ,
MakeUserID ( die - > GetOffset ( ) ) ,
name ,
encoding_uid ,
MakeUserID ( parent_die - > GetOffset ( ) ) ) ;
}
member_clang_type = GetClangASTContext ( ) . CreateArrayType ( member_array_element_type , 0 , false ) ;
}
}
}
field_decl = class_clang_type . AddFieldToRecordType ( name ,
member_clang_type ,
accessibility ,
bit_size ) ;
GetClangASTContext ( ) . SetMetadataAsUserID ( field_decl , MakeUserID ( die - > GetOffset ( ) ) ) ;
2014-02-18 11:23:10 -05:00
2015-07-03 12:57:06 -04:00
layout_info . field_offsets . insert ( std : : make_pair ( field_decl , field_bit_offset ) ) ;
2013-08-23 13:46:38 -04:00
}
else
{
if ( name )
GetObjectFile ( ) - > GetModule ( ) - > ReportError ( " 0x%8.8 " PRIx64 " : DW_TAG_member '%s' refers to type 0x%8.8 " PRIx64 " which was unable to be parsed " ,
MakeUserID ( die - > GetOffset ( ) ) ,
name ,
encoding_uid ) ;
else
GetObjectFile ( ) - > GetModule ( ) - > ReportError ( " 0x%8.8 " PRIx64 " : DW_TAG_member refers to type 0x%8.8 " PRIx64 " which was unable to be parsed " ,
MakeUserID ( die - > GetOffset ( ) ) ,
encoding_uid ) ;
}
}
2015-09-06 10:32:30 -04:00
if ( prop_name ! = NULL & & member_type )
2013-08-23 13:46:38 -04:00
{
clang : : ObjCIvarDecl * ivar_decl = NULL ;
if ( field_decl )
{
ivar_decl = clang : : dyn_cast < clang : : ObjCIvarDecl > ( field_decl ) ;
assert ( ivar_decl ! = NULL ) ;
}
ClangASTMetadata metadata ;
metadata . SetUserID ( MakeUserID ( die - > GetOffset ( ) ) ) ;
delayed_properties . push_back ( DelayedAddObjCClassProperty ( class_clang_type ,
prop_name ,
member_type - > GetClangLayoutType ( ) ,
ivar_decl ,
prop_setter_name ,
prop_getter_name ,
prop_attributes ,
& metadata ) ) ;
if ( ivar_decl )
GetClangASTContext ( ) . SetMetadataAsUserID ( ivar_decl , MakeUserID ( die - > GetOffset ( ) ) ) ;
}
}
}
+ + member_idx ;
}
break ;
case DW_TAG_subprogram :
// Let the type parsing code handle this one for us.
member_function_dies . Append ( die ) ;
break ;
case DW_TAG_inheritance :
{
is_a_class = true ;
if ( default_accessibility = = eAccessNone )
default_accessibility = eAccessPrivate ;
// TODO: implement DW_TAG_inheritance type parsing
DWARFDebugInfoEntry : : Attributes attributes ;
const size_t num_attributes = die - > GetAttributes ( this ,
dwarf_cu ,
fixed_form_sizes ,
attributes ) ;
if ( num_attributes > 0 )
{
Declaration decl ;
DWARFExpression location ;
lldb : : user_id_t encoding_uid = LLDB_INVALID_UID ;
AccessType accessibility = default_accessibility ;
bool is_virtual = false ;
bool is_base_of_class = true ;
off_t member_byte_offset = 0 ;
uint32_t i ;
for ( i = 0 ; i < num_attributes ; + + i )
{
const dw_attr_t attr = attributes . AttributeAtIndex ( i ) ;
DWARFFormValue form_value ;
if ( attributes . ExtractFormValueAtIndex ( this , i , form_value ) )
{
switch ( attr )
{
case DW_AT_decl_file : decl . SetFile ( sc . comp_unit - > GetSupportFiles ( ) . GetFileSpecAtIndex ( form_value . Unsigned ( ) ) ) ; break ;
case DW_AT_decl_line : decl . SetLine ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_decl_column : decl . SetColumn ( form_value . Unsigned ( ) ) ; break ;
2015-02-06 16:38:51 -05:00
case DW_AT_type : encoding_uid = form_value . Reference ( ) ; break ;
2013-08-23 13:46:38 -04:00
case DW_AT_data_member_location :
if ( form_value . BlockData ( ) )
{
Value initialValue ( 0 ) ;
Value memberOffset ( 0 ) ;
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor & debug_info_data = get_debug_info_data ( ) ;
2013-08-23 13:46:38 -04:00
uint32_t block_length = form_value . Unsigned ( ) ;
uint32_t block_offset = form_value . BlockData ( ) - debug_info_data . GetDataStart ( ) ;
if ( DWARFExpression : : Evaluate ( NULL ,
NULL ,
NULL ,
NULL ,
2013-11-06 11:48:53 -05:00
module ,
2013-08-23 13:46:38 -04:00
debug_info_data ,
block_offset ,
block_length ,
eRegisterKindDWARF ,
& initialValue ,
memberOffset ,
NULL ) )
{
member_byte_offset = memberOffset . ResolveValue ( NULL ) . UInt ( ) ;
}
}
else
{
// With DWARF 3 and later, if the value is an integer constant,
// this form value is the offset in bytes from the beginning
// of the containing entity.
member_byte_offset = form_value . Unsigned ( ) ;
}
break ;
case DW_AT_accessibility :
accessibility = DW_ACCESS_to_AccessType ( form_value . Unsigned ( ) ) ;
break ;
case DW_AT_virtuality :
is_virtual = form_value . Boolean ( ) ;
break ;
case DW_AT_sibling :
break ;
default :
break ;
}
}
}
Type * base_class_type = ResolveTypeUID ( encoding_uid ) ;
2015-07-03 12:57:06 -04:00
if ( base_class_type = = NULL )
{
GetObjectFile ( ) - > GetModule ( ) - > ReportError ( " 0x%8.8x: DW_TAG_inheritance failed to resolve the base class at 0x%8.8 " PRIx64 " from enclosing type 0x%8.8x. \n Please file a bug and attach the file at the start of this error message " ,
die - > GetOffset ( ) ,
encoding_uid ,
parent_die - > GetOffset ( ) ) ;
break ;
}
2013-08-23 13:46:38 -04:00
ClangASTType base_class_clang_type = base_class_type - > GetClangFullType ( ) ;
assert ( base_class_clang_type ) ;
if ( class_language = = eLanguageTypeObjC )
{
class_clang_type . SetObjCSuperClass ( base_class_clang_type ) ;
}
else
{
base_classes . push_back ( base_class_clang_type . CreateBaseClassSpecifier ( accessibility ,
is_virtual ,
is_base_of_class ) ) ;
if ( is_virtual )
{
2013-11-06 11:48:53 -05:00
// Do not specify any offset for virtual inheritance. The DWARF produced by clang doesn't
// give us a constant offset, but gives us a DWARF expressions that requires an actual object
// in memory. the DW_AT_data_member_location for a virtual base class looks like:
// DW_AT_data_member_location( DW_OP_dup, DW_OP_deref, DW_OP_constu(0x00000018), DW_OP_minus, DW_OP_deref, DW_OP_plus )
// Given this, there is really no valid response we can give to clang for virtual base
// class offsets, and this should eventually be removed from LayoutRecordType() in the external
// AST source in clang.
2013-08-23 13:46:38 -04:00
}
else
{
2015-07-03 12:57:06 -04:00
layout_info . base_offsets . insert (
std : : make_pair ( base_class_clang_type . GetAsCXXRecordDecl ( ) ,
clang : : CharUnits : : fromQuantity ( member_byte_offset ) ) ) ;
2013-08-23 13:46:38 -04:00
}
}
}
}
break ;
default :
break ;
}
}
return count ;
}
clang : : DeclContext *
SymbolFileDWARF : : GetClangDeclContextContainingTypeUID ( lldb : : user_id_t type_uid )
{
DWARFDebugInfo * debug_info = DebugInfo ( ) ;
if ( debug_info & & UserIDMatches ( type_uid ) )
{
DWARFCompileUnitSP cu_sp ;
const DWARFDebugInfoEntry * die = debug_info - > GetDIEPtr ( type_uid , & cu_sp ) ;
if ( die )
return GetClangDeclContextContainingDIE ( cu_sp . get ( ) , die , NULL ) ;
}
return NULL ;
}
clang : : DeclContext *
SymbolFileDWARF : : GetClangDeclContextForTypeUID ( const lldb_private : : SymbolContext & sc , lldb : : user_id_t type_uid )
{
if ( UserIDMatches ( type_uid ) )
return GetClangDeclContextForDIEOffset ( sc , type_uid ) ;
return NULL ;
}
Type *
SymbolFileDWARF : : ResolveTypeUID ( lldb : : user_id_t type_uid )
{
if ( UserIDMatches ( type_uid ) )
{
DWARFDebugInfo * debug_info = DebugInfo ( ) ;
if ( debug_info )
{
DWARFCompileUnitSP cu_sp ;
const DWARFDebugInfoEntry * type_die = debug_info - > GetDIEPtr ( type_uid , & cu_sp ) ;
const bool assert_not_being_parsed = true ;
return ResolveTypeUID ( cu_sp . get ( ) , type_die , assert_not_being_parsed ) ;
}
}
return NULL ;
}
Type *
SymbolFileDWARF : : ResolveTypeUID ( DWARFCompileUnit * cu , const DWARFDebugInfoEntry * die , bool assert_not_being_parsed )
{
if ( die ! = NULL )
{
Log * log ( LogChannelDWARF : : GetLogIfAll ( DWARF_LOG_DEBUG_INFO ) ) ;
if ( log )
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' " ,
die - > GetOffset ( ) ,
DW_TAG_value_to_name ( die - > Tag ( ) ) ,
die - > GetName ( this , cu ) ) ;
// We might be coming in in the middle of a type tree (a class
// withing a class, an enum within a class), so parse any needed
// parent DIEs before we get to this one...
const DWARFDebugInfoEntry * decl_ctx_die = GetDeclContextDIEContainingDIE ( cu , die ) ;
switch ( decl_ctx_die - > Tag ( ) )
{
case DW_TAG_structure_type :
case DW_TAG_union_type :
case DW_TAG_class_type :
{
// Get the type, which could be a forward declaration
if ( log )
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent forward type for 0x%8.8x " ,
die - > GetOffset ( ) ,
DW_TAG_value_to_name ( die - > Tag ( ) ) ,
die - > GetName ( this , cu ) ,
decl_ctx_die - > GetOffset ( ) ) ;
//
// Type *parent_type = ResolveTypeUID (cu, decl_ctx_die, assert_not_being_parsed);
// if (child_requires_parent_class_union_or_struct_to_be_completed(die->Tag()))
// {
// if (log)
// GetObjectFile()->GetModule()->LogMessage (log,
// "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent full type for 0x%8.8x since die is a function",
// die->GetOffset(),
// DW_TAG_value_to_name(die->Tag()),
// die->GetName(this, cu),
// decl_ctx_die->GetOffset());
// // Ask the type to complete itself if it already hasn't since if we
// // want a function (method or static) from a class, the class must
// // create itself and add it's own methods and class functions.
// if (parent_type)
// parent_type->GetClangFullType();
// }
}
break ;
default :
break ;
}
return ResolveType ( cu , die ) ;
}
return NULL ;
}
// This function is used when SymbolFileDWARFDebugMap owns a bunch of
// SymbolFileDWARF objects to detect if this DWARF file is the one that
// can resolve a clang_type.
bool
SymbolFileDWARF : : HasForwardDeclForClangType ( const ClangASTType & clang_type )
{
ClangASTType clang_type_no_qualifiers = clang_type . RemoveFastQualifiers ( ) ;
const DWARFDebugInfoEntry * die = m_forward_decl_clang_type_to_die . lookup ( clang_type_no_qualifiers . GetOpaqueQualType ( ) ) ;
return die ! = NULL ;
}
bool
SymbolFileDWARF : : ResolveClangOpaqueTypeDefinition ( ClangASTType & clang_type )
{
// We have a struct/union/class/enum that needs to be fully resolved.
ClangASTType clang_type_no_qualifiers = clang_type . RemoveFastQualifiers ( ) ;
const DWARFDebugInfoEntry * die = m_forward_decl_clang_type_to_die . lookup ( clang_type_no_qualifiers . GetOpaqueQualType ( ) ) ;
if ( die = = NULL )
{
// We have already resolved this type...
return true ;
}
// Once we start resolving this type, remove it from the forward declaration
// map in case anyone child members or other types require this type to get resolved.
// The type will get resolved when all of the calls to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition
// are done.
m_forward_decl_clang_type_to_die . erase ( clang_type_no_qualifiers . GetOpaqueQualType ( ) ) ;
// Disable external storage for this type so we don't get anymore
// clang::ExternalASTSource queries for this type.
clang_type . SetHasExternalStorage ( false ) ;
DWARFDebugInfo * debug_info = DebugInfo ( ) ;
DWARFCompileUnit * dwarf_cu = debug_info - > GetCompileUnitContainingDIE ( die - > GetOffset ( ) ) . get ( ) ;
Type * type = m_die_to_type . lookup ( die ) ;
const dw_tag_t tag = die - > Tag ( ) ;
Log * log ( LogChannelDWARF : : GetLogIfAny ( DWARF_LOG_DEBUG_INFO | DWARF_LOG_TYPE_COMPLETION ) ) ;
if ( log )
GetObjectFile ( ) - > GetModule ( ) - > LogMessageVerboseBacktrace ( log ,
" 0x%8.8 " PRIx64 " : %s '%s' resolving forward declaration... " ,
MakeUserID ( die - > GetOffset ( ) ) ,
DW_TAG_value_to_name ( tag ) ,
type - > GetName ( ) . AsCString ( ) ) ;
assert ( clang_type ) ;
DWARFDebugInfoEntry : : Attributes attributes ;
switch ( tag )
{
case DW_TAG_structure_type :
case DW_TAG_union_type :
case DW_TAG_class_type :
{
LayoutInfo layout_info ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
{
if ( die - > HasChildren ( ) )
{
LanguageType class_language = eLanguageTypeUnknown ;
if ( clang_type . IsObjCObjectOrInterfaceType ( ) )
{
class_language = eLanguageTypeObjC ;
// For objective C we don't start the definition when
// the class is created.
clang_type . StartTagDeclarationDefinition ( ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
int tag_decl_kind = - 1 ;
AccessType default_accessibility = eAccessNone ;
if ( tag = = DW_TAG_structure_type )
{
tag_decl_kind = clang : : TTK_Struct ;
default_accessibility = eAccessPublic ;
}
else if ( tag = = DW_TAG_union_type )
{
tag_decl_kind = clang : : TTK_Union ;
default_accessibility = eAccessPublic ;
}
else if ( tag = = DW_TAG_class_type )
{
tag_decl_kind = clang : : TTK_Class ;
default_accessibility = eAccessPrivate ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
SymbolContext sc ( GetCompUnitForDWARFCompUnit ( dwarf_cu ) ) ;
std : : vector < clang : : CXXBaseSpecifier * > base_classes ;
std : : vector < int > member_accessibilities ;
bool is_a_class = false ;
// Parse members and base classes first
DWARFDIECollection member_function_dies ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
DelayedPropertyList delayed_properties ;
ParseChildMembers ( sc ,
dwarf_cu ,
die ,
clang_type ,
class_language ,
base_classes ,
member_accessibilities ,
member_function_dies ,
delayed_properties ,
default_accessibility ,
is_a_class ,
layout_info ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
// Now parse any methods if there were any...
size_t num_functions = member_function_dies . Size ( ) ;
if ( num_functions > 0 )
{
for ( size_t i = 0 ; i < num_functions ; + + i )
{
ResolveType ( dwarf_cu , member_function_dies . GetDIEPtrAtIndex ( i ) ) ;
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( class_language = = eLanguageTypeObjC )
{
2013-11-06 11:48:53 -05:00
ConstString class_name ( clang_type . GetTypeName ( ) ) ;
if ( class_name )
2013-08-23 13:46:38 -04:00
{
DIEArray method_die_offsets ;
if ( m_using_apple_tables )
{
if ( m_apple_objc_ap . get ( ) )
2013-11-06 11:48:53 -05:00
m_apple_objc_ap - > FindByName ( class_name . GetCString ( ) , method_die_offsets ) ;
2013-08-23 13:46:38 -04:00
}
else
{
if ( ! m_indexed )
Index ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
m_objc_class_selectors_index . Find ( class_name , method_die_offsets ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! method_die_offsets . empty ( ) )
{
DWARFDebugInfo * debug_info = DebugInfo ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
DWARFCompileUnit * method_cu = NULL ;
const size_t num_matches = method_die_offsets . size ( ) ;
for ( size_t i = 0 ; i < num_matches ; + + i )
{
const dw_offset_t die_offset = method_die_offsets [ i ] ;
DWARFDebugInfoEntry * method_die = debug_info - > GetDIEPtrWithCompileUnitHint ( die_offset , & method_cu ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( method_die )
ResolveType ( method_cu , method_die ) ;
else
{
if ( m_using_apple_tables )
{
GetObjectFile ( ) - > GetModule ( ) - > ReportErrorIfModifyDetected ( " the DWARF debug information has been modified (.apple_objc accelerator table had bad die 0x%8.8x for '%s') \n " ,
2013-11-06 11:48:53 -05:00
die_offset , class_name . GetCString ( ) ) ;
2013-08-23 13:46:38 -04:00
}
}
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
for ( DelayedPropertyList : : iterator pi = delayed_properties . begin ( ) , pe = delayed_properties . end ( ) ;
pi ! = pe ;
+ + pi )
pi - > Finalize ( ) ;
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
// If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we
// need to tell the clang type it is actually a class.
if ( class_language ! = eLanguageTypeObjC )
{
if ( is_a_class & & tag_decl_kind ! = clang : : TTK_Class )
clang_type . SetTagTypeKind ( clang : : TTK_Class ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
// Since DW_TAG_structure_type gets used for both classes
// and structures, we may need to set any DW_TAG_member
// fields to have a "private" access if none was specified.
// When we parsed the child members we tracked that actual
// accessibility value for each DW_TAG_member in the
// "member_accessibilities" array. If the value for the
// member is zero, then it was set to the "default_accessibility"
// which for structs was "public". Below we correct this
// by setting any fields to "private" that weren't correctly
// set.
if ( is_a_class & & ! member_accessibilities . empty ( ) )
{
// This is a class and all members that didn't have
// their access specified are private.
clang_type . SetDefaultAccessForRecordFields ( eAccessPrivate ,
& member_accessibilities . front ( ) ,
member_accessibilities . size ( ) ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! base_classes . empty ( ) )
{
2014-02-18 11:23:10 -05:00
// Make sure all base classes refer to complete types and not
// forward declarations. If we don't do this, clang will crash
// with an assertion in the call to clang_type.SetBaseClassesForClassType()
bool base_class_error = false ;
for ( auto & base_class : base_classes )
{
clang : : TypeSourceInfo * type_source_info = base_class - > getTypeSourceInfo ( ) ;
if ( type_source_info )
{
ClangASTType base_class_type ( GetClangASTContext ( ) . getASTContext ( ) , type_source_info - > getType ( ) ) ;
if ( base_class_type . GetCompleteType ( ) = = false )
{
if ( ! base_class_error )
{
GetObjectFile ( ) - > GetModule ( ) - > ReportError ( " DWARF DIE at 0x%8.8x for class '%s' has a base class '%s' that is a forward declaration, not a complete definition. \n Please file a bug against the compiler and include the preprocessed output for %s " ,
die - > GetOffset ( ) ,
die - > GetName ( this , dwarf_cu ) ,
base_class_type . GetTypeName ( ) . GetCString ( ) ,
sc . comp_unit ? sc . comp_unit - > GetPath ( ) . c_str ( ) : " the source file " ) ;
}
// We have no choice other than to pretend that the base class
// is complete. If we don't do this, clang will crash when we
// call setBases() inside of "clang_type.SetBaseClassesForClassType()"
// below. Since we provide layout assistance, all ivars in this
2014-11-25 16:00:58 -05:00
// class and other classes will be fine, this is the best we can do
2014-02-18 11:23:10 -05:00
// short of crashing.
base_class_type . StartTagDeclarationDefinition ( ) ;
base_class_type . CompleteTagDeclarationDefinition ( ) ;
}
}
}
2013-08-23 13:46:38 -04:00
clang_type . SetBaseClassesForClassType ( & base_classes . front ( ) ,
base_classes . size ( ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
// Clang will copy each CXXBaseSpecifier in "base_classes"
// so we have to free them all.
ClangASTType : : DeleteBaseClassSpecifiers ( & base_classes . front ( ) ,
base_classes . size ( ) ) ;
}
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
clang_type . BuildIndirectFields ( ) ;
clang_type . CompleteTagDeclarationDefinition ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! layout_info . field_offsets . empty ( ) | |
! layout_info . base_offsets . empty ( ) | |
! layout_info . vbase_offsets . empty ( ) )
{
if ( type )
layout_info . bit_size = type - > GetByteSize ( ) * 8 ;
if ( layout_info . bit_size = = 0 )
layout_info . bit_size = die - > GetAttributeValueAsUnsigned ( this , dwarf_cu , DW_AT_byte_size , 0 ) * 8 ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
clang : : CXXRecordDecl * record_decl = clang_type . GetAsCXXRecordDecl ( ) ;
if ( record_decl )
{
if ( log )
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) caching layout info for record_decl = %p, bit_size = % " PRIu64 " , alignment = % " PRIu64 " , field_offsets[%u], base_offsets[%u], vbase_offsets[%u]) " ,
2014-11-25 16:00:58 -05:00
static_cast < void * > ( clang_type . GetOpaqueQualType ( ) ) ,
static_cast < void * > ( record_decl ) ,
2013-08-23 13:46:38 -04:00
layout_info . bit_size ,
layout_info . alignment ,
2014-11-25 16:00:58 -05:00
static_cast < uint32_t > ( layout_info . field_offsets . size ( ) ) ,
static_cast < uint32_t > ( layout_info . base_offsets . size ( ) ) ,
static_cast < uint32_t > ( layout_info . vbase_offsets . size ( ) ) ) ;
2013-08-23 13:46:38 -04:00
uint32_t idx ;
{
2015-07-03 12:57:06 -04:00
llvm : : DenseMap < const clang : : FieldDecl * , uint64_t > : : const_iterator pos ,
end = layout_info . field_offsets . end ( ) ;
for ( idx = 0 , pos = layout_info . field_offsets . begin ( ) ; pos ! = end ; + + pos , + + idx )
2013-08-23 13:46:38 -04:00
{
2015-07-03 12:57:06 -04:00
GetObjectFile ( ) - > GetModule ( ) - > LogMessage (
log , " SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) field[%u] = "
" { bit_offset=%u, name='%s' } " ,
static_cast < void * > ( clang_type . GetOpaqueQualType ( ) ) , idx ,
static_cast < uint32_t > ( pos - > second ) , pos - > first - > getNameAsString ( ) . c_str ( ) ) ;
2013-08-23 13:46:38 -04:00
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
{
2015-07-03 12:57:06 -04:00
llvm : : DenseMap < const clang : : CXXRecordDecl * , clang : : CharUnits > : : const_iterator base_pos ,
base_end = layout_info . base_offsets . end ( ) ;
for ( idx = 0 , base_pos = layout_info . base_offsets . begin ( ) ; base_pos ! = base_end ;
+ + base_pos , + + idx )
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage (
log , " SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) base[%u] "
" = { byte_offset=%u, name='%s' } " ,
clang_type . GetOpaqueQualType ( ) , idx , ( uint32_t ) base_pos - > second . getQuantity ( ) ,
base_pos - > first - > getNameAsString ( ) . c_str ( ) ) ;
}
2013-08-23 13:46:38 -04:00
}
{
2015-07-03 12:57:06 -04:00
llvm : : DenseMap < const clang : : CXXRecordDecl * , clang : : CharUnits > : : const_iterator vbase_pos ,
vbase_end = layout_info . vbase_offsets . end ( ) ;
for ( idx = 0 , vbase_pos = layout_info . vbase_offsets . begin ( ) ; vbase_pos ! = vbase_end ;
+ + vbase_pos , + + idx )
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage (
log , " SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) "
" vbase[%u] = { byte_offset=%u, name='%s' } " ,
static_cast < void * > ( clang_type . GetOpaqueQualType ( ) ) , idx ,
static_cast < uint32_t > ( vbase_pos - > second . getQuantity ( ) ) ,
vbase_pos - > first - > getNameAsString ( ) . c_str ( ) ) ;
}
2013-08-23 13:46:38 -04:00
}
}
m_record_decl_to_layout_map . insert ( std : : make_pair ( record_decl , layout_info ) ) ;
}
}
}
2013-11-06 11:48:53 -05:00
return ( bool ) clang_type ;
2013-08-23 13:46:38 -04:00
case DW_TAG_enumeration_type :
clang_type . StartTagDeclarationDefinition ( ) ;
if ( die - > HasChildren ( ) )
{
SymbolContext sc ( GetCompUnitForDWARFCompUnit ( dwarf_cu ) ) ;
bool is_signed = false ;
clang_type . IsIntegerType ( is_signed ) ;
ParseChildEnumerators ( sc , clang_type , is_signed , type - > GetByteSize ( ) , dwarf_cu , die ) ;
}
clang_type . CompleteTagDeclarationDefinition ( ) ;
2013-11-06 11:48:53 -05:00
return ( bool ) clang_type ;
2013-08-23 13:46:38 -04:00
default :
assert ( false & & " not a forward clang type decl! " ) ;
break ;
}
return false ;
}
Type *
SymbolFileDWARF : : ResolveType ( DWARFCompileUnit * dwarf_cu , const DWARFDebugInfoEntry * type_die , bool assert_not_being_parsed )
{
if ( type_die ! = NULL )
{
Type * type = m_die_to_type . lookup ( type_die ) ;
if ( type = = NULL )
type = GetTypeForDIE ( dwarf_cu , type_die ) . get ( ) ;
if ( assert_not_being_parsed )
{
if ( type ! = DIE_IS_BEING_PARSED )
return type ;
GetObjectFile ( ) - > GetModule ( ) - > ReportError ( " Parsing a die that is being parsed die: 0x%8.8x: %s %s " ,
type_die - > GetOffset ( ) ,
DW_TAG_value_to_name ( type_die - > Tag ( ) ) ,
type_die - > GetName ( this , dwarf_cu ) ) ;
}
else
return type ;
}
return NULL ;
}
CompileUnit *
SymbolFileDWARF : : GetCompUnitForDWARFCompUnit ( DWARFCompileUnit * dwarf_cu , uint32_t cu_idx )
{
// Check if the symbol vendor already knows about this compile unit?
if ( dwarf_cu - > GetUserData ( ) = = NULL )
{
// The symbol vendor doesn't know about this compile unit, we
// need to parse and add it to the symbol vendor object.
return ParseCompileUnit ( dwarf_cu , cu_idx ) . get ( ) ;
}
return ( CompileUnit * ) dwarf_cu - > GetUserData ( ) ;
}
bool
SymbolFileDWARF : : GetFunction ( DWARFCompileUnit * dwarf_cu , const DWARFDebugInfoEntry * func_die , SymbolContext & sc )
{
sc . Clear ( false ) ;
// Check if the symbol vendor already knows about this compile unit?
sc . comp_unit = GetCompUnitForDWARFCompUnit ( dwarf_cu , UINT32_MAX ) ;
sc . function = sc . comp_unit - > FindFunctionByUID ( MakeUserID ( func_die - > GetOffset ( ) ) ) . get ( ) ;
if ( sc . function = = NULL )
sc . function = ParseCompileUnitFunction ( sc , dwarf_cu , func_die ) ;
if ( sc . function )
{
sc . module_sp = sc . function - > CalculateSymbolContextModule ( ) ;
return true ;
}
return false ;
}
2015-07-03 12:57:06 -04:00
void
SymbolFileDWARF : : UpdateExternalModuleListIfNeeded ( )
{
if ( m_fetched_external_modules )
return ;
m_fetched_external_modules = true ;
DWARFDebugInfo * debug_info = DebugInfo ( ) ;
debug_info - > GetNumCompileUnits ( ) ;
const uint32_t num_compile_units = GetNumCompileUnits ( ) ;
for ( uint32_t cu_idx = 0 ; cu_idx < num_compile_units ; + + cu_idx )
{
DWARFCompileUnit * dwarf_cu = debug_info - > GetCompileUnitAtIndex ( cu_idx ) ;
const DWARFDebugInfoEntry * die = dwarf_cu - > GetCompileUnitDIEOnly ( ) ;
if ( die & & die - > HasChildren ( ) = = false )
{
const uint64_t name_strp = die - > GetAttributeValueAsUnsigned ( this , dwarf_cu , DW_AT_name , UINT64_MAX ) ;
const uint64_t dwo_path_strp = die - > GetAttributeValueAsUnsigned ( this , dwarf_cu , DW_AT_GNU_dwo_name , UINT64_MAX ) ;
if ( name_strp ! = UINT64_MAX )
{
if ( m_external_type_modules . find ( dwo_path_strp ) = = m_external_type_modules . end ( ) )
{
const char * name = get_debug_str_data ( ) . PeekCStr ( name_strp ) ;
const char * dwo_path = get_debug_str_data ( ) . PeekCStr ( dwo_path_strp ) ;
if ( name | | dwo_path )
{
ModuleSP module_sp ;
if ( dwo_path )
{
ModuleSpec dwo_module_spec ;
dwo_module_spec . GetFileSpec ( ) . SetFile ( dwo_path , false ) ;
dwo_module_spec . GetArchitecture ( ) = m_obj_file - > GetModule ( ) - > GetArchitecture ( ) ;
//printf ("Loading dwo = '%s'\n", dwo_path);
Error error = ModuleList : : GetSharedModule ( dwo_module_spec , module_sp , NULL , NULL , NULL ) ;
}
if ( dwo_path_strp ! = LLDB_INVALID_UID )
{
m_external_type_modules [ dwo_path_strp ] = ClangModuleInfo { ConstString ( name ) , module_sp } ;
}
else
{
// This hack should be removed promptly once clang emits both.
m_external_type_modules [ name_strp ] = ClangModuleInfo { ConstString ( name ) , module_sp } ;
}
}
}
}
}
}
}
2015-02-08 20:44:09 -05:00
SymbolFileDWARF : : GlobalVariableMap &
SymbolFileDWARF : : GetGlobalAranges ( )
{
if ( ! m_global_aranges_ap )
{
m_global_aranges_ap . reset ( new GlobalVariableMap ( ) ) ;
ModuleSP module_sp = GetObjectFile ( ) - > GetModule ( ) ;
if ( module_sp )
{
const size_t num_cus = module_sp - > GetNumCompileUnits ( ) ;
for ( size_t i = 0 ; i < num_cus ; + + i )
{
CompUnitSP cu_sp = module_sp - > GetCompileUnitAtIndex ( i ) ;
if ( cu_sp )
{
VariableListSP globals_sp = cu_sp - > GetVariableList ( true ) ;
if ( globals_sp )
{
const size_t num_globals = globals_sp - > GetSize ( ) ;
for ( size_t g = 0 ; g < num_globals ; + + g )
{
VariableSP var_sp = globals_sp - > GetVariableAtIndex ( g ) ;
if ( var_sp & & ! var_sp - > GetLocationIsConstantValueData ( ) )
{
const DWARFExpression & location = var_sp - > LocationExpression ( ) ;
Value location_result ;
Error error ;
if ( location . Evaluate ( NULL , NULL , NULL , LLDB_INVALID_ADDRESS , NULL , location_result , & error ) )
{
if ( location_result . GetValueType ( ) = = Value : : eValueTypeFileAddress )
{
lldb : : addr_t file_addr = location_result . GetScalar ( ) . ULongLong ( ) ;
lldb : : addr_t byte_size = 1 ;
if ( var_sp - > GetType ( ) )
byte_size = var_sp - > GetType ( ) - > GetByteSize ( ) ;
m_global_aranges_ap - > Append ( GlobalVariableMap : : Entry ( file_addr , byte_size , var_sp . get ( ) ) ) ;
}
}
}
}
}
}
}
}
m_global_aranges_ap - > Sort ( ) ;
}
return * m_global_aranges_ap ;
}
2013-08-23 13:46:38 -04:00
uint32_t
SymbolFileDWARF : : ResolveSymbolContext ( const Address & so_addr , uint32_t resolve_scope , SymbolContext & sc )
{
Timer scoped_timer ( __PRETTY_FUNCTION__ ,
" SymbolFileDWARF::ResolveSymbolContext (so_addr = { section = %p, offset = 0x% " PRIx64 " }, resolve_scope = 0x%8.8x) " ,
2014-11-25 16:00:58 -05:00
static_cast < void * > ( so_addr . GetSection ( ) . get ( ) ) ,
so_addr . GetOffset ( ) , resolve_scope ) ;
2013-08-23 13:46:38 -04:00
uint32_t resolved = 0 ;
2015-02-08 20:44:09 -05:00
if ( resolve_scope & ( eSymbolContextCompUnit |
eSymbolContextFunction |
eSymbolContextBlock |
eSymbolContextLineEntry |
eSymbolContextVariable ) )
2013-08-23 13:46:38 -04:00
{
lldb : : addr_t file_vm_addr = so_addr . GetFileAddress ( ) ;
DWARFDebugInfo * debug_info = DebugInfo ( ) ;
if ( debug_info )
{
const dw_offset_t cu_offset = debug_info - > GetCompileUnitAranges ( ) . FindAddress ( file_vm_addr ) ;
2015-02-08 20:44:09 -05:00
if ( cu_offset = = DW_INVALID_OFFSET )
{
// Global variables are not in the compile unit address ranges. The only way to
// currently find global variables is to iterate over the .debug_pubnames or the
// __apple_names table and find all items in there that point to DW_TAG_variable
// DIEs and then find the address that matches.
if ( resolve_scope & eSymbolContextVariable )
{
GlobalVariableMap & map = GetGlobalAranges ( ) ;
const GlobalVariableMap : : Entry * entry = map . FindEntryThatContains ( file_vm_addr ) ;
if ( entry & & entry - > data )
{
Variable * variable = entry - > data ;
SymbolContextScope * scc = variable - > GetSymbolContextScope ( ) ;
if ( scc )
{
scc - > CalculateSymbolContext ( & sc ) ;
sc . variable = variable ;
}
return sc . GetResolvedMask ( ) ;
}
}
}
else
2013-08-23 13:46:38 -04:00
{
uint32_t cu_idx = DW_INVALID_INDEX ;
DWARFCompileUnit * dwarf_cu = debug_info - > GetCompileUnit ( cu_offset , & cu_idx ) . get ( ) ;
if ( dwarf_cu )
{
sc . comp_unit = GetCompUnitForDWARFCompUnit ( dwarf_cu , cu_idx ) ;
if ( sc . comp_unit )
{
resolved | = eSymbolContextCompUnit ;
bool force_check_line_table = false ;
if ( resolve_scope & ( eSymbolContextFunction | eSymbolContextBlock ) )
{
DWARFDebugInfoEntry * function_die = NULL ;
DWARFDebugInfoEntry * block_die = NULL ;
if ( resolve_scope & eSymbolContextBlock )
{
dwarf_cu - > LookupAddress ( file_vm_addr , & function_die , & block_die ) ;
}
else
{
dwarf_cu - > LookupAddress ( file_vm_addr , & function_die , NULL ) ;
}
if ( function_die ! = NULL )
{
sc . function = sc . comp_unit - > FindFunctionByUID ( MakeUserID ( function_die - > GetOffset ( ) ) ) . get ( ) ;
if ( sc . function = = NULL )
sc . function = ParseCompileUnitFunction ( sc , dwarf_cu , function_die ) ;
}
else
{
// We might have had a compile unit that had discontiguous
// address ranges where the gaps are symbols that don't have
// any debug info. Discontiguous compile unit address ranges
// should only happen when there aren't other functions from
// other compile units in these gaps. This helps keep the size
// of the aranges down.
force_check_line_table = true ;
}
if ( sc . function ! = NULL )
{
resolved | = eSymbolContextFunction ;
if ( resolve_scope & eSymbolContextBlock )
{
Block & block = sc . function - > GetBlock ( true ) ;
if ( block_die ! = NULL )
sc . block = block . FindBlockByID ( MakeUserID ( block_die - > GetOffset ( ) ) ) ;
else
sc . block = block . FindBlockByID ( MakeUserID ( function_die - > GetOffset ( ) ) ) ;
if ( sc . block )
resolved | = eSymbolContextBlock ;
}
}
}
if ( ( resolve_scope & eSymbolContextLineEntry ) | | force_check_line_table )
{
LineTable * line_table = sc . comp_unit - > GetLineTable ( ) ;
if ( line_table ! = NULL )
{
// And address that makes it into this function should be in terms
// of this debug file if there is no debug map, or it will be an
// address in the .o file which needs to be fixed up to be in terms
// of the debug map executable. Either way, calling FixupAddress()
// will work for us.
Address exe_so_addr ( so_addr ) ;
if ( FixupAddress ( exe_so_addr ) )
{
if ( line_table - > FindLineEntryByAddress ( exe_so_addr , sc . line_entry ) )
{
resolved | = eSymbolContextLineEntry ;
}
}
}
}
if ( force_check_line_table & & ! ( resolved & eSymbolContextLineEntry ) )
{
// We might have had a compile unit that had discontiguous
// address ranges where the gaps are symbols that don't have
// any debug info. Discontiguous compile unit address ranges
// should only happen when there aren't other functions from
// other compile units in these gaps. This helps keep the size
// of the aranges down.
sc . comp_unit = NULL ;
resolved & = ~ eSymbolContextCompUnit ;
}
}
else
{
GetObjectFile ( ) - > GetModule ( ) - > ReportWarning ( " 0x%8.8x: compile unit %u failed to create a valid lldb_private::CompileUnit class. " ,
cu_offset ,
cu_idx ) ;
}
}
}
}
}
return resolved ;
}
uint32_t
SymbolFileDWARF : : ResolveSymbolContext ( const FileSpec & file_spec , uint32_t line , bool check_inlines , uint32_t resolve_scope , SymbolContextList & sc_list )
{
const uint32_t prev_size = sc_list . GetSize ( ) ;
if ( resolve_scope & eSymbolContextCompUnit )
{
DWARFDebugInfo * debug_info = DebugInfo ( ) ;
if ( debug_info )
{
uint32_t cu_idx ;
DWARFCompileUnit * dwarf_cu = NULL ;
for ( cu_idx = 0 ; ( dwarf_cu = debug_info - > GetCompileUnitAtIndex ( cu_idx ) ) ! = NULL ; + + cu_idx )
{
CompileUnit * dc_cu = GetCompUnitForDWARFCompUnit ( dwarf_cu , cu_idx ) ;
2013-11-06 11:48:53 -05:00
const bool full_match = ( bool ) file_spec . GetDirectory ( ) ;
2013-08-23 13:46:38 -04:00
bool file_spec_matches_cu_file_spec = dc_cu ! = NULL & & FileSpec : : Equal ( file_spec , * dc_cu , full_match ) ;
if ( check_inlines | | file_spec_matches_cu_file_spec )
{
SymbolContext sc ( m_obj_file - > GetModule ( ) ) ;
sc . comp_unit = GetCompUnitForDWARFCompUnit ( dwarf_cu , cu_idx ) ;
if ( sc . comp_unit )
{
uint32_t file_idx = UINT32_MAX ;
// If we are looking for inline functions only and we don't
// find it in the support files, we are done.
if ( check_inlines )
{
file_idx = sc . comp_unit - > GetSupportFiles ( ) . FindFileIndex ( 1 , file_spec , true ) ;
if ( file_idx = = UINT32_MAX )
continue ;
}
if ( line ! = 0 )
{
LineTable * line_table = sc . comp_unit - > GetLineTable ( ) ;
if ( line_table ! = NULL & & line ! = 0 )
{
// We will have already looked up the file index if
// we are searching for inline entries.
if ( ! check_inlines )
file_idx = sc . comp_unit - > GetSupportFiles ( ) . FindFileIndex ( 1 , file_spec , true ) ;
if ( file_idx ! = UINT32_MAX )
{
uint32_t found_line ;
uint32_t line_idx = line_table - > FindLineEntryIndexByFileIndex ( 0 , file_idx , line , false , & sc . line_entry ) ;
found_line = sc . line_entry . line ;
while ( line_idx ! = UINT32_MAX )
{
sc . function = NULL ;
sc . block = NULL ;
if ( resolve_scope & ( eSymbolContextFunction | eSymbolContextBlock ) )
{
const lldb : : addr_t file_vm_addr = sc . line_entry . range . GetBaseAddress ( ) . GetFileAddress ( ) ;
if ( file_vm_addr ! = LLDB_INVALID_ADDRESS )
{
DWARFDebugInfoEntry * function_die = NULL ;
DWARFDebugInfoEntry * block_die = NULL ;
dwarf_cu - > LookupAddress ( file_vm_addr , & function_die , resolve_scope & eSymbolContextBlock ? & block_die : NULL ) ;
if ( function_die ! = NULL )
{
sc . function = sc . comp_unit - > FindFunctionByUID ( MakeUserID ( function_die - > GetOffset ( ) ) ) . get ( ) ;
if ( sc . function = = NULL )
sc . function = ParseCompileUnitFunction ( sc , dwarf_cu , function_die ) ;
}
if ( sc . function ! = NULL )
{
Block & block = sc . function - > GetBlock ( true ) ;
if ( block_die ! = NULL )
sc . block = block . FindBlockByID ( MakeUserID ( block_die - > GetOffset ( ) ) ) ;
2015-02-06 16:38:51 -05:00
else if ( function_die ! = NULL )
2013-08-23 13:46:38 -04:00
sc . block = block . FindBlockByID ( MakeUserID ( function_die - > GetOffset ( ) ) ) ;
}
}
}
sc_list . Append ( sc ) ;
line_idx = line_table - > FindLineEntryIndexByFileIndex ( line_idx + 1 , file_idx , found_line , true , & sc . line_entry ) ;
}
}
}
else if ( file_spec_matches_cu_file_spec & & ! check_inlines )
{
// only append the context if we aren't looking for inline call sites
// by file and line and if the file spec matches that of the compile unit
sc_list . Append ( sc ) ;
}
}
else if ( file_spec_matches_cu_file_spec & & ! check_inlines )
{
// only append the context if we aren't looking for inline call sites
// by file and line and if the file spec matches that of the compile unit
sc_list . Append ( sc ) ;
}
if ( ! check_inlines )
break ;
}
}
}
}
}
return sc_list . GetSize ( ) - prev_size ;
}
void
SymbolFileDWARF : : Index ( )
{
if ( m_indexed )
return ;
m_indexed = true ;
Timer scoped_timer ( __PRETTY_FUNCTION__ ,
" SymbolFileDWARF::Index (%s) " ,
2015-02-06 16:38:51 -05:00
GetObjectFile ( ) - > GetFileSpec ( ) . GetFilename ( ) . AsCString ( " <Unknown> " ) ) ;
2013-08-23 13:46:38 -04:00
DWARFDebugInfo * debug_info = DebugInfo ( ) ;
if ( debug_info )
{
uint32_t cu_idx = 0 ;
const uint32_t num_compile_units = GetNumCompileUnits ( ) ;
for ( cu_idx = 0 ; cu_idx < num_compile_units ; + + cu_idx )
{
DWARFCompileUnit * dwarf_cu = debug_info - > GetCompileUnitAtIndex ( cu_idx ) ;
bool clear_dies = dwarf_cu - > ExtractDIEsIfNeeded ( false ) > 1 ;
dwarf_cu - > Index ( cu_idx ,
m_function_basename_index ,
m_function_fullname_index ,
m_function_method_index ,
m_function_selector_index ,
m_objc_class_selectors_index ,
m_global_index ,
m_type_index ,
m_namespace_index ) ;
// Keep memory down by clearing DIEs if this generate function
// caused them to be parsed
if ( clear_dies )
dwarf_cu - > ClearDIEs ( true ) ;
}
m_function_basename_index . Finalize ( ) ;
m_function_fullname_index . Finalize ( ) ;
m_function_method_index . Finalize ( ) ;
m_function_selector_index . Finalize ( ) ;
m_objc_class_selectors_index . Finalize ( ) ;
m_global_index . Finalize ( ) ;
m_type_index . Finalize ( ) ;
m_namespace_index . Finalize ( ) ;
# if defined (ENABLE_DEBUG_PRINTF)
StreamFile s ( stdout , false ) ;
s . Printf ( " DWARF index for '%s': " ,
GetObjectFile ( ) - > GetFileSpec ( ) . GetPath ( ) . c_str ( ) ) ;
s . Printf ( " \n Function basenames: \n " ) ; m_function_basename_index . Dump ( & s ) ;
s . Printf ( " \n Function fullnames: \n " ) ; m_function_fullname_index . Dump ( & s ) ;
s . Printf ( " \n Function methods: \n " ) ; m_function_method_index . Dump ( & s ) ;
s . Printf ( " \n Function selectors: \n " ) ; m_function_selector_index . Dump ( & s ) ;
s . Printf ( " \n Objective C class selectors: \n " ) ; m_objc_class_selectors_index . Dump ( & s ) ;
s . Printf ( " \n Globals and statics: \n " ) ; m_global_index . Dump ( & s ) ;
s . Printf ( " \n Types: \n " ) ; m_type_index . Dump ( & s ) ;
s . Printf ( " \n Namepaces: \n " ) ; m_namespace_index . Dump ( & s ) ;
# endif
}
}
bool
SymbolFileDWARF : : NamespaceDeclMatchesThisSymbolFile ( const ClangNamespaceDecl * namespace_decl )
{
if ( namespace_decl = = NULL )
{
// Invalid namespace decl which means we aren't matching only things
// in this symbol file, so return true to indicate it matches this
// symbol file.
return true ;
}
clang : : ASTContext * namespace_ast = namespace_decl - > GetASTContext ( ) ;
if ( namespace_ast = = NULL )
return true ; // No AST in the "namespace_decl", return true since it
// could then match any symbol file, including this one
if ( namespace_ast = = GetClangASTContext ( ) . getASTContext ( ) )
return true ; // The ASTs match, return true
// The namespace AST was valid, and it does not match...
Log * log ( LogChannelDWARF : : GetLogIfAll ( DWARF_LOG_LOOKUPS ) ) ;
if ( log )
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log , " Valid namespace does not match symbol file " ) ;
return false ;
}
bool
SymbolFileDWARF : : DIEIsInNamespace ( const ClangNamespaceDecl * namespace_decl ,
DWARFCompileUnit * cu ,
const DWARFDebugInfoEntry * die )
{
2014-11-25 16:00:58 -05:00
// No namespace specified, so the answer is
2013-08-23 13:46:38 -04:00
if ( namespace_decl = = NULL )
return true ;
Log * log ( LogChannelDWARF : : GetLogIfAll ( DWARF_LOG_LOOKUPS ) ) ;
const DWARFDebugInfoEntry * decl_ctx_die = NULL ;
clang : : DeclContext * die_clang_decl_ctx = GetClangDeclContextContainingDIE ( cu , die , & decl_ctx_die ) ;
if ( decl_ctx_die )
{
clang : : NamespaceDecl * clang_namespace_decl = namespace_decl - > GetNamespaceDecl ( ) ;
if ( clang_namespace_decl )
{
if ( decl_ctx_die - > Tag ( ) ! = DW_TAG_namespace )
{
if ( log )
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log , " Found a match, but its parent is not a namespace " ) ;
return false ;
}
if ( clang_namespace_decl = = die_clang_decl_ctx )
return true ;
else
return false ;
}
else
{
// We have a namespace_decl that was not NULL but it contained
// a NULL "clang::NamespaceDecl", so this means the global namespace
2014-11-25 16:00:58 -05:00
// So as long the contained decl context DIE isn't a namespace
2013-08-23 13:46:38 -04:00
// we should be ok.
if ( decl_ctx_die - > Tag ( ) ! = DW_TAG_namespace )
return true ;
}
}
if ( log )
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log , " Found a match, but its parent doesn't exist " ) ;
return false ;
}
uint32_t
SymbolFileDWARF : : FindGlobalVariables ( const ConstString & name , const lldb_private : : ClangNamespaceDecl * namespace_decl , bool append , uint32_t max_matches , VariableList & variables )
{
Log * log ( LogChannelDWARF : : GetLogIfAll ( DWARF_LOG_LOOKUPS ) ) ;
if ( log )
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::FindGlobalVariables (name= \" %s \" , namespace_decl=%p, append=%u, max_matches=%u, variables) " ,
name . GetCString ( ) ,
2014-11-25 16:00:58 -05:00
static_cast < const void * > ( namespace_decl ) ,
append , max_matches ) ;
2013-08-23 13:46:38 -04:00
if ( ! NamespaceDeclMatchesThisSymbolFile ( namespace_decl ) )
2013-11-06 11:48:53 -05:00
return 0 ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
DWARFDebugInfo * info = DebugInfo ( ) ;
if ( info = = NULL )
return 0 ;
// 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 ( ) ;
DIEArray die_offsets ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( m_using_apple_tables )
{
if ( m_apple_names_ap . get ( ) )
{
const char * name_cstr = name . GetCString ( ) ;
2015-02-06 16:38:51 -05:00
llvm : : StringRef basename ;
llvm : : StringRef context ;
2014-11-25 16:00:58 -05:00
2015-02-06 16:38:51 -05:00
if ( ! CPPLanguageRuntime : : ExtractContextAndIdentifier ( name_cstr , context , basename ) )
basename = name_cstr ;
2014-11-25 16:00:58 -05:00
2015-02-06 16:38:51 -05:00
m_apple_names_ap - > FindByName ( basename . data ( ) , die_offsets ) ;
2013-08-23 13:46:38 -04:00
}
}
else
{
// Index the DWARF if we haven't already
if ( ! m_indexed )
Index ( ) ;
m_global_index . Find ( name , die_offsets ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
const size_t num_die_matches = die_offsets . size ( ) ;
if ( num_die_matches )
{
SymbolContext sc ;
sc . module_sp = m_obj_file - > GetModule ( ) ;
assert ( sc . module_sp ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
DWARFDebugInfo * debug_info = DebugInfo ( ) ;
DWARFCompileUnit * dwarf_cu = NULL ;
const DWARFDebugInfoEntry * die = NULL ;
bool done = false ;
for ( size_t i = 0 ; i < num_die_matches & & ! done ; + + i )
{
const dw_offset_t die_offset = die_offsets [ i ] ;
die = debug_info - > GetDIEPtrWithCompileUnitHint ( die_offset , & dwarf_cu ) ;
if ( die )
{
switch ( die - > Tag ( ) )
{
default :
case DW_TAG_subprogram :
case DW_TAG_inlined_subroutine :
case DW_TAG_try_block :
case DW_TAG_catch_block :
break ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
case DW_TAG_variable :
{
sc . comp_unit = GetCompUnitForDWARFCompUnit ( dwarf_cu , UINT32_MAX ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( namespace_decl & & ! DIEIsInNamespace ( namespace_decl , dwarf_cu , die ) )
continue ;
ParseVariables ( sc , dwarf_cu , LLDB_INVALID_ADDRESS , die , false , false , & variables ) ;
if ( variables . GetSize ( ) - original_size > = max_matches )
done = true ;
}
break ;
}
}
else
{
if ( m_using_apple_tables )
{
GetObjectFile ( ) - > GetModule ( ) - > ReportErrorIfModifyDetected ( " the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s') \n " ,
die_offset , name . GetCString ( ) ) ;
}
}
}
}
// Return the number of variable that were appended to the list
const uint32_t num_matches = variables . GetSize ( ) - original_size ;
if ( log & & num_matches > 0 )
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::FindGlobalVariables (name= \" %s \" , namespace_decl=%p, append=%u, max_matches=%u, variables) => %u " ,
2014-11-25 16:00:58 -05:00
name . GetCString ( ) ,
static_cast < const void * > ( namespace_decl ) ,
append , max_matches ,
2013-08-23 13:46:38 -04:00
num_matches ) ;
}
return num_matches ;
}
uint32_t
SymbolFileDWARF : : FindGlobalVariables ( const RegularExpression & regex , bool append , uint32_t max_matches , VariableList & variables )
{
Log * log ( LogChannelDWARF : : GetLogIfAll ( DWARF_LOG_LOOKUPS ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( log )
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::FindGlobalVariables (regex= \" %s \" , append=%u, max_matches=%u, variables) " ,
2014-11-25 16:00:58 -05:00
regex . GetText ( ) , append ,
2013-08-23 13:46:38 -04:00
max_matches ) ;
}
DWARFDebugInfo * info = DebugInfo ( ) ;
if ( info = = NULL )
return 0 ;
// 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 ( ) ;
DIEArray die_offsets ;
if ( m_using_apple_tables )
{
if ( m_apple_names_ap . get ( ) )
{
DWARFMappedHash : : DIEInfoArray hash_data_array ;
if ( m_apple_names_ap - > AppendAllDIEsThatMatchingRegex ( regex , hash_data_array ) )
DWARFMappedHash : : ExtractDIEArray ( hash_data_array , die_offsets ) ;
}
}
else
{
// Index the DWARF if we haven't already
if ( ! m_indexed )
Index ( ) ;
m_global_index . Find ( regex , die_offsets ) ;
}
SymbolContext sc ;
sc . module_sp = m_obj_file - > GetModule ( ) ;
assert ( sc . module_sp ) ;
DWARFCompileUnit * dwarf_cu = NULL ;
const DWARFDebugInfoEntry * die = NULL ;
const size_t num_matches = die_offsets . size ( ) ;
if ( num_matches )
{
DWARFDebugInfo * debug_info = DebugInfo ( ) ;
for ( size_t i = 0 ; i < num_matches ; + + i )
{
const dw_offset_t die_offset = die_offsets [ i ] ;
die = debug_info - > GetDIEPtrWithCompileUnitHint ( die_offset , & dwarf_cu ) ;
if ( die )
{
sc . comp_unit = GetCompUnitForDWARFCompUnit ( dwarf_cu , UINT32_MAX ) ;
ParseVariables ( sc , dwarf_cu , LLDB_INVALID_ADDRESS , die , false , false , & variables ) ;
if ( variables . GetSize ( ) - original_size > = max_matches )
break ;
}
else
{
if ( m_using_apple_tables )
{
GetObjectFile ( ) - > GetModule ( ) - > ReportErrorIfModifyDetected ( " the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for regex '%s') \n " ,
die_offset , regex . GetText ( ) ) ;
}
}
}
}
// Return the number of variable that were appended to the list
return variables . GetSize ( ) - original_size ;
}
bool
SymbolFileDWARF : : ResolveFunction ( dw_offset_t die_offset ,
DWARFCompileUnit * & dwarf_cu ,
2015-07-03 12:57:06 -04:00
bool include_inlines ,
2013-08-23 13:46:38 -04:00
SymbolContextList & sc_list )
{
const DWARFDebugInfoEntry * die = DebugInfo ( ) - > GetDIEPtrWithCompileUnitHint ( die_offset , & dwarf_cu ) ;
2015-07-03 12:57:06 -04:00
return ResolveFunction ( dwarf_cu , die , include_inlines , sc_list ) ;
2013-08-23 13:46:38 -04:00
}
bool
SymbolFileDWARF : : ResolveFunction ( DWARFCompileUnit * cu ,
const DWARFDebugInfoEntry * die ,
2015-07-03 12:57:06 -04:00
bool include_inlines ,
2013-08-23 13:46:38 -04:00
SymbolContextList & sc_list )
{
SymbolContext sc ;
if ( die = = NULL )
return false ;
// If we were passed a die that is not a function, just return false...
2015-07-03 12:57:06 -04:00
if ( ! ( die - > Tag ( ) = = DW_TAG_subprogram | | ( include_inlines & & die - > Tag ( ) = = DW_TAG_inlined_subroutine ) ) )
2013-08-23 13:46:38 -04:00
return false ;
const DWARFDebugInfoEntry * inlined_die = NULL ;
if ( die - > Tag ( ) = = DW_TAG_inlined_subroutine )
{
inlined_die = die ;
while ( ( die = die - > GetParent ( ) ) ! = NULL )
{
if ( die - > Tag ( ) = = DW_TAG_subprogram )
break ;
}
}
2015-02-06 16:38:51 -05:00
assert ( die & & die - > Tag ( ) = = DW_TAG_subprogram ) ;
2013-08-23 13:46:38 -04:00
if ( GetFunction ( cu , die , sc ) )
{
Address addr ;
// Parse all blocks if needed
if ( inlined_die )
{
2015-02-08 20:44:09 -05:00
Block & function_block = sc . function - > GetBlock ( true ) ;
sc . block = function_block . FindBlockByID ( MakeUserID ( inlined_die - > GetOffset ( ) ) ) ;
if ( sc . block = = NULL )
sc . block = function_block . FindBlockByID ( inlined_die - > GetOffset ( ) ) ;
if ( sc . block = = NULL | | sc . block - > GetStartAddress ( addr ) = = false )
2013-08-23 13:46:38 -04:00
addr . Clear ( ) ;
}
else
{
sc . block = NULL ;
addr = sc . function - > GetAddressRange ( ) . GetBaseAddress ( ) ;
}
if ( addr . IsValid ( ) )
{
sc_list . Append ( sc ) ;
return true ;
}
}
return false ;
}
void
SymbolFileDWARF : : FindFunctions ( const ConstString & name ,
const NameToDIE & name_to_die ,
2015-07-03 12:57:06 -04:00
bool include_inlines ,
2013-08-23 13:46:38 -04:00
SymbolContextList & sc_list )
{
DIEArray die_offsets ;
if ( name_to_die . Find ( name , die_offsets ) )
{
2015-07-03 12:57:06 -04:00
ParseFunctions ( die_offsets , include_inlines , sc_list ) ;
2013-08-23 13:46:38 -04:00
}
}
void
SymbolFileDWARF : : FindFunctions ( const RegularExpression & regex ,
const NameToDIE & name_to_die ,
2015-07-03 12:57:06 -04:00
bool include_inlines ,
2013-08-23 13:46:38 -04:00
SymbolContextList & sc_list )
{
DIEArray die_offsets ;
if ( name_to_die . Find ( regex , die_offsets ) )
{
2015-07-03 12:57:06 -04:00
ParseFunctions ( die_offsets , include_inlines , sc_list ) ;
2013-08-23 13:46:38 -04:00
}
}
void
SymbolFileDWARF : : FindFunctions ( const RegularExpression & regex ,
const DWARFMappedHash : : MemoryTable & memory_table ,
2015-07-03 12:57:06 -04:00
bool include_inlines ,
2013-08-23 13:46:38 -04:00
SymbolContextList & sc_list )
{
DIEArray die_offsets ;
DWARFMappedHash : : DIEInfoArray hash_data_array ;
if ( memory_table . AppendAllDIEsThatMatchingRegex ( regex , hash_data_array ) )
{
DWARFMappedHash : : ExtractDIEArray ( hash_data_array , die_offsets ) ;
2015-07-03 12:57:06 -04:00
ParseFunctions ( die_offsets , include_inlines , sc_list ) ;
2013-08-23 13:46:38 -04:00
}
}
void
SymbolFileDWARF : : ParseFunctions ( const DIEArray & die_offsets ,
2015-07-03 12:57:06 -04:00
bool include_inlines ,
2013-08-23 13:46:38 -04:00
SymbolContextList & sc_list )
{
const size_t num_matches = die_offsets . size ( ) ;
if ( num_matches )
{
DWARFCompileUnit * dwarf_cu = NULL ;
for ( size_t i = 0 ; i < num_matches ; + + i )
{
const dw_offset_t die_offset = die_offsets [ i ] ;
2015-07-03 12:57:06 -04:00
ResolveFunction ( die_offset , dwarf_cu , include_inlines , sc_list ) ;
2013-08-23 13:46:38 -04:00
}
}
}
bool
SymbolFileDWARF : : FunctionDieMatchesPartialName ( const DWARFDebugInfoEntry * die ,
const DWARFCompileUnit * dwarf_cu ,
uint32_t name_type_mask ,
const char * partial_name ,
const char * base_name_start ,
const char * base_name_end )
{
// If we are looking only for methods, throw away all the ones that are or aren't in C++ classes:
if ( name_type_mask = = eFunctionNameTypeMethod | | name_type_mask = = eFunctionNameTypeBase )
{
clang : : DeclContext * containing_decl_ctx = GetClangDeclContextContainingDIEOffset ( die - > GetOffset ( ) ) ;
if ( ! containing_decl_ctx )
return false ;
bool is_cxx_method = DeclKindIsCXXClass ( containing_decl_ctx - > getDeclKind ( ) ) ;
if ( name_type_mask = = eFunctionNameTypeMethod )
{
if ( is_cxx_method = = false )
return false ;
}
if ( name_type_mask = = eFunctionNameTypeBase )
{
if ( is_cxx_method = = true )
return false ;
}
}
// Now we need to check whether the name we got back for this type matches the extra specifications
// that were in the name we're looking up:
if ( base_name_start ! = partial_name | | * base_name_end ! = ' \0 ' )
{
// First see if the stuff to the left matches the full name. To do that let's see if
// we can pull out the mips linkage name attribute:
Mangled best_name ;
DWARFDebugInfoEntry : : Attributes attributes ;
DWARFFormValue form_value ;
die - > GetAttributes ( this , dwarf_cu , NULL , attributes ) ;
uint32_t idx = attributes . FindAttributeIndex ( DW_AT_MIPS_linkage_name ) ;
if ( idx = = UINT32_MAX )
idx = attributes . FindAttributeIndex ( DW_AT_linkage_name ) ;
if ( idx ! = UINT32_MAX )
{
if ( attributes . ExtractFormValueAtIndex ( this , idx , form_value ) )
{
const char * mangled_name = form_value . AsCString ( & get_debug_str_data ( ) ) ;
if ( mangled_name )
best_name . SetValue ( ConstString ( mangled_name ) , true ) ;
}
}
if ( ! best_name )
{
idx = attributes . FindAttributeIndex ( DW_AT_name ) ;
if ( idx ! = UINT32_MAX & & attributes . ExtractFormValueAtIndex ( this , idx , form_value ) )
{
const char * name = form_value . AsCString ( & get_debug_str_data ( ) ) ;
best_name . SetValue ( ConstString ( name ) , false ) ;
}
}
2015-09-06 10:32:30 -04:00
const LanguageType cu_language = const_cast < DWARFCompileUnit * > ( dwarf_cu ) - > GetLanguageType ( ) ;
if ( best_name . GetDemangledName ( cu_language ) )
2013-08-23 13:46:38 -04:00
{
2015-09-06 10:32:30 -04:00
const char * demangled = best_name . GetDemangledName ( cu_language ) . GetCString ( ) ;
2013-08-23 13:46:38 -04:00
if ( demangled )
{
std : : string name_no_parens ( partial_name , base_name_end - partial_name ) ;
const char * partial_in_demangled = strstr ( demangled , name_no_parens . c_str ( ) ) ;
if ( partial_in_demangled = = NULL )
return false ;
else
{
// Sort out the case where our name is something like "Process::Destroy" and the match is
// "SBProcess::Destroy" - that shouldn't be a match. We should really always match on
// namespace boundaries...
if ( partial_name [ 0 ] = = ' : ' & & partial_name [ 1 ] = = ' : ' )
{
// The partial name was already on a namespace boundary so all matches are good.
return true ;
}
else if ( partial_in_demangled = = demangled )
{
// They both start the same, so this is an good match.
return true ;
}
else
{
if ( partial_in_demangled - demangled = = 1 )
{
// Only one character difference, can't be a namespace boundary...
return false ;
}
else if ( * ( partial_in_demangled - 1 ) = = ' : ' & & * ( partial_in_demangled - 2 ) = = ' : ' )
{
// We are on a namespace boundary, so this is also good.
return true ;
}
else
return false ;
}
}
}
}
}
return true ;
}
uint32_t
SymbolFileDWARF : : FindFunctions ( const ConstString & name ,
const lldb_private : : ClangNamespaceDecl * namespace_decl ,
uint32_t name_type_mask ,
bool include_inlines ,
bool append ,
SymbolContextList & sc_list )
{
Timer scoped_timer ( __PRETTY_FUNCTION__ ,
" SymbolFileDWARF::FindFunctions (name = '%s') " ,
name . AsCString ( ) ) ;
// eFunctionNameTypeAuto should be pre-resolved by a call to Module::PrepareForFunctionNameLookup()
assert ( ( name_type_mask & eFunctionNameTypeAuto ) = = 0 ) ;
Log * log ( LogChannelDWARF : : GetLogIfAll ( DWARF_LOG_LOOKUPS ) ) ;
if ( log )
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::FindFunctions (name= \" %s \" , name_type_mask=0x%x, append=%u, sc_list) " ,
name . GetCString ( ) ,
name_type_mask ,
append ) ;
}
// If we aren't appending the results to this list, then clear the list
if ( ! append )
sc_list . Clear ( ) ;
if ( ! NamespaceDeclMatchesThisSymbolFile ( namespace_decl ) )
2013-11-06 11:48:53 -05:00
return 0 ;
2013-08-23 13:46:38 -04:00
// If name is empty then we won't find anything.
if ( name . IsEmpty ( ) )
return 0 ;
// Remember how many sc_list are in the list before we search in case
// we are appending the results to a variable list.
const char * name_cstr = name . GetCString ( ) ;
const uint32_t original_size = sc_list . GetSize ( ) ;
DWARFDebugInfo * info = DebugInfo ( ) ;
if ( info = = NULL )
return 0 ;
DWARFCompileUnit * dwarf_cu = NULL ;
std : : set < const DWARFDebugInfoEntry * > resolved_dies ;
if ( m_using_apple_tables )
{
if ( m_apple_names_ap . get ( ) )
{
DIEArray die_offsets ;
uint32_t num_matches = 0 ;
if ( name_type_mask & eFunctionNameTypeFull )
{
// If they asked for the full name, match what they typed. At some point we may
// want to canonicalize this (strip double spaces, etc. For now, we just add all the
// dies that we find by exact match.
num_matches = m_apple_names_ap - > FindByName ( name_cstr , die_offsets ) ;
for ( uint32_t i = 0 ; i < num_matches ; i + + )
{
const dw_offset_t die_offset = die_offsets [ i ] ;
const DWARFDebugInfoEntry * die = info - > GetDIEPtrWithCompileUnitHint ( die_offset , & dwarf_cu ) ;
if ( die )
{
if ( namespace_decl & & ! DIEIsInNamespace ( namespace_decl , dwarf_cu , die ) )
continue ;
if ( resolved_dies . find ( die ) = = resolved_dies . end ( ) )
{
2015-07-03 12:57:06 -04:00
if ( ResolveFunction ( dwarf_cu , die , include_inlines , sc_list ) )
2013-08-23 13:46:38 -04:00
resolved_dies . insert ( die ) ;
}
}
else
{
GetObjectFile ( ) - > GetModule ( ) - > ReportErrorIfModifyDetected ( " the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s') " ,
die_offset , name_cstr ) ;
}
}
}
if ( name_type_mask & eFunctionNameTypeSelector )
{
if ( namespace_decl & & * namespace_decl )
return 0 ; // no selectors in namespaces
num_matches = m_apple_names_ap - > FindByName ( name_cstr , die_offsets ) ;
// Now make sure these are actually ObjC methods. In this case we can simply look up the name,
// and if it is an ObjC method name, we're good.
for ( uint32_t i = 0 ; i < num_matches ; i + + )
{
const dw_offset_t die_offset = die_offsets [ i ] ;
const DWARFDebugInfoEntry * die = info - > GetDIEPtrWithCompileUnitHint ( die_offset , & dwarf_cu ) ;
if ( die )
{
const char * die_name = die - > GetName ( this , dwarf_cu ) ;
if ( ObjCLanguageRuntime : : IsPossibleObjCMethodName ( die_name ) )
{
if ( resolved_dies . find ( die ) = = resolved_dies . end ( ) )
{
2015-07-03 12:57:06 -04:00
if ( ResolveFunction ( dwarf_cu , die , include_inlines , sc_list ) )
2013-08-23 13:46:38 -04:00
resolved_dies . insert ( die ) ;
}
}
}
else
{
GetObjectFile ( ) - > GetModule ( ) - > ReportError ( " the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s') " ,
die_offset , name_cstr ) ;
}
}
die_offsets . clear ( ) ;
}
if ( ( ( name_type_mask & eFunctionNameTypeMethod ) & & ! namespace_decl ) | | name_type_mask & eFunctionNameTypeBase )
{
// The apple_names table stores just the "base name" of C++ methods in the table. So we have to
// extract the base name, look that up, and if there is any other information in the name we were
// passed in we have to post-filter based on that.
// FIXME: Arrange the logic above so that we don't calculate the base name twice:
num_matches = m_apple_names_ap - > FindByName ( name_cstr , die_offsets ) ;
for ( uint32_t i = 0 ; i < num_matches ; i + + )
{
const dw_offset_t die_offset = die_offsets [ i ] ;
const DWARFDebugInfoEntry * die = info - > GetDIEPtrWithCompileUnitHint ( die_offset , & dwarf_cu ) ;
if ( die )
{
if ( namespace_decl & & ! DIEIsInNamespace ( namespace_decl , dwarf_cu , die ) )
continue ;
// If we get to here, the die is good, and we should add it:
if ( resolved_dies . find ( die ) = = resolved_dies . end ( ) )
2015-07-03 12:57:06 -04:00
if ( ResolveFunction ( dwarf_cu , die , include_inlines , sc_list ) )
2013-08-23 13:46:38 -04:00
{
bool keep_die = true ;
if ( ( name_type_mask & ( eFunctionNameTypeBase | eFunctionNameTypeMethod ) ) ! = ( eFunctionNameTypeBase | eFunctionNameTypeMethod ) )
{
// We are looking for either basenames or methods, so we need to
// trim out the ones we won't want by looking at the type
SymbolContext sc ;
if ( sc_list . GetLastContext ( sc ) )
{
if ( sc . block )
{
// We have an inlined function
}
else if ( sc . function )
{
Type * type = sc . function - > GetType ( ) ;
2013-11-06 11:48:53 -05:00
if ( type )
2013-08-23 13:46:38 -04:00
{
2013-11-06 11:48:53 -05:00
clang : : DeclContext * decl_ctx = GetClangDeclContextContainingTypeUID ( type - > GetID ( ) ) ;
if ( decl_ctx - > isRecord ( ) )
2013-08-23 13:46:38 -04:00
{
2013-11-06 11:48:53 -05:00
if ( name_type_mask & eFunctionNameTypeBase )
{
sc_list . RemoveContextAtIndex ( sc_list . GetSize ( ) - 1 ) ;
keep_die = false ;
}
}
else
{
if ( name_type_mask & eFunctionNameTypeMethod )
{
sc_list . RemoveContextAtIndex ( sc_list . GetSize ( ) - 1 ) ;
keep_die = false ;
}
2013-08-23 13:46:38 -04:00
}
}
else
{
2013-11-06 11:48:53 -05:00
GetObjectFile ( ) - > GetModule ( ) - > ReportWarning ( " function at die offset 0x%8.8x had no function type " ,
die_offset ) ;
2013-08-23 13:46:38 -04:00
}
}
}
}
if ( keep_die )
resolved_dies . insert ( die ) ;
}
}
else
{
GetObjectFile ( ) - > GetModule ( ) - > ReportErrorIfModifyDetected ( " the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s') " ,
die_offset , name_cstr ) ;
}
}
die_offsets . clear ( ) ;
}
}
}
else
{
// Index the DWARF if we haven't already
if ( ! m_indexed )
Index ( ) ;
if ( name_type_mask & eFunctionNameTypeFull )
{
2015-07-03 12:57:06 -04:00
FindFunctions ( name , m_function_fullname_index , include_inlines , sc_list ) ;
2013-08-23 13:46:38 -04:00
2013-11-06 11:48:53 -05:00
// FIXME Temporary workaround for global/anonymous namespace
2015-07-03 12:57:06 -04:00
// functions debugging FreeBSD and Linux binaries.
2013-08-23 13:46:38 -04:00
// If we didn't find any functions in the global namespace try
// looking in the basename index but ignore any returned
2015-07-03 12:57:06 -04:00
// functions that have a namespace but keep functions which
// have an anonymous namespace
// TODO: The arch in the object file isn't correct for MSVC
// binaries on windows, we should find a way to make it
// correct and handle those symbols as well.
2013-08-23 13:46:38 -04:00
if ( sc_list . GetSize ( ) = = 0 )
{
2015-07-03 12:57:06 -04:00
ArchSpec arch ;
if ( ! namespace_decl & &
GetObjectFile ( ) - > GetArchitecture ( arch ) & &
( arch . GetTriple ( ) . isOSFreeBSD ( ) | | arch . GetTriple ( ) . isOSLinux ( ) | |
arch . GetMachine ( ) = = llvm : : Triple : : hexagon ) )
2013-08-23 13:46:38 -04:00
{
2015-07-03 12:57:06 -04:00
SymbolContextList temp_sc_list ;
FindFunctions ( name , m_function_basename_index , include_inlines , temp_sc_list ) ;
2013-08-23 13:46:38 -04:00
SymbolContext sc ;
for ( uint32_t i = 0 ; i < temp_sc_list . GetSize ( ) ; i + + )
{
if ( temp_sc_list . GetContextAtIndex ( i , sc ) )
{
ConstString mangled_name = sc . GetFunctionName ( Mangled : : ePreferMangled ) ;
ConstString demangled_name = sc . GetFunctionName ( Mangled : : ePreferDemangled ) ;
2015-07-03 12:57:06 -04:00
// Mangled names on Linux and FreeBSD are of the form:
// _ZN18function_namespace13function_nameEv.
2013-08-23 13:46:38 -04:00
if ( strncmp ( mangled_name . GetCString ( ) , " _ZN " , 3 ) | |
! strncmp ( demangled_name . GetCString ( ) , " (anonymous namespace) " , 21 ) )
{
sc_list . Append ( sc ) ;
}
}
}
}
}
}
DIEArray die_offsets ;
DWARFCompileUnit * dwarf_cu = NULL ;
if ( name_type_mask & eFunctionNameTypeBase )
{
uint32_t num_base = m_function_basename_index . Find ( name , die_offsets ) ;
for ( uint32_t i = 0 ; i < num_base ; i + + )
{
const DWARFDebugInfoEntry * die = info - > GetDIEPtrWithCompileUnitHint ( die_offsets [ i ] , & dwarf_cu ) ;
if ( die )
{
if ( namespace_decl & & ! DIEIsInNamespace ( namespace_decl , dwarf_cu , die ) )
continue ;
// If we get to here, the die is good, and we should add it:
if ( resolved_dies . find ( die ) = = resolved_dies . end ( ) )
{
2015-07-03 12:57:06 -04:00
if ( ResolveFunction ( dwarf_cu , die , include_inlines , sc_list ) )
2013-08-23 13:46:38 -04:00
resolved_dies . insert ( die ) ;
}
}
}
die_offsets . clear ( ) ;
}
if ( name_type_mask & eFunctionNameTypeMethod )
{
if ( namespace_decl & & * namespace_decl )
return 0 ; // no methods in namespaces
uint32_t num_base = m_function_method_index . Find ( name , die_offsets ) ;
{
for ( uint32_t i = 0 ; i < num_base ; i + + )
{
const DWARFDebugInfoEntry * die = info - > GetDIEPtrWithCompileUnitHint ( die_offsets [ i ] , & dwarf_cu ) ;
if ( die )
{
// If we get to here, the die is good, and we should add it:
if ( resolved_dies . find ( die ) = = resolved_dies . end ( ) )
{
2015-07-03 12:57:06 -04:00
if ( ResolveFunction ( dwarf_cu , die , include_inlines , sc_list ) )
2013-08-23 13:46:38 -04:00
resolved_dies . insert ( die ) ;
}
}
}
}
die_offsets . clear ( ) ;
}
if ( ( name_type_mask & eFunctionNameTypeSelector ) & & ( ! namespace_decl | | ! * namespace_decl ) )
{
2015-07-03 12:57:06 -04:00
FindFunctions ( name , m_function_selector_index , include_inlines , sc_list ) ;
2013-08-23 13:46:38 -04:00
}
}
// Return the number of variable that were appended to the list
const uint32_t num_matches = sc_list . GetSize ( ) - original_size ;
if ( log & & num_matches > 0 )
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
2015-07-03 12:57:06 -04:00
" SymbolFileDWARF::FindFunctions (name= \" %s \" , name_type_mask=0x%x, include_inlines=%d, append=%u, sc_list) => %u " ,
2013-08-23 13:46:38 -04:00
name . GetCString ( ) ,
name_type_mask ,
2015-07-03 12:57:06 -04:00
include_inlines ,
2013-08-23 13:46:38 -04:00
append ,
num_matches ) ;
}
return num_matches ;
}
uint32_t
SymbolFileDWARF : : FindFunctions ( const RegularExpression & regex , bool include_inlines , bool append , SymbolContextList & sc_list )
{
Timer scoped_timer ( __PRETTY_FUNCTION__ ,
" SymbolFileDWARF::FindFunctions (regex = '%s') " ,
regex . GetText ( ) ) ;
Log * log ( LogChannelDWARF : : GetLogIfAll ( DWARF_LOG_LOOKUPS ) ) ;
if ( log )
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::FindFunctions (regex= \" %s \" , append=%u, sc_list) " ,
regex . GetText ( ) ,
append ) ;
}
// If we aren't appending the results to this list, then clear the list
if ( ! append )
sc_list . Clear ( ) ;
// Remember how many sc_list are in the list before we search in case
// we are appending the results to a variable list.
uint32_t original_size = sc_list . GetSize ( ) ;
if ( m_using_apple_tables )
{
if ( m_apple_names_ap . get ( ) )
2015-07-03 12:57:06 -04:00
FindFunctions ( regex , * m_apple_names_ap , include_inlines , sc_list ) ;
2013-08-23 13:46:38 -04:00
}
else
{
// Index the DWARF if we haven't already
if ( ! m_indexed )
Index ( ) ;
2015-07-03 12:57:06 -04:00
FindFunctions ( regex , m_function_basename_index , include_inlines , sc_list ) ;
2013-08-23 13:46:38 -04:00
2015-07-03 12:57:06 -04:00
FindFunctions ( regex , m_function_fullname_index , include_inlines , sc_list ) ;
2013-08-23 13:46:38 -04:00
}
// Return the number of variable that were appended to the list
return sc_list . GetSize ( ) - original_size ;
}
uint32_t
SymbolFileDWARF : : FindTypes ( const SymbolContext & sc ,
const ConstString & name ,
const lldb_private : : ClangNamespaceDecl * namespace_decl ,
bool append ,
uint32_t max_matches ,
TypeList & types )
{
DWARFDebugInfo * info = DebugInfo ( ) ;
if ( info = = NULL )
return 0 ;
Log * log ( LogChannelDWARF : : GetLogIfAll ( DWARF_LOG_LOOKUPS ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( log )
{
if ( namespace_decl )
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::FindTypes (sc, name= \" %s \" , clang::NamespaceDecl(%p) \" %s \" , append=%u, max_matches=%u, type_list) " ,
name . GetCString ( ) ,
2014-11-25 16:00:58 -05:00
static_cast < void * > ( namespace_decl - > GetNamespaceDecl ( ) ) ,
2013-08-23 13:46:38 -04:00
namespace_decl - > GetQualifiedName ( ) . c_str ( ) ,
2014-11-25 16:00:58 -05:00
append , max_matches ) ;
2013-08-23 13:46:38 -04:00
else
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::FindTypes (sc, name= \" %s \" , clang::NamespaceDecl(NULL), append=%u, max_matches=%u, type_list) " ,
2014-11-25 16:00:58 -05:00
name . GetCString ( ) , append ,
2013-08-23 13:46:38 -04:00
max_matches ) ;
}
// If we aren't appending the results to this list, then clear the list
if ( ! append )
types . Clear ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! NamespaceDeclMatchesThisSymbolFile ( namespace_decl ) )
2013-11-06 11:48:53 -05:00
return 0 ;
2013-08-23 13:46:38 -04:00
DIEArray die_offsets ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( m_using_apple_tables )
{
if ( m_apple_types_ap . get ( ) )
{
const char * name_cstr = name . GetCString ( ) ;
m_apple_types_ap - > FindByName ( name_cstr , die_offsets ) ;
}
}
else
{
if ( ! m_indexed )
Index ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
m_type_index . Find ( name , die_offsets ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
const size_t num_die_matches = die_offsets . size ( ) ;
if ( num_die_matches )
{
const uint32_t initial_types_size = types . GetSize ( ) ;
DWARFCompileUnit * dwarf_cu = NULL ;
const DWARFDebugInfoEntry * die = NULL ;
DWARFDebugInfo * debug_info = DebugInfo ( ) ;
for ( size_t i = 0 ; i < num_die_matches ; + + i )
{
const dw_offset_t die_offset = die_offsets [ i ] ;
die = debug_info - > GetDIEPtrWithCompileUnitHint ( die_offset , & dwarf_cu ) ;
if ( die )
{
if ( namespace_decl & & ! DIEIsInNamespace ( namespace_decl , dwarf_cu , die ) )
continue ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
Type * matching_type = ResolveType ( dwarf_cu , die ) ;
if ( matching_type )
{
// We found a type pointer, now find the shared pointer form our type list
types . InsertUnique ( matching_type - > shared_from_this ( ) ) ;
if ( types . GetSize ( ) > = max_matches )
break ;
}
}
else
{
if ( m_using_apple_tables )
{
GetObjectFile ( ) - > GetModule ( ) - > ReportErrorIfModifyDetected ( " the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s') \n " ,
die_offset , name . GetCString ( ) ) ;
}
}
}
const uint32_t num_matches = types . GetSize ( ) - initial_types_size ;
if ( log & & num_matches )
{
if ( namespace_decl )
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::FindTypes (sc, name= \" %s \" , clang::NamespaceDecl(%p) \" %s \" , append=%u, max_matches=%u, type_list) => %u " ,
name . GetCString ( ) ,
2014-11-25 16:00:58 -05:00
static_cast < void * > ( namespace_decl - > GetNamespaceDecl ( ) ) ,
2013-08-23 13:46:38 -04:00
namespace_decl - > GetQualifiedName ( ) . c_str ( ) ,
2014-11-25 16:00:58 -05:00
append , max_matches ,
2013-08-23 13:46:38 -04:00
num_matches ) ;
}
else
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::FindTypes (sc, name= \" %s \" , clang::NamespaceDecl(NULL), append=%u, max_matches=%u, type_list) => %u " ,
name . GetCString ( ) ,
2014-11-25 16:00:58 -05:00
append , max_matches ,
2013-08-23 13:46:38 -04:00
num_matches ) ;
}
}
return num_matches ;
}
return 0 ;
}
ClangNamespaceDecl
SymbolFileDWARF : : FindNamespace ( const SymbolContext & sc ,
const ConstString & name ,
const lldb_private : : ClangNamespaceDecl * parent_namespace_decl )
{
Log * log ( LogChannelDWARF : : GetLogIfAll ( DWARF_LOG_LOOKUPS ) ) ;
if ( log )
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::FindNamespace (sc, name= \" %s \" ) " ,
name . GetCString ( ) ) ;
}
if ( ! NamespaceDeclMatchesThisSymbolFile ( parent_namespace_decl ) )
2013-11-06 11:48:53 -05:00
return ClangNamespaceDecl ( ) ;
2013-08-23 13:46:38 -04:00
ClangNamespaceDecl namespace_decl ;
DWARFDebugInfo * info = DebugInfo ( ) ;
if ( info )
{
DIEArray die_offsets ;
// Index if we already haven't to make sure the compile units
// get indexed and make their global DIE index list
if ( m_using_apple_tables )
{
if ( m_apple_namespaces_ap . get ( ) )
{
const char * name_cstr = name . GetCString ( ) ;
m_apple_namespaces_ap - > FindByName ( name_cstr , die_offsets ) ;
}
}
else
{
if ( ! m_indexed )
Index ( ) ;
m_namespace_index . Find ( name , die_offsets ) ;
}
DWARFCompileUnit * dwarf_cu = NULL ;
const DWARFDebugInfoEntry * die = NULL ;
const size_t num_matches = die_offsets . size ( ) ;
if ( num_matches )
{
DWARFDebugInfo * debug_info = DebugInfo ( ) ;
for ( size_t i = 0 ; i < num_matches ; + + i )
{
const dw_offset_t die_offset = die_offsets [ i ] ;
die = debug_info - > GetDIEPtrWithCompileUnitHint ( die_offset , & dwarf_cu ) ;
if ( die )
{
if ( parent_namespace_decl & & ! DIEIsInNamespace ( parent_namespace_decl , dwarf_cu , die ) )
continue ;
clang : : NamespaceDecl * clang_namespace_decl = ResolveNamespaceDIE ( dwarf_cu , die ) ;
if ( clang_namespace_decl )
{
namespace_decl . SetASTContext ( GetClangASTContext ( ) . getASTContext ( ) ) ;
namespace_decl . SetNamespaceDecl ( clang_namespace_decl ) ;
break ;
}
}
else
{
if ( m_using_apple_tables )
{
GetObjectFile ( ) - > GetModule ( ) - > ReportErrorIfModifyDetected ( " the DWARF debug information has been modified (.apple_namespaces accelerator table had bad die 0x%8.8x for '%s') \n " ,
die_offset , name . GetCString ( ) ) ;
}
}
}
}
}
if ( log & & namespace_decl . GetNamespaceDecl ( ) )
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::FindNamespace (sc, name= \" %s \" ) => clang::NamespaceDecl(%p) \" %s \" " ,
name . GetCString ( ) ,
2014-11-25 16:00:58 -05:00
static_cast < const void * > ( namespace_decl . GetNamespaceDecl ( ) ) ,
2013-08-23 13:46:38 -04:00
namespace_decl . GetQualifiedName ( ) . c_str ( ) ) ;
}
return namespace_decl ;
}
uint32_t
SymbolFileDWARF : : FindTypes ( std : : vector < dw_offset_t > die_offsets , uint32_t max_matches , TypeList & types )
{
// Remember how many sc_list are in the list before we search in case
// we are appending the results to a variable list.
uint32_t original_size = types . GetSize ( ) ;
const uint32_t num_die_offsets = die_offsets . size ( ) ;
// Parse all of the types we found from the pubtypes matches
uint32_t i ;
uint32_t num_matches = 0 ;
for ( i = 0 ; i < num_die_offsets ; + + i )
{
Type * matching_type = ResolveTypeUID ( die_offsets [ i ] ) ;
if ( matching_type )
{
// We found a type pointer, now find the shared pointer form our type list
types . InsertUnique ( matching_type - > shared_from_this ( ) ) ;
+ + num_matches ;
if ( num_matches > = max_matches )
break ;
}
}
// Return the number of variable that were appended to the list
return types . GetSize ( ) - original_size ;
}
size_t
SymbolFileDWARF : : ParseChildParameters ( const SymbolContext & sc ,
clang : : DeclContext * containing_decl_ctx ,
DWARFCompileUnit * dwarf_cu ,
const DWARFDebugInfoEntry * parent_die ,
bool skip_artificial ,
bool & is_static ,
2014-02-25 16:42:16 -05:00
bool & is_variadic ,
2013-08-23 13:46:38 -04:00
std : : vector < ClangASTType > & function_param_types ,
std : : vector < clang : : ParmVarDecl * > & function_param_decls ,
2014-11-25 16:00:58 -05:00
unsigned & type_quals ) // ,
// ClangASTContext::TemplateParameterInfos &template_param_infos))
2013-08-23 13:46:38 -04:00
{
if ( parent_die = = NULL )
return 0 ;
2015-02-06 16:38:51 -05:00
const uint8_t * fixed_form_sizes = DWARFFormValue : : GetFixedFormSizesForAddressSize ( dwarf_cu - > GetAddressByteSize ( ) , dwarf_cu - > IsDWARF64 ( ) ) ;
2013-08-23 13:46:38 -04:00
size_t arg_idx = 0 ;
const DWARFDebugInfoEntry * die ;
for ( die = parent_die - > GetFirstChild ( ) ; die ! = NULL ; die = die - > GetSibling ( ) )
{
dw_tag_t tag = die - > Tag ( ) ;
switch ( tag )
{
case DW_TAG_formal_parameter :
{
DWARFDebugInfoEntry : : Attributes attributes ;
const size_t num_attributes = die - > GetAttributes ( this , dwarf_cu , fixed_form_sizes , attributes ) ;
if ( num_attributes > 0 )
{
const char * name = NULL ;
Declaration decl ;
dw_offset_t param_type_die_offset = DW_INVALID_OFFSET ;
bool is_artificial = false ;
// one of None, Auto, Register, Extern, Static, PrivateExtern
clang : : StorageClass storage = clang : : SC_None ;
uint32_t i ;
for ( i = 0 ; i < num_attributes ; + + i )
{
const dw_attr_t attr = attributes . AttributeAtIndex ( i ) ;
DWARFFormValue form_value ;
if ( attributes . ExtractFormValueAtIndex ( this , i , form_value ) )
{
switch ( attr )
{
case DW_AT_decl_file : decl . SetFile ( sc . comp_unit - > GetSupportFiles ( ) . GetFileSpecAtIndex ( form_value . Unsigned ( ) ) ) ; break ;
case DW_AT_decl_line : decl . SetLine ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_decl_column : decl . SetColumn ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_name : name = form_value . AsCString ( & get_debug_str_data ( ) ) ; break ;
2015-02-06 16:38:51 -05:00
case DW_AT_type : param_type_die_offset = form_value . Reference ( ) ; break ;
2013-08-23 13:46:38 -04:00
case DW_AT_artificial : is_artificial = form_value . Boolean ( ) ; break ;
case DW_AT_location :
// if (form_value.BlockData())
// {
2013-11-06 11:48:53 -05:00
// const DWARFDataExtractor& debug_info_data = debug_info();
2013-08-23 13:46:38 -04:00
// uint32_t block_length = form_value.Unsigned();
2013-11-06 11:48:53 -05:00
// DWARFDataExtractor location(debug_info_data, form_value.BlockData() - debug_info_data.GetDataStart(), block_length);
2013-08-23 13:46:38 -04:00
// }
// else
// {
// }
// break;
case DW_AT_const_value :
case DW_AT_default_value :
case DW_AT_description :
case DW_AT_endianity :
case DW_AT_is_optional :
case DW_AT_segment :
case DW_AT_variable_parameter :
default :
case DW_AT_abstract_origin :
case DW_AT_sibling :
break ;
}
}
}
bool skip = false ;
if ( skip_artificial )
{
if ( is_artificial )
{
// In order to determine if a C++ member function is
// "const" we have to look at the const-ness of "this"...
// Ugly, but that
if ( arg_idx = = 0 )
{
if ( DeclKindIsCXXClass ( containing_decl_ctx - > getDeclKind ( ) ) )
{
// Often times compilers omit the "this" name for the
// specification DIEs, so we can't rely upon the name
// being in the formal parameter DIE...
if ( name = = NULL | | : : strcmp ( name , " this " ) = = 0 )
{
Type * this_type = ResolveTypeUID ( param_type_die_offset ) ;
if ( this_type )
{
uint32_t encoding_mask = this_type - > GetEncodingMask ( ) ;
if ( encoding_mask & Type : : eEncodingIsPointerUID )
{
is_static = false ;
if ( encoding_mask & ( 1u < < Type : : eEncodingIsConstUID ) )
type_quals | = clang : : Qualifiers : : Const ;
if ( encoding_mask & ( 1u < < Type : : eEncodingIsVolatileUID ) )
type_quals | = clang : : Qualifiers : : Volatile ;
}
}
}
}
}
skip = true ;
}
else
{
// HACK: Objective C formal parameters "self" and "_cmd"
// are not marked as artificial in the DWARF...
CompileUnit * comp_unit = GetCompUnitForDWARFCompUnit ( dwarf_cu , UINT32_MAX ) ;
if ( comp_unit )
{
switch ( comp_unit - > GetLanguage ( ) )
{
case eLanguageTypeObjC :
case eLanguageTypeObjC_plus_plus :
if ( name & & name [ 0 ] & & ( strcmp ( name , " self " ) = = 0 | | strcmp ( name , " _cmd " ) = = 0 ) )
skip = true ;
break ;
default :
break ;
}
}
}
}
if ( ! skip )
{
Type * type = ResolveTypeUID ( param_type_die_offset ) ;
if ( type )
{
function_param_types . push_back ( type - > GetClangForwardType ( ) ) ;
clang : : ParmVarDecl * param_var_decl = GetClangASTContext ( ) . CreateParameterDeclaration ( name ,
type - > GetClangForwardType ( ) ,
storage ) ;
assert ( param_var_decl ) ;
function_param_decls . push_back ( param_var_decl ) ;
GetClangASTContext ( ) . SetMetadataAsUserID ( param_var_decl , MakeUserID ( die - > GetOffset ( ) ) ) ;
}
}
}
arg_idx + + ;
}
break ;
2014-02-25 16:42:16 -05:00
case DW_TAG_unspecified_parameters :
is_variadic = true ;
break ;
2013-08-23 13:46:38 -04:00
case DW_TAG_template_type_parameter :
case DW_TAG_template_value_parameter :
2014-11-25 16:00:58 -05:00
// The one caller of this was never using the template_param_infos,
// and the local variable was taking up a large amount of stack space
// in SymbolFileDWARF::ParseType() so this was removed. If we ever need
// the template params back, we can add them back.
// ParseTemplateDIE (dwarf_cu, die, template_param_infos);
2013-08-23 13:46:38 -04:00
break ;
default :
break ;
}
}
return arg_idx ;
}
size_t
SymbolFileDWARF : : ParseChildEnumerators
(
const SymbolContext & sc ,
lldb_private : : ClangASTType & clang_type ,
bool is_signed ,
uint32_t enumerator_byte_size ,
DWARFCompileUnit * dwarf_cu ,
const DWARFDebugInfoEntry * parent_die
)
{
if ( parent_die = = NULL )
return 0 ;
size_t enumerators_added = 0 ;
const DWARFDebugInfoEntry * die ;
2015-02-06 16:38:51 -05:00
const uint8_t * fixed_form_sizes = DWARFFormValue : : GetFixedFormSizesForAddressSize ( dwarf_cu - > GetAddressByteSize ( ) , dwarf_cu - > IsDWARF64 ( ) ) ;
2013-08-23 13:46:38 -04:00
for ( die = parent_die - > GetFirstChild ( ) ; die ! = NULL ; die = die - > GetSibling ( ) )
{
const dw_tag_t tag = die - > Tag ( ) ;
if ( tag = = DW_TAG_enumerator )
{
DWARFDebugInfoEntry : : Attributes attributes ;
const size_t num_child_attributes = die - > GetAttributes ( this , dwarf_cu , fixed_form_sizes , attributes ) ;
if ( num_child_attributes > 0 )
{
const char * name = NULL ;
bool got_value = false ;
int64_t enum_value = 0 ;
Declaration decl ;
uint32_t i ;
for ( i = 0 ; i < num_child_attributes ; + + i )
{
const dw_attr_t attr = attributes . AttributeAtIndex ( i ) ;
DWARFFormValue form_value ;
if ( attributes . ExtractFormValueAtIndex ( this , i , form_value ) )
{
switch ( attr )
{
case DW_AT_const_value :
got_value = true ;
if ( is_signed )
enum_value = form_value . Signed ( ) ;
else
enum_value = form_value . Unsigned ( ) ;
break ;
case DW_AT_name :
name = form_value . AsCString ( & get_debug_str_data ( ) ) ;
break ;
case DW_AT_description :
default :
case DW_AT_decl_file : decl . SetFile ( sc . comp_unit - > GetSupportFiles ( ) . GetFileSpecAtIndex ( form_value . Unsigned ( ) ) ) ; break ;
case DW_AT_decl_line : decl . SetLine ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_decl_column : decl . SetColumn ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_sibling :
break ;
}
}
}
if ( name & & name [ 0 ] & & got_value )
{
clang_type . AddEnumerationValueToEnumerationType ( clang_type . GetEnumerationIntegerType ( ) ,
decl ,
name ,
enum_value ,
enumerator_byte_size * 8 ) ;
+ + enumerators_added ;
}
}
}
}
return enumerators_added ;
}
void
SymbolFileDWARF : : ParseChildArrayInfo
(
const SymbolContext & sc ,
DWARFCompileUnit * dwarf_cu ,
const DWARFDebugInfoEntry * parent_die ,
int64_t & first_index ,
std : : vector < uint64_t > & element_orders ,
uint32_t & byte_stride ,
uint32_t & bit_stride
)
{
if ( parent_die = = NULL )
return ;
const DWARFDebugInfoEntry * die ;
2015-02-06 16:38:51 -05:00
const uint8_t * fixed_form_sizes = DWARFFormValue : : GetFixedFormSizesForAddressSize ( dwarf_cu - > GetAddressByteSize ( ) , dwarf_cu - > IsDWARF64 ( ) ) ;
2013-08-23 13:46:38 -04:00
for ( die = parent_die - > GetFirstChild ( ) ; die ! = NULL ; die = die - > GetSibling ( ) )
{
const dw_tag_t tag = die - > Tag ( ) ;
switch ( tag )
{
case DW_TAG_subrange_type :
{
DWARFDebugInfoEntry : : Attributes attributes ;
const size_t num_child_attributes = die - > GetAttributes ( this , dwarf_cu , fixed_form_sizes , attributes ) ;
if ( num_child_attributes > 0 )
{
uint64_t num_elements = 0 ;
uint64_t lower_bound = 0 ;
uint64_t upper_bound = 0 ;
bool upper_bound_valid = false ;
uint32_t i ;
for ( i = 0 ; i < num_child_attributes ; + + i )
{
const dw_attr_t attr = attributes . AttributeAtIndex ( i ) ;
DWARFFormValue form_value ;
if ( attributes . ExtractFormValueAtIndex ( this , i , form_value ) )
{
switch ( attr )
{
case DW_AT_name :
break ;
case DW_AT_count :
num_elements = form_value . Unsigned ( ) ;
break ;
case DW_AT_bit_stride :
bit_stride = form_value . Unsigned ( ) ;
break ;
case DW_AT_byte_stride :
byte_stride = form_value . Unsigned ( ) ;
break ;
case DW_AT_lower_bound :
lower_bound = form_value . Unsigned ( ) ;
break ;
case DW_AT_upper_bound :
upper_bound_valid = true ;
upper_bound = form_value . Unsigned ( ) ;
break ;
default :
case DW_AT_abstract_origin :
case DW_AT_accessibility :
case DW_AT_allocated :
case DW_AT_associated :
case DW_AT_data_location :
case DW_AT_declaration :
case DW_AT_description :
case DW_AT_sibling :
case DW_AT_threads_scaled :
case DW_AT_type :
case DW_AT_visibility :
break ;
}
}
}
if ( num_elements = = 0 )
{
if ( upper_bound_valid & & upper_bound > = lower_bound )
num_elements = upper_bound - lower_bound + 1 ;
}
element_orders . push_back ( num_elements ) ;
}
}
break ;
}
}
}
TypeSP
SymbolFileDWARF : : GetTypeForDIE ( DWARFCompileUnit * dwarf_cu , const DWARFDebugInfoEntry * die )
{
TypeSP type_sp ;
if ( die ! = NULL )
{
assert ( dwarf_cu ! = NULL ) ;
Type * type_ptr = m_die_to_type . lookup ( die ) ;
if ( type_ptr = = NULL )
{
CompileUnit * lldb_cu = GetCompUnitForDWARFCompUnit ( dwarf_cu ) ;
assert ( lldb_cu ) ;
SymbolContext sc ( lldb_cu ) ;
type_sp = ParseType ( sc , dwarf_cu , die , NULL ) ;
}
else if ( type_ptr ! = DIE_IS_BEING_PARSED )
{
// Grab the existing type from the master types lists
type_sp = type_ptr - > shared_from_this ( ) ;
}
}
return type_sp ;
}
clang : : DeclContext *
SymbolFileDWARF : : GetClangDeclContextContainingDIEOffset ( dw_offset_t die_offset )
{
if ( die_offset ! = DW_INVALID_OFFSET )
{
DWARFCompileUnitSP cu_sp ;
const DWARFDebugInfoEntry * die = DebugInfo ( ) - > GetDIEPtr ( die_offset , & cu_sp ) ;
return GetClangDeclContextContainingDIE ( cu_sp . get ( ) , die , NULL ) ;
}
return NULL ;
}
clang : : DeclContext *
SymbolFileDWARF : : GetClangDeclContextForDIEOffset ( const SymbolContext & sc , dw_offset_t die_offset )
{
if ( die_offset ! = DW_INVALID_OFFSET )
{
DWARFDebugInfo * debug_info = DebugInfo ( ) ;
if ( debug_info )
{
DWARFCompileUnitSP cu_sp ;
const DWARFDebugInfoEntry * die = debug_info - > GetDIEPtr ( die_offset , & cu_sp ) ;
if ( die )
return GetClangDeclContextForDIE ( sc , cu_sp . get ( ) , die ) ;
}
}
return NULL ;
}
clang : : NamespaceDecl *
SymbolFileDWARF : : ResolveNamespaceDIE ( DWARFCompileUnit * dwarf_cu , const DWARFDebugInfoEntry * die )
{
if ( die & & die - > Tag ( ) = = DW_TAG_namespace )
{
// See if we already parsed this namespace DIE and associated it with a
// uniqued namespace declaration
clang : : NamespaceDecl * namespace_decl = static_cast < clang : : NamespaceDecl * > ( m_die_to_decl_ctx [ die ] ) ;
if ( namespace_decl )
return namespace_decl ;
else
{
const char * namespace_name = die - > GetAttributeValueAsString ( this , dwarf_cu , DW_AT_name , NULL ) ;
clang : : DeclContext * containing_decl_ctx = GetClangDeclContextContainingDIE ( dwarf_cu , die , NULL ) ;
namespace_decl = GetClangASTContext ( ) . GetUniqueNamespaceDeclaration ( namespace_name , containing_decl_ctx ) ;
Log * log ( LogChannelDWARF : : GetLogIfAll ( DWARF_LOG_DEBUG_INFO ) ) ;
if ( log )
{
if ( namespace_name )
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" ASTContext => %p: 0x%8.8 " PRIx64 " : DW_TAG_namespace with DW_AT_name( \" %s \" ) => clang::NamespaceDecl *%p (original = %p) " ,
2014-11-25 16:00:58 -05:00
static_cast < void * > ( GetClangASTContext ( ) . getASTContext ( ) ) ,
2013-08-23 13:46:38 -04:00
MakeUserID ( die - > GetOffset ( ) ) ,
namespace_name ,
2014-11-25 16:00:58 -05:00
static_cast < void * > ( namespace_decl ) ,
static_cast < void * > ( namespace_decl - > getOriginalNamespace ( ) ) ) ;
2013-08-23 13:46:38 -04:00
}
else
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" ASTContext => %p: 0x%8.8 " PRIx64 " : DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p (original = %p) " ,
2014-11-25 16:00:58 -05:00
static_cast < void * > ( GetClangASTContext ( ) . getASTContext ( ) ) ,
2013-08-23 13:46:38 -04:00
MakeUserID ( die - > GetOffset ( ) ) ,
2014-11-25 16:00:58 -05:00
static_cast < void * > ( namespace_decl ) ,
static_cast < void * > ( namespace_decl - > getOriginalNamespace ( ) ) ) ;
2013-08-23 13:46:38 -04:00
}
}
if ( namespace_decl )
LinkDeclContextToDIE ( ( clang : : DeclContext * ) namespace_decl , die ) ;
return namespace_decl ;
}
}
return NULL ;
}
clang : : DeclContext *
SymbolFileDWARF : : GetClangDeclContextForDIE ( const SymbolContext & sc , DWARFCompileUnit * cu , const DWARFDebugInfoEntry * die )
{
clang : : DeclContext * clang_decl_ctx = GetCachedClangDeclContextForDIE ( die ) ;
if ( clang_decl_ctx )
return clang_decl_ctx ;
// If this DIE has a specification, or an abstract origin, then trace to those.
dw_offset_t die_offset = die - > GetAttributeValueAsReference ( this , cu , DW_AT_specification , DW_INVALID_OFFSET ) ;
if ( die_offset ! = DW_INVALID_OFFSET )
return GetClangDeclContextForDIEOffset ( sc , die_offset ) ;
die_offset = die - > GetAttributeValueAsReference ( this , cu , DW_AT_abstract_origin , DW_INVALID_OFFSET ) ;
if ( die_offset ! = DW_INVALID_OFFSET )
return GetClangDeclContextForDIEOffset ( sc , die_offset ) ;
Log * log ( LogChannelDWARF : : GetLogIfAll ( DWARF_LOG_DEBUG_INFO ) ) ;
if ( log )
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log , " SymbolFileDWARF::GetClangDeclContextForDIE (die = 0x%8.8x) %s '%s' " , die - > GetOffset ( ) , DW_TAG_value_to_name ( die - > Tag ( ) ) , die - > GetName ( this , cu ) ) ;
// This is the DIE we want. Parse it, then query our map.
bool assert_not_being_parsed = true ;
ResolveTypeUID ( cu , die , assert_not_being_parsed ) ;
clang_decl_ctx = GetCachedClangDeclContextForDIE ( die ) ;
return clang_decl_ctx ;
}
clang : : DeclContext *
SymbolFileDWARF : : GetClangDeclContextContainingDIE ( DWARFCompileUnit * cu , const DWARFDebugInfoEntry * die , const DWARFDebugInfoEntry * * decl_ctx_die_copy )
{
if ( m_clang_tu_decl = = NULL )
m_clang_tu_decl = GetClangASTContext ( ) . getASTContext ( ) - > getTranslationUnitDecl ( ) ;
const DWARFDebugInfoEntry * decl_ctx_die = GetDeclContextDIEContainingDIE ( cu , die ) ;
if ( decl_ctx_die_copy )
* decl_ctx_die_copy = decl_ctx_die ;
if ( decl_ctx_die )
{
DIEToDeclContextMap : : iterator pos = m_die_to_decl_ctx . find ( decl_ctx_die ) ;
if ( pos ! = m_die_to_decl_ctx . end ( ) )
return pos - > second ;
switch ( decl_ctx_die - > Tag ( ) )
{
case DW_TAG_compile_unit :
return m_clang_tu_decl ;
case DW_TAG_namespace :
return ResolveNamespaceDIE ( cu , decl_ctx_die ) ;
break ;
case DW_TAG_structure_type :
case DW_TAG_union_type :
case DW_TAG_class_type :
{
Type * type = ResolveType ( cu , decl_ctx_die ) ;
if ( type )
{
clang : : DeclContext * decl_ctx = type - > GetClangForwardType ( ) . GetDeclContextForType ( ) ;
if ( decl_ctx )
{
LinkDeclContextToDIE ( decl_ctx , decl_ctx_die ) ;
if ( decl_ctx )
return decl_ctx ;
}
}
}
break ;
default :
break ;
}
}
return m_clang_tu_decl ;
}
const DWARFDebugInfoEntry *
SymbolFileDWARF : : GetDeclContextDIEContainingDIE ( DWARFCompileUnit * cu , const DWARFDebugInfoEntry * die )
{
if ( cu & & die )
{
const DWARFDebugInfoEntry * const decl_die = die ;
while ( die ! = NULL )
{
// If this is the original DIE that we are searching for a declaration
// for, then don't look in the cache as we don't want our own decl
// context to be our decl context...
if ( decl_die ! = die )
{
switch ( die - > Tag ( ) )
{
case DW_TAG_compile_unit :
case DW_TAG_namespace :
case DW_TAG_structure_type :
case DW_TAG_union_type :
case DW_TAG_class_type :
return die ;
default :
break ;
}
}
dw_offset_t die_offset = die - > GetAttributeValueAsReference ( this , cu , DW_AT_specification , DW_INVALID_OFFSET ) ;
if ( die_offset ! = DW_INVALID_OFFSET )
{
DWARFCompileUnit * spec_cu = cu ;
const DWARFDebugInfoEntry * spec_die = DebugInfo ( ) - > GetDIEPtrWithCompileUnitHint ( die_offset , & spec_cu ) ;
const DWARFDebugInfoEntry * spec_die_decl_ctx_die = GetDeclContextDIEContainingDIE ( spec_cu , spec_die ) ;
if ( spec_die_decl_ctx_die )
return spec_die_decl_ctx_die ;
}
die_offset = die - > GetAttributeValueAsReference ( this , cu , DW_AT_abstract_origin , DW_INVALID_OFFSET ) ;
if ( die_offset ! = DW_INVALID_OFFSET )
{
DWARFCompileUnit * abs_cu = cu ;
const DWARFDebugInfoEntry * abs_die = DebugInfo ( ) - > GetDIEPtrWithCompileUnitHint ( die_offset , & abs_cu ) ;
const DWARFDebugInfoEntry * abs_die_decl_ctx_die = GetDeclContextDIEContainingDIE ( abs_cu , abs_die ) ;
if ( abs_die_decl_ctx_die )
return abs_die_decl_ctx_die ;
}
die = die - > GetParent ( ) ;
}
}
return NULL ;
}
Symbol *
SymbolFileDWARF : : GetObjCClassSymbol ( const ConstString & objc_class_name )
{
Symbol * objc_class_symbol = NULL ;
if ( m_obj_file )
{
Symtab * symtab = m_obj_file - > GetSymtab ( ) ;
if ( symtab )
{
objc_class_symbol = symtab - > FindFirstSymbolWithNameAndType ( objc_class_name ,
eSymbolTypeObjCClass ,
Symtab : : eDebugNo ,
Symtab : : eVisibilityAny ) ;
}
}
return objc_class_symbol ;
}
// Some compilers don't emit the DW_AT_APPLE_objc_complete_type attribute. If they don't
// then we can end up looking through all class types for a complete type and never find
// the full definition. We need to know if this attribute is supported, so we determine
// this here and cache th result. We also need to worry about the debug map DWARF file
// if we are doing darwin DWARF in .o file debugging.
bool
SymbolFileDWARF : : Supports_DW_AT_APPLE_objc_complete_type ( DWARFCompileUnit * cu )
{
if ( m_supports_DW_AT_APPLE_objc_complete_type = = eLazyBoolCalculate )
{
m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo ;
if ( cu & & cu - > Supports_DW_AT_APPLE_objc_complete_type ( ) )
m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes ;
else
{
DWARFDebugInfo * debug_info = DebugInfo ( ) ;
const uint32_t num_compile_units = GetNumCompileUnits ( ) ;
for ( uint32_t cu_idx = 0 ; cu_idx < num_compile_units ; + + cu_idx )
{
DWARFCompileUnit * dwarf_cu = debug_info - > GetCompileUnitAtIndex ( cu_idx ) ;
if ( dwarf_cu ! = cu & & dwarf_cu - > Supports_DW_AT_APPLE_objc_complete_type ( ) )
{
m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes ;
break ;
}
}
}
if ( m_supports_DW_AT_APPLE_objc_complete_type = = eLazyBoolNo & & GetDebugMapSymfile ( ) )
return m_debug_map_symfile - > Supports_DW_AT_APPLE_objc_complete_type ( this ) ;
}
return m_supports_DW_AT_APPLE_objc_complete_type = = eLazyBoolYes ;
}
// This function can be used when a DIE is found that is a forward declaration
// DIE and we want to try and find a type that has the complete definition.
TypeSP
SymbolFileDWARF : : FindCompleteObjCDefinitionTypeForDIE ( const DWARFDebugInfoEntry * die ,
const ConstString & type_name ,
bool must_be_implementation )
{
TypeSP type_sp ;
if ( ! type_name | | ( must_be_implementation & & ! GetObjCClassSymbol ( type_name ) ) )
return type_sp ;
DIEArray die_offsets ;
if ( m_using_apple_tables )
{
if ( m_apple_types_ap . get ( ) )
{
const char * name_cstr = type_name . GetCString ( ) ;
m_apple_types_ap - > FindCompleteObjCClassByName ( name_cstr , die_offsets , must_be_implementation ) ;
}
}
else
{
if ( ! m_indexed )
Index ( ) ;
m_type_index . Find ( type_name , die_offsets ) ;
}
const size_t num_matches = die_offsets . size ( ) ;
DWARFCompileUnit * type_cu = NULL ;
const DWARFDebugInfoEntry * type_die = NULL ;
if ( num_matches )
{
DWARFDebugInfo * debug_info = DebugInfo ( ) ;
for ( size_t i = 0 ; i < num_matches ; + + i )
{
const dw_offset_t die_offset = die_offsets [ i ] ;
type_die = debug_info - > GetDIEPtrWithCompileUnitHint ( die_offset , & type_cu ) ;
if ( type_die )
{
bool try_resolving_type = false ;
// Don't try and resolve the DIE we are looking for with the DIE itself!
if ( type_die ! = die )
{
switch ( type_die - > Tag ( ) )
{
case DW_TAG_class_type :
case DW_TAG_structure_type :
try_resolving_type = true ;
break ;
default :
break ;
}
}
if ( try_resolving_type )
{
2013-11-06 11:48:53 -05:00
if ( must_be_implementation & & type_cu - > Supports_DW_AT_APPLE_objc_complete_type ( ) )
try_resolving_type = type_die - > GetAttributeValueAsUnsigned ( this , type_cu , DW_AT_APPLE_objc_complete_type , 0 ) ;
2013-08-23 13:46:38 -04:00
if ( try_resolving_type )
{
Type * resolved_type = ResolveType ( type_cu , type_die , false ) ;
if ( resolved_type & & resolved_type ! = DIE_IS_BEING_PARSED )
{
2013-11-06 11:48:53 -05:00
DEBUG_PRINTF ( " resolved 0x%8.8 " PRIx64 " from %s to 0x%8.8 " PRIx64 " (cu 0x%8.8 " PRIx64 " ) \n " ,
2013-08-23 13:46:38 -04:00
MakeUserID ( die - > GetOffset ( ) ) ,
2015-02-06 16:38:51 -05:00
m_obj_file - > GetFileSpec ( ) . GetFilename ( ) . AsCString ( " <Unknown> " ) ,
2013-08-23 13:46:38 -04:00
MakeUserID ( type_die - > GetOffset ( ) ) ,
MakeUserID ( type_cu - > GetOffset ( ) ) ) ;
if ( die )
m_die_to_type [ die ] = resolved_type ;
type_sp = resolved_type - > shared_from_this ( ) ;
break ;
}
}
}
}
else
{
if ( m_using_apple_tables )
{
GetObjectFile ( ) - > GetModule ( ) - > ReportErrorIfModifyDetected ( " the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s') \n " ,
die_offset , type_name . GetCString ( ) ) ;
}
}
}
}
return type_sp ;
}
//----------------------------------------------------------------------
// This function helps to ensure that the declaration contexts match for
// two different DIEs. Often times debug information will refer to a
// forward declaration of a type (the equivalent of "struct my_struct;".
// There will often be a declaration of that type elsewhere that has the
// full definition. When we go looking for the full type "my_struct", we
// will find one or more matches in the accelerator tables and we will
// then need to make sure the type was in the same declaration context
// as the original DIE. This function can efficiently compare two DIEs
// and will return true when the declaration context matches, and false
// when they don't.
//----------------------------------------------------------------------
bool
SymbolFileDWARF : : DIEDeclContextsMatch ( DWARFCompileUnit * cu1 , const DWARFDebugInfoEntry * die1 ,
DWARFCompileUnit * cu2 , const DWARFDebugInfoEntry * die2 )
{
if ( die1 = = die2 )
return true ;
# if defined (LLDB_CONFIGURATION_DEBUG)
// You can't and shouldn't call this function with a compile unit from
// two different SymbolFileDWARF instances.
assert ( DebugInfo ( ) - > ContainsCompileUnit ( cu1 ) ) ;
assert ( DebugInfo ( ) - > ContainsCompileUnit ( cu2 ) ) ;
# endif
DWARFDIECollection decl_ctx_1 ;
DWARFDIECollection decl_ctx_2 ;
//The declaration DIE stack is a stack of the declaration context
// DIEs all the way back to the compile unit. If a type "T" is
// declared inside a class "B", and class "B" is declared inside
// a class "A" and class "A" is in a namespace "lldb", and the
// namespace is in a compile unit, there will be a stack of DIEs:
//
// [0] DW_TAG_class_type for "B"
// [1] DW_TAG_class_type for "A"
// [2] DW_TAG_namespace for "lldb"
// [3] DW_TAG_compile_unit for the source file.
//
// We grab both contexts and make sure that everything matches
// all the way back to the compiler unit.
// First lets grab the decl contexts for both DIEs
die1 - > GetDeclContextDIEs ( this , cu1 , decl_ctx_1 ) ;
die2 - > GetDeclContextDIEs ( this , cu2 , decl_ctx_2 ) ;
// Make sure the context arrays have the same size, otherwise
// we are done
const size_t count1 = decl_ctx_1 . Size ( ) ;
const size_t count2 = decl_ctx_2 . Size ( ) ;
if ( count1 ! = count2 )
return false ;
2014-11-25 16:00:58 -05:00
// Make sure the DW_TAG values match all the way back up the
2013-08-23 13:46:38 -04:00
// compile unit. If they don't, then we are done.
const DWARFDebugInfoEntry * decl_ctx_die1 ;
const DWARFDebugInfoEntry * decl_ctx_die2 ;
size_t i ;
for ( i = 0 ; i < count1 ; i + + )
{
decl_ctx_die1 = decl_ctx_1 . GetDIEPtrAtIndex ( i ) ;
decl_ctx_die2 = decl_ctx_2 . GetDIEPtrAtIndex ( i ) ;
if ( decl_ctx_die1 - > Tag ( ) ! = decl_ctx_die2 - > Tag ( ) )
return false ;
}
# if defined LLDB_CONFIGURATION_DEBUG
// Make sure the top item in the decl context die array is always
// DW_TAG_compile_unit. If it isn't then something went wrong in
// the DWARFDebugInfoEntry::GetDeclContextDIEs() function...
assert ( decl_ctx_1 . GetDIEPtrAtIndex ( count1 - 1 ) - > Tag ( ) = = DW_TAG_compile_unit ) ;
# endif
// Always skip the compile unit when comparing by only iterating up to
// "count - 1". Here we compare the names as we go.
for ( i = 0 ; i < count1 - 1 ; i + + )
{
decl_ctx_die1 = decl_ctx_1 . GetDIEPtrAtIndex ( i ) ;
decl_ctx_die2 = decl_ctx_2 . GetDIEPtrAtIndex ( i ) ;
const char * name1 = decl_ctx_die1 - > GetName ( this , cu1 ) ;
const char * name2 = decl_ctx_die2 - > GetName ( this , cu2 ) ;
// If the string was from a DW_FORM_strp, then the pointer will often
// be the same!
if ( name1 = = name2 )
continue ;
// Name pointers are not equal, so only compare the strings
// if both are not NULL.
if ( name1 & & name2 )
{
// If the strings don't compare, we are done...
if ( strcmp ( name1 , name2 ) ! = 0 )
return false ;
}
else
{
// One name was NULL while the other wasn't
return false ;
}
}
// We made it through all of the checks and the declaration contexts
// are equal.
return true ;
}
TypeSP
SymbolFileDWARF : : FindDefinitionTypeForDWARFDeclContext ( const DWARFDeclContext & dwarf_decl_ctx )
{
TypeSP type_sp ;
const uint32_t dwarf_decl_ctx_count = dwarf_decl_ctx . GetSize ( ) ;
if ( dwarf_decl_ctx_count > 0 )
{
const ConstString type_name ( dwarf_decl_ctx [ 0 ] . name ) ;
const dw_tag_t tag = dwarf_decl_ctx [ 0 ] . tag ;
if ( type_name )
{
Log * log ( LogChannelDWARF : : GetLogIfAny ( DWARF_LOG_TYPE_COMPLETION | DWARF_LOG_LOOKUPS ) ) ;
if ( log )
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s') " ,
DW_TAG_value_to_name ( dwarf_decl_ctx [ 0 ] . tag ) ,
dwarf_decl_ctx . GetQualifiedName ( ) ) ;
}
DIEArray die_offsets ;
if ( m_using_apple_tables )
{
if ( m_apple_types_ap . get ( ) )
{
const bool has_tag = m_apple_types_ap - > GetHeader ( ) . header_data . ContainsAtom ( DWARFMappedHash : : eAtomTypeTag ) ;
const bool has_qualified_name_hash = m_apple_types_ap - > GetHeader ( ) . header_data . ContainsAtom ( DWARFMappedHash : : eAtomTypeQualNameHash ) ;
if ( has_tag & & has_qualified_name_hash )
{
const char * qualified_name = dwarf_decl_ctx . GetQualifiedName ( ) ;
const uint32_t qualified_name_hash = MappedHash : : HashStringUsingDJB ( qualified_name ) ;
if ( log )
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log , " FindByNameAndTagAndQualifiedNameHash() " ) ;
m_apple_types_ap - > FindByNameAndTagAndQualifiedNameHash ( type_name . GetCString ( ) , tag , qualified_name_hash , die_offsets ) ;
}
else if ( has_tag )
{
if ( log )
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log , " FindByNameAndTag() " ) ;
m_apple_types_ap - > FindByNameAndTag ( type_name . GetCString ( ) , tag , die_offsets ) ;
}
else
{
m_apple_types_ap - > FindByName ( type_name . GetCString ( ) , die_offsets ) ;
}
}
}
else
{
if ( ! m_indexed )
Index ( ) ;
m_type_index . Find ( type_name , die_offsets ) ;
}
const size_t num_matches = die_offsets . size ( ) ;
DWARFCompileUnit * type_cu = NULL ;
const DWARFDebugInfoEntry * type_die = NULL ;
if ( num_matches )
{
DWARFDebugInfo * debug_info = DebugInfo ( ) ;
for ( size_t i = 0 ; i < num_matches ; + + i )
{
const dw_offset_t die_offset = die_offsets [ i ] ;
type_die = debug_info - > GetDIEPtrWithCompileUnitHint ( die_offset , & type_cu ) ;
if ( type_die )
{
bool try_resolving_type = false ;
// Don't try and resolve the DIE we are looking for with the DIE itself!
const dw_tag_t type_tag = type_die - > Tag ( ) ;
// Make sure the tags match
if ( type_tag = = tag )
{
// The tags match, lets try resolving this type
try_resolving_type = true ;
}
else
{
// The tags don't match, but we need to watch our for a
// forward declaration for a struct and ("struct foo")
// ends up being a class ("class foo { ... };") or
// vice versa.
switch ( type_tag )
{
case DW_TAG_class_type :
// We had a "class foo", see if we ended up with a "struct foo { ... };"
try_resolving_type = ( tag = = DW_TAG_structure_type ) ;
break ;
case DW_TAG_structure_type :
// We had a "struct foo", see if we ended up with a "class foo { ... };"
try_resolving_type = ( tag = = DW_TAG_class_type ) ;
break ;
default :
// Tags don't match, don't event try to resolve
// using this type whose name matches....
break ;
}
}
if ( try_resolving_type )
{
DWARFDeclContext type_dwarf_decl_ctx ;
type_die - > GetDWARFDeclContext ( this , type_cu , type_dwarf_decl_ctx ) ;
if ( log )
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s') trying die=0x%8.8x (%s) " ,
DW_TAG_value_to_name ( dwarf_decl_ctx [ 0 ] . tag ) ,
dwarf_decl_ctx . GetQualifiedName ( ) ,
type_die - > GetOffset ( ) ,
type_dwarf_decl_ctx . GetQualifiedName ( ) ) ;
}
// Make sure the decl contexts match all the way up
if ( dwarf_decl_ctx = = type_dwarf_decl_ctx )
{
Type * resolved_type = ResolveType ( type_cu , type_die , false ) ;
if ( resolved_type & & resolved_type ! = DIE_IS_BEING_PARSED )
{
type_sp = resolved_type - > shared_from_this ( ) ;
break ;
}
}
}
else
{
if ( log )
{
std : : string qualified_name ;
type_die - > GetQualifiedName ( this , type_cu , qualified_name ) ;
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s') ignoring die=0x%8.8x (%s) " ,
DW_TAG_value_to_name ( dwarf_decl_ctx [ 0 ] . tag ) ,
dwarf_decl_ctx . GetQualifiedName ( ) ,
type_die - > GetOffset ( ) ,
qualified_name . c_str ( ) ) ;
}
}
}
else
{
if ( m_using_apple_tables )
{
GetObjectFile ( ) - > GetModule ( ) - > ReportErrorIfModifyDetected ( " the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s') \n " ,
die_offset , type_name . GetCString ( ) ) ;
}
}
}
}
}
}
return type_sp ;
}
bool
SymbolFileDWARF : : CopyUniqueClassMethodTypes ( SymbolFileDWARF * src_symfile ,
Type * class_type ,
DWARFCompileUnit * src_cu ,
const DWARFDebugInfoEntry * src_class_die ,
DWARFCompileUnit * dst_cu ,
const DWARFDebugInfoEntry * dst_class_die ,
2014-11-25 16:00:58 -05:00
DWARFDIECollection & failures )
2013-08-23 13:46:38 -04:00
{
if ( ! class_type | | ! src_cu | | ! src_class_die | | ! dst_cu | | ! dst_class_die )
return false ;
if ( src_class_die - > Tag ( ) ! = dst_class_die - > Tag ( ) )
return false ;
// We need to complete the class type so we can get all of the method types
// parsed so we can then unique those types to their equivalent counterparts
// in "dst_cu" and "dst_class_die"
class_type - > GetClangFullType ( ) ;
const DWARFDebugInfoEntry * src_die ;
const DWARFDebugInfoEntry * dst_die ;
UniqueCStringMap < const DWARFDebugInfoEntry * > src_name_to_die ;
UniqueCStringMap < const DWARFDebugInfoEntry * > dst_name_to_die ;
UniqueCStringMap < const DWARFDebugInfoEntry * > src_name_to_die_artificial ;
UniqueCStringMap < const DWARFDebugInfoEntry * > dst_name_to_die_artificial ;
for ( src_die = src_class_die - > GetFirstChild ( ) ; src_die ! = NULL ; src_die = src_die - > GetSibling ( ) )
{
if ( src_die - > Tag ( ) = = DW_TAG_subprogram )
{
// Make sure this is a declaration and not a concrete instance by looking
// for DW_AT_declaration set to 1. Sometimes concrete function instances
// are placed inside the class definitions and shouldn't be included in
// the list of things are are tracking here.
if ( src_die - > GetAttributeValueAsUnsigned ( src_symfile , src_cu , DW_AT_declaration , 0 ) = = 1 )
{
const char * src_name = src_die - > GetMangledName ( src_symfile , src_cu ) ;
if ( src_name )
{
ConstString src_const_name ( src_name ) ;
if ( src_die - > GetAttributeValueAsUnsigned ( src_symfile , src_cu , DW_AT_artificial , 0 ) )
src_name_to_die_artificial . Append ( src_const_name . GetCString ( ) , src_die ) ;
else
src_name_to_die . Append ( src_const_name . GetCString ( ) , src_die ) ;
}
}
}
}
for ( dst_die = dst_class_die - > GetFirstChild ( ) ; dst_die ! = NULL ; dst_die = dst_die - > GetSibling ( ) )
{
if ( dst_die - > Tag ( ) = = DW_TAG_subprogram )
{
// Make sure this is a declaration and not a concrete instance by looking
// for DW_AT_declaration set to 1. Sometimes concrete function instances
// are placed inside the class definitions and shouldn't be included in
// the list of things are are tracking here.
if ( dst_die - > GetAttributeValueAsUnsigned ( this , dst_cu , DW_AT_declaration , 0 ) = = 1 )
{
const char * dst_name = dst_die - > GetMangledName ( this , dst_cu ) ;
if ( dst_name )
{
ConstString dst_const_name ( dst_name ) ;
if ( dst_die - > GetAttributeValueAsUnsigned ( this , dst_cu , DW_AT_artificial , 0 ) )
dst_name_to_die_artificial . Append ( dst_const_name . GetCString ( ) , dst_die ) ;
else
dst_name_to_die . Append ( dst_const_name . GetCString ( ) , dst_die ) ;
}
}
}
}
const uint32_t src_size = src_name_to_die . GetSize ( ) ;
const uint32_t dst_size = dst_name_to_die . GetSize ( ) ;
Log * log ( LogChannelDWARF : : GetLogIfAny ( DWARF_LOG_DEBUG_INFO | DWARF_LOG_TYPE_COMPLETION ) ) ;
// Is everything kosher so we can go through the members at top speed?
bool fast_path = true ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( src_size ! = dst_size )
{
if ( src_size ! = 0 & & dst_size ! = 0 )
{
if ( log )
log - > Printf ( " warning: trying to unique class DIE 0x%8.8x to 0x%8.8x, but they didn't have the same size (src=%d, dst=%d) " ,
src_class_die - > GetOffset ( ) ,
dst_class_die - > GetOffset ( ) ,
src_size ,
dst_size ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
fast_path = false ;
}
uint32_t idx ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( fast_path )
{
for ( idx = 0 ; idx < src_size ; + + idx )
{
src_die = src_name_to_die . GetValueAtIndexUnchecked ( idx ) ;
dst_die = dst_name_to_die . GetValueAtIndexUnchecked ( idx ) ;
if ( src_die - > Tag ( ) ! = dst_die - > Tag ( ) )
{
if ( log )
log - > Printf ( " warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) tags didn't match 0x%8.8x (%s) " ,
src_class_die - > GetOffset ( ) ,
dst_class_die - > GetOffset ( ) ,
src_die - > GetOffset ( ) ,
DW_TAG_value_to_name ( src_die - > Tag ( ) ) ,
dst_die - > GetOffset ( ) ,
DW_TAG_value_to_name ( src_die - > Tag ( ) ) ) ;
fast_path = false ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
const char * src_name = src_die - > GetMangledName ( src_symfile , src_cu ) ;
const char * dst_name = dst_die - > GetMangledName ( this , dst_cu ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
// Make sure the names match
if ( src_name = = dst_name | | ( strcmp ( src_name , dst_name ) = = 0 ) )
continue ;
if ( log )
log - > Printf ( " warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) names didn't match 0x%8.8x (%s) " ,
src_class_die - > GetOffset ( ) ,
dst_class_die - > GetOffset ( ) ,
src_die - > GetOffset ( ) ,
src_name ,
dst_die - > GetOffset ( ) ,
dst_name ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
fast_path = false ;
}
}
// Now do the work of linking the DeclContexts and Types.
if ( fast_path )
{
// We can do this quickly. Just run across the tables index-for-index since
// we know each node has matching names and tags.
for ( idx = 0 ; idx < src_size ; + + idx )
{
src_die = src_name_to_die . GetValueAtIndexUnchecked ( idx ) ;
dst_die = dst_name_to_die . GetValueAtIndexUnchecked ( idx ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
clang : : DeclContext * src_decl_ctx = src_symfile - > m_die_to_decl_ctx [ src_die ] ;
if ( src_decl_ctx )
{
if ( log )
2014-11-25 16:00:58 -05:00
log - > Printf ( " uniquing decl context %p from 0x%8.8x for 0x%8.8x " ,
static_cast < void * > ( src_decl_ctx ) ,
src_die - > GetOffset ( ) , dst_die - > GetOffset ( ) ) ;
2013-08-23 13:46:38 -04:00
LinkDeclContextToDIE ( src_decl_ctx , dst_die ) ;
}
else
{
if ( log )
2014-11-25 16:00:58 -05:00
log - > Printf ( " warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found " ,
src_die - > GetOffset ( ) , dst_die - > GetOffset ( ) ) ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
Type * src_child_type = m_die_to_type [ src_die ] ;
if ( src_child_type )
{
if ( log )
2014-11-25 16:00:58 -05:00
log - > Printf ( " uniquing type %p (uid=0x% " PRIx64 " ) from 0x%8.8x for 0x%8.8x " ,
static_cast < void * > ( src_child_type ) ,
src_child_type - > GetID ( ) ,
src_die - > GetOffset ( ) , dst_die - > GetOffset ( ) ) ;
2013-08-23 13:46:38 -04:00
m_die_to_type [ dst_die ] = src_child_type ;
}
else
{
if ( log )
log - > Printf ( " warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found " , src_die - > GetOffset ( ) , dst_die - > GetOffset ( ) ) ;
}
}
}
else
{
// We must do this slowly. For each member of the destination, look
// up a member in the source with the same name, check its tag, and
// unique them if everything matches up. Report failures.
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! src_name_to_die . IsEmpty ( ) & & ! dst_name_to_die . IsEmpty ( ) )
{
src_name_to_die . Sort ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
for ( idx = 0 ; idx < dst_size ; + + idx )
{
const char * dst_name = dst_name_to_die . GetCStringAtIndex ( idx ) ;
dst_die = dst_name_to_die . GetValueAtIndexUnchecked ( idx ) ;
src_die = src_name_to_die . Find ( dst_name , NULL ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( src_die & & ( src_die - > Tag ( ) = = dst_die - > Tag ( ) ) )
{
clang : : DeclContext * src_decl_ctx = src_symfile - > m_die_to_decl_ctx [ src_die ] ;
if ( src_decl_ctx )
{
if ( log )
2014-11-25 16:00:58 -05:00
log - > Printf ( " uniquing decl context %p from 0x%8.8x for 0x%8.8x " ,
static_cast < void * > ( src_decl_ctx ) ,
src_die - > GetOffset ( ) ,
dst_die - > GetOffset ( ) ) ;
2013-08-23 13:46:38 -04:00
LinkDeclContextToDIE ( src_decl_ctx , dst_die ) ;
}
else
{
if ( log )
log - > Printf ( " warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found " , src_die - > GetOffset ( ) , dst_die - > GetOffset ( ) ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
Type * src_child_type = m_die_to_type [ src_die ] ;
if ( src_child_type )
{
if ( log )
2014-11-25 16:00:58 -05:00
log - > Printf ( " uniquing type %p (uid=0x% " PRIx64 " ) from 0x%8.8x for 0x%8.8x " ,
static_cast < void * > ( src_child_type ) ,
src_child_type - > GetID ( ) ,
src_die - > GetOffset ( ) ,
dst_die - > GetOffset ( ) ) ;
2013-08-23 13:46:38 -04:00
m_die_to_type [ dst_die ] = src_child_type ;
}
else
{
if ( log )
log - > Printf ( " warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found " , src_die - > GetOffset ( ) , dst_die - > GetOffset ( ) ) ;
}
}
else
{
if ( log )
log - > Printf ( " warning: couldn't find a match for 0x%8.8x " , dst_die - > GetOffset ( ) ) ;
2014-11-25 16:00:58 -05:00
failures . Append ( dst_die ) ;
2013-08-23 13:46:38 -04:00
}
}
}
}
const uint32_t src_size_artificial = src_name_to_die_artificial . GetSize ( ) ;
const uint32_t dst_size_artificial = dst_name_to_die_artificial . GetSize ( ) ;
UniqueCStringMap < const DWARFDebugInfoEntry * > name_to_die_artificial_not_in_src ;
if ( src_size_artificial & & dst_size_artificial )
{
dst_name_to_die_artificial . Sort ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
for ( idx = 0 ; idx < src_size_artificial ; + + idx )
{
const char * src_name_artificial = src_name_to_die_artificial . GetCStringAtIndex ( idx ) ;
src_die = src_name_to_die_artificial . GetValueAtIndexUnchecked ( idx ) ;
dst_die = dst_name_to_die_artificial . Find ( src_name_artificial , NULL ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( dst_die )
{
// Both classes have the artificial types, link them
clang : : DeclContext * src_decl_ctx = m_die_to_decl_ctx [ src_die ] ;
if ( src_decl_ctx )
{
if ( log )
2014-11-25 16:00:58 -05:00
log - > Printf ( " uniquing decl context %p from 0x%8.8x for 0x%8.8x " ,
static_cast < void * > ( src_decl_ctx ) ,
src_die - > GetOffset ( ) , dst_die - > GetOffset ( ) ) ;
2013-08-23 13:46:38 -04:00
LinkDeclContextToDIE ( src_decl_ctx , dst_die ) ;
}
else
{
if ( log )
log - > Printf ( " warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found " , src_die - > GetOffset ( ) , dst_die - > GetOffset ( ) ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
Type * src_child_type = m_die_to_type [ src_die ] ;
if ( src_child_type )
{
if ( log )
2014-11-25 16:00:58 -05:00
log - > Printf ( " uniquing type %p (uid=0x% " PRIx64 " ) from 0x%8.8x for 0x%8.8x " ,
static_cast < void * > ( src_child_type ) ,
src_child_type - > GetID ( ) ,
src_die - > GetOffset ( ) , dst_die - > GetOffset ( ) ) ;
2013-08-23 13:46:38 -04:00
m_die_to_type [ dst_die ] = src_child_type ;
}
else
{
if ( log )
log - > Printf ( " warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found " , src_die - > GetOffset ( ) , dst_die - > GetOffset ( ) ) ;
}
}
}
}
if ( dst_size_artificial )
{
for ( idx = 0 ; idx < dst_size_artificial ; + + idx )
{
const char * dst_name_artificial = dst_name_to_die_artificial . GetCStringAtIndex ( idx ) ;
dst_die = dst_name_to_die_artificial . GetValueAtIndexUnchecked ( idx ) ;
if ( log )
log - > Printf ( " warning: need to create artificial method for 0x%8.8x for method '%s' " , dst_die - > GetOffset ( ) , dst_name_artificial ) ;
2014-11-25 16:00:58 -05:00
failures . Append ( dst_die ) ;
2013-08-23 13:46:38 -04:00
}
}
2014-11-25 16:00:58 -05:00
return ( failures . Size ( ) ! = 0 ) ;
2013-08-23 13:46:38 -04:00
}
TypeSP
SymbolFileDWARF : : ParseType ( const SymbolContext & sc , DWARFCompileUnit * dwarf_cu , const DWARFDebugInfoEntry * die , bool * type_is_new_ptr )
{
TypeSP type_sp ;
if ( type_is_new_ptr )
* type_is_new_ptr = false ;
2014-11-25 16:00:58 -05:00
# if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
2013-08-23 13:46:38 -04:00
static DIEStack g_die_stack ;
DIEStack : : ScopedPopper scoped_die_logger ( g_die_stack ) ;
# endif
AccessType accessibility = eAccessNone ;
if ( die ! = NULL )
{
Log * log ( LogChannelDWARF : : GetLogIfAll ( DWARF_LOG_DEBUG_INFO ) ) ;
if ( log )
{
const DWARFDebugInfoEntry * context_die ;
clang : : DeclContext * context = GetClangDeclContextContainingDIE ( dwarf_cu , die , & context_die ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log , " SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die 0x%8.8x)) %s name = '%s') " ,
2014-11-25 16:00:58 -05:00
die - > GetOffset ( ) ,
static_cast < void * > ( context ) ,
context_die - > GetOffset ( ) ,
DW_TAG_value_to_name ( die - > Tag ( ) ) ,
die - > GetName ( this , dwarf_cu ) ) ;
# if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
2013-08-23 13:46:38 -04:00
scoped_die_logger . Push ( dwarf_cu , die ) ;
g_die_stack . LogDIEs ( log , this ) ;
# endif
}
//
// Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
// if (log && dwarf_cu)
// {
// StreamString s;
// die->DumpLocation (this, dwarf_cu, s);
// GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDwarf::%s %s", __FUNCTION__, s.GetData());
//
// }
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
Type * type_ptr = m_die_to_type . lookup ( die ) ;
TypeList * type_list = GetTypeList ( ) ;
if ( type_ptr = = NULL )
{
ClangASTContext & ast = GetClangASTContext ( ) ;
if ( type_is_new_ptr )
* type_is_new_ptr = true ;
const dw_tag_t tag = die - > Tag ( ) ;
bool is_forward_declaration = false ;
DWARFDebugInfoEntry : : Attributes attributes ;
const char * type_name_cstr = NULL ;
ConstString type_name_const_str ;
Type : : ResolveState resolve_state = Type : : eResolveStateUnresolved ;
uint64_t byte_size = 0 ;
Declaration decl ;
Type : : EncodingDataType encoding_data_type = Type : : eEncodingIsUID ;
ClangASTType clang_type ;
2014-11-25 16:00:58 -05:00
DWARFFormValue form_value ;
2013-08-23 13:46:38 -04:00
dw_attr_t attr ;
switch ( tag )
{
case DW_TAG_base_type :
case DW_TAG_pointer_type :
case DW_TAG_reference_type :
case DW_TAG_rvalue_reference_type :
case DW_TAG_typedef :
case DW_TAG_const_type :
case DW_TAG_restrict_type :
case DW_TAG_volatile_type :
case DW_TAG_unspecified_type :
{
// Set a bit that lets us know that we are currently parsing this
m_die_to_type [ die ] = DIE_IS_BEING_PARSED ;
const size_t num_attributes = die - > GetAttributes ( this , dwarf_cu , NULL , attributes ) ;
uint32_t encoding = 0 ;
lldb : : user_id_t encoding_uid = LLDB_INVALID_UID ;
if ( num_attributes > 0 )
{
uint32_t i ;
for ( i = 0 ; i < num_attributes ; + + i )
{
attr = attributes . AttributeAtIndex ( i ) ;
if ( attributes . ExtractFormValueAtIndex ( this , i , form_value ) )
{
switch ( attr )
{
case DW_AT_decl_file : decl . SetFile ( sc . comp_unit - > GetSupportFiles ( ) . GetFileSpecAtIndex ( form_value . Unsigned ( ) ) ) ; break ;
case DW_AT_decl_line : decl . SetLine ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_decl_column : decl . SetColumn ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_name :
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
type_name_cstr = form_value . AsCString ( & get_debug_str_data ( ) ) ;
// Work around a bug in llvm-gcc where they give a name to a reference type which doesn't
// include the "&"...
if ( tag = = DW_TAG_reference_type )
{
if ( strchr ( type_name_cstr , ' & ' ) = = NULL )
type_name_cstr = NULL ;
}
if ( type_name_cstr )
type_name_const_str . SetCString ( type_name_cstr ) ;
break ;
case DW_AT_byte_size : byte_size = form_value . Unsigned ( ) ; break ;
case DW_AT_encoding : encoding = form_value . Unsigned ( ) ; break ;
2015-02-06 16:38:51 -05:00
case DW_AT_type : encoding_uid = form_value . Reference ( ) ; break ;
2013-08-23 13:46:38 -04:00
default :
case DW_AT_sibling :
break ;
}
}
}
}
2013-11-06 11:48:53 -05:00
DEBUG_PRINTF ( " 0x%8.8 " PRIx64 " : %s ( \" %s \" ) type => 0x%8.8lx \n " , MakeUserID ( die - > GetOffset ( ) ) , DW_TAG_value_to_name ( tag ) , type_name_cstr , encoding_uid ) ;
2013-08-23 13:46:38 -04:00
switch ( tag )
{
default :
break ;
case DW_TAG_unspecified_type :
if ( strcmp ( type_name_cstr , " nullptr_t " ) = = 0 | |
strcmp ( type_name_cstr , " decltype(nullptr) " ) = = 0 )
{
resolve_state = Type : : eResolveStateFull ;
clang_type = ast . GetBasicType ( eBasicTypeNullPtr ) ;
break ;
}
// Fall through to base type below in case we can handle the type there...
case DW_TAG_base_type :
resolve_state = Type : : eResolveStateFull ;
clang_type = ast . GetBuiltinTypeForDWARFEncodingAndBitSize ( type_name_cstr ,
encoding ,
byte_size * 8 ) ;
break ;
case DW_TAG_pointer_type : encoding_data_type = Type : : eEncodingIsPointerUID ; break ;
case DW_TAG_reference_type : encoding_data_type = Type : : eEncodingIsLValueReferenceUID ; break ;
case DW_TAG_rvalue_reference_type : encoding_data_type = Type : : eEncodingIsRValueReferenceUID ; break ;
case DW_TAG_typedef : encoding_data_type = Type : : eEncodingIsTypedefUID ; break ;
case DW_TAG_const_type : encoding_data_type = Type : : eEncodingIsConstUID ; break ;
case DW_TAG_restrict_type : encoding_data_type = Type : : eEncodingIsRestrictUID ; break ;
case DW_TAG_volatile_type : encoding_data_type = Type : : eEncodingIsVolatileUID ; break ;
}
if ( ! clang_type & & ( encoding_data_type = = Type : : eEncodingIsPointerUID | | encoding_data_type = = Type : : eEncodingIsTypedefUID ) & & sc . comp_unit ! = NULL )
{
bool translation_unit_is_objc = ( sc . comp_unit - > GetLanguage ( ) = = eLanguageTypeObjC | | sc . comp_unit - > GetLanguage ( ) = = eLanguageTypeObjC_plus_plus ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( translation_unit_is_objc )
{
if ( type_name_cstr ! = NULL )
{
static ConstString g_objc_type_name_id ( " id " ) ;
static ConstString g_objc_type_name_Class ( " Class " ) ;
static ConstString g_objc_type_name_selector ( " SEL " ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( type_name_const_str = = g_objc_type_name_id )
{
if ( log )
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log , " SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'id' built-in type. " ,
die - > GetOffset ( ) ,
DW_TAG_value_to_name ( die - > Tag ( ) ) ,
die - > GetName ( this , dwarf_cu ) ) ;
clang_type = ast . GetBasicType ( eBasicTypeObjCID ) ;
encoding_data_type = Type : : eEncodingIsUID ;
encoding_uid = LLDB_INVALID_UID ;
resolve_state = Type : : eResolveStateFull ;
}
else if ( type_name_const_str = = g_objc_type_name_Class )
{
if ( log )
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log , " SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'Class' built-in type. " ,
die - > GetOffset ( ) ,
DW_TAG_value_to_name ( die - > Tag ( ) ) ,
die - > GetName ( this , dwarf_cu ) ) ;
clang_type = ast . GetBasicType ( eBasicTypeObjCClass ) ;
encoding_data_type = Type : : eEncodingIsUID ;
encoding_uid = LLDB_INVALID_UID ;
resolve_state = Type : : eResolveStateFull ;
}
else if ( type_name_const_str = = g_objc_type_name_selector )
{
if ( log )
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log , " SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'selector' built-in type. " ,
die - > GetOffset ( ) ,
DW_TAG_value_to_name ( die - > Tag ( ) ) ,
die - > GetName ( this , dwarf_cu ) ) ;
clang_type = ast . GetBasicType ( eBasicTypeObjCSel ) ;
encoding_data_type = Type : : eEncodingIsUID ;
encoding_uid = LLDB_INVALID_UID ;
resolve_state = Type : : eResolveStateFull ;
}
}
else if ( encoding_data_type = = Type : : eEncodingIsPointerUID & & encoding_uid ! = LLDB_INVALID_UID )
{
// Clang sometimes erroneously emits id as objc_object*. In that case we fix up the type to "id".
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
DWARFDebugInfoEntry * encoding_die = dwarf_cu - > GetDIEPtr ( encoding_uid ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( encoding_die & & encoding_die - > Tag ( ) = = DW_TAG_structure_type )
2014-11-25 16:00:58 -05:00
{
2013-08-23 13:46:38 -04:00
if ( const char * struct_name = encoding_die - > GetAttributeValueAsString ( this , dwarf_cu , DW_AT_name , NULL ) )
{
if ( ! strcmp ( struct_name , " objc_object " ) )
{
if ( log )
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log , " SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is 'objc_object*', which we overrode to 'id'. " ,
die - > GetOffset ( ) ,
DW_TAG_value_to_name ( die - > Tag ( ) ) ,
die - > GetName ( this , dwarf_cu ) ) ;
clang_type = ast . GetBasicType ( eBasicTypeObjCID ) ;
encoding_data_type = Type : : eEncodingIsUID ;
encoding_uid = LLDB_INVALID_UID ;
resolve_state = Type : : eResolveStateFull ;
}
}
}
}
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
type_sp . reset ( new Type ( MakeUserID ( die - > GetOffset ( ) ) ,
this ,
type_name_const_str ,
byte_size ,
NULL ,
encoding_uid ,
encoding_data_type ,
& decl ,
clang_type ,
resolve_state ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
m_die_to_type [ die ] = type_sp . get ( ) ;
// Type* encoding_type = GetUniquedTypeForDIEOffset(encoding_uid, type_sp, NULL, 0, 0, false);
// if (encoding_type != NULL)
// {
// if (encoding_type != DIE_IS_BEING_PARSED)
// type_sp->SetEncodingType(encoding_type);
// else
// m_indirect_fixups.push_back(type_sp.get());
// }
}
break ;
case DW_TAG_structure_type :
case DW_TAG_union_type :
case DW_TAG_class_type :
{
// Set a bit that lets us know that we are currently parsing this
m_die_to_type [ die ] = DIE_IS_BEING_PARSED ;
bool byte_size_valid = false ;
LanguageType class_language = eLanguageTypeUnknown ;
bool is_complete_objc_class = false ;
//bool struct_is_class = false;
const size_t num_attributes = die - > GetAttributes ( this , dwarf_cu , NULL , attributes ) ;
if ( num_attributes > 0 )
{
uint32_t i ;
for ( i = 0 ; i < num_attributes ; + + i )
{
attr = attributes . AttributeAtIndex ( i ) ;
if ( attributes . ExtractFormValueAtIndex ( this , i , form_value ) )
{
switch ( attr )
{
case DW_AT_decl_file :
if ( dwarf_cu - > DW_AT_decl_file_attributes_are_invalid ( ) )
2013-11-06 11:48:53 -05:00
{
// llvm-gcc outputs invalid DW_AT_decl_file attributes that always
// point to the compile unit file, so we clear this invalid value
// so that we can still unique types efficiently.
2013-08-23 13:46:38 -04:00
decl . SetFile ( FileSpec ( " <invalid> " , false ) ) ;
2013-11-06 11:48:53 -05:00
}
2013-08-23 13:46:38 -04:00
else
decl . SetFile ( sc . comp_unit - > GetSupportFiles ( ) . GetFileSpecAtIndex ( form_value . Unsigned ( ) ) ) ;
break ;
case DW_AT_decl_line :
decl . SetLine ( form_value . Unsigned ( ) ) ;
break ;
case DW_AT_decl_column :
decl . SetColumn ( form_value . Unsigned ( ) ) ;
break ;
case DW_AT_name :
type_name_cstr = form_value . AsCString ( & get_debug_str_data ( ) ) ;
type_name_const_str . SetCString ( type_name_cstr ) ;
break ;
case DW_AT_byte_size :
byte_size = form_value . Unsigned ( ) ;
byte_size_valid = true ;
break ;
case DW_AT_accessibility :
accessibility = DW_ACCESS_to_AccessType ( form_value . Unsigned ( ) ) ;
break ;
case DW_AT_declaration :
is_forward_declaration = form_value . Boolean ( ) ;
break ;
case DW_AT_APPLE_runtime_class :
class_language = ( LanguageType ) form_value . Signed ( ) ;
break ;
case DW_AT_APPLE_objc_complete_type :
is_complete_objc_class = form_value . Signed ( ) ;
break ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
case DW_AT_allocated :
case DW_AT_associated :
case DW_AT_data_location :
case DW_AT_description :
case DW_AT_start_scope :
case DW_AT_visibility :
default :
case DW_AT_sibling :
break ;
}
}
}
}
2014-11-25 16:00:58 -05:00
// UniqueDWARFASTType is large, so don't create a local variables on the
// stack, put it on the heap. This function is often called recursively
// and clang isn't good and sharing the stack space for variables in different blocks.
std : : unique_ptr < UniqueDWARFASTType > unique_ast_entry_ap ( new UniqueDWARFASTType ( ) ) ;
2013-08-23 13:46:38 -04:00
// Only try and unique the type if it has a name.
if ( type_name_const_str & &
GetUniqueDWARFASTTypeMap ( ) . Find ( type_name_const_str ,
this ,
dwarf_cu ,
die ,
decl ,
byte_size_valid ? byte_size : - 1 ,
2014-11-25 16:00:58 -05:00
* unique_ast_entry_ap ) )
2013-08-23 13:46:38 -04:00
{
// We have already parsed this type or from another
// compile unit. GCC loves to use the "one definition
// rule" which can result in multiple definitions
// of the same class over and over in each compile
// unit.
2014-11-25 16:00:58 -05:00
type_sp = unique_ast_entry_ap - > m_type_sp ;
2013-08-23 13:46:38 -04:00
if ( type_sp )
{
m_die_to_type [ die ] = type_sp . get ( ) ;
return type_sp ;
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
DEBUG_PRINTF ( " 0x%8.8 " PRIx64 " : %s ( \" %s \" ) \n " , MakeUserID ( die - > GetOffset ( ) ) , DW_TAG_value_to_name ( tag ) , type_name_cstr ) ;
int tag_decl_kind = - 1 ;
AccessType default_accessibility = eAccessNone ;
if ( tag = = DW_TAG_structure_type )
{
tag_decl_kind = clang : : TTK_Struct ;
default_accessibility = eAccessPublic ;
}
else if ( tag = = DW_TAG_union_type )
{
tag_decl_kind = clang : : TTK_Union ;
default_accessibility = eAccessPublic ;
}
else if ( tag = = DW_TAG_class_type )
{
tag_decl_kind = clang : : TTK_Class ;
default_accessibility = eAccessPrivate ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( byte_size_valid & & byte_size = = 0 & & type_name_cstr & &
die - > HasChildren ( ) = = false & &
sc . comp_unit - > GetLanguage ( ) = = eLanguageTypeObjC )
{
// Work around an issue with clang at the moment where
// forward declarations for objective C classes are emitted
// as:
// DW_TAG_structure_type [2]
// DW_AT_name( "ForwardObjcClass" )
// DW_AT_byte_size( 0x00 )
// DW_AT_decl_file( "..." )
// DW_AT_decl_line( 1 )
//
// Note that there is no DW_AT_declaration and there are
// no children, and the byte size is zero.
is_forward_declaration = true ;
}
if ( class_language = = eLanguageTypeObjC | |
class_language = = eLanguageTypeObjC_plus_plus )
{
if ( ! is_complete_objc_class & & Supports_DW_AT_APPLE_objc_complete_type ( dwarf_cu ) )
{
// We have a valid eSymbolTypeObjCClass class symbol whose
// name matches the current objective C class that we
// are trying to find and this DIE isn't the complete
// definition (we checked is_complete_objc_class above and
// know it is false), so the real definition is in here somewhere
type_sp = FindCompleteObjCDefinitionTypeForDIE ( die , type_name_const_str , true ) ;
if ( ! type_sp & & GetDebugMapSymfile ( ) )
{
// We weren't able to find a full declaration in
// this DWARF, see if we have a declaration anywhere
// else...
type_sp = m_debug_map_symfile - > FindCompleteObjCDefinitionTypeForDIE ( die , type_name_const_str , true ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( type_sp )
{
if ( log )
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF(%p) - 0x%8.8x: %s type \" %s \" is an incomplete objc type, complete type is 0x%8.8 " PRIx64 ,
2014-11-25 16:00:58 -05:00
static_cast < void * > ( this ) ,
2013-08-23 13:46:38 -04:00
die - > GetOffset ( ) ,
DW_TAG_value_to_name ( tag ) ,
type_name_cstr ,
type_sp - > GetID ( ) ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
// We found a real definition for this type elsewhere
// so lets use it and cache the fact that we found
// a complete type for this die
m_die_to_type [ die ] = type_sp . get ( ) ;
return type_sp ;
}
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( is_forward_declaration )
{
// We have a forward declaration to a type and we need
// to try and find a full declaration. We look in the
// current type index just in case we have a forward
// declaration followed by an actual declarations in the
// DWARF. If this fails, we need to look elsewhere...
if ( log )
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF(%p) - 0x%8.8x: %s type \" %s \" is a forward declaration, trying to find complete type " ,
2014-11-25 16:00:58 -05:00
static_cast < void * > ( this ) ,
2013-08-23 13:46:38 -04:00
die - > GetOffset ( ) ,
DW_TAG_value_to_name ( tag ) ,
type_name_cstr ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
DWARFDeclContext die_decl_ctx ;
die - > GetDWARFDeclContext ( this , dwarf_cu , die_decl_ctx ) ;
//type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, type_name_const_str);
type_sp = FindDefinitionTypeForDWARFDeclContext ( die_decl_ctx ) ;
if ( ! type_sp & & GetDebugMapSymfile ( ) )
{
// We weren't able to find a full declaration in
// this DWARF, see if we have a declaration anywhere
// else...
type_sp = m_debug_map_symfile - > FindDefinitionTypeForDWARFDeclContext ( die_decl_ctx ) ;
}
if ( type_sp )
{
if ( log )
{
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF(%p) - 0x%8.8x: %s type \" %s \" is a forward declaration, complete type is 0x%8.8 " PRIx64 ,
2014-11-25 16:00:58 -05:00
static_cast < void * > ( this ) ,
2013-08-23 13:46:38 -04:00
die - > GetOffset ( ) ,
DW_TAG_value_to_name ( tag ) ,
type_name_cstr ,
type_sp - > GetID ( ) ) ;
}
// We found a real definition for this type elsewhere
// so lets use it and cache the fact that we found
// a complete type for this die
m_die_to_type [ die ] = type_sp . get ( ) ;
return type_sp ;
}
}
assert ( tag_decl_kind ! = - 1 ) ;
bool clang_type_was_created = false ;
clang_type . SetClangType ( ast . getASTContext ( ) , m_forward_decl_die_to_clang_type . lookup ( die ) ) ;
if ( ! clang_type )
{
const DWARFDebugInfoEntry * decl_ctx_die ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
clang : : DeclContext * decl_ctx = GetClangDeclContextContainingDIE ( dwarf_cu , die , & decl_ctx_die ) ;
if ( accessibility = = eAccessNone & & decl_ctx )
{
// Check the decl context that contains this class/struct/union.
2014-11-25 16:00:58 -05:00
// If it is a class we must give it an accessibility.
2013-08-23 13:46:38 -04:00
const clang : : Decl : : Kind containing_decl_kind = decl_ctx - > getDeclKind ( ) ;
if ( DeclKindIsCXXClass ( containing_decl_kind ) )
accessibility = default_accessibility ;
}
ClangASTMetadata metadata ;
metadata . SetUserID ( MakeUserID ( die - > GetOffset ( ) ) ) ;
metadata . SetIsDynamicCXXType ( ClassOrStructIsVirtual ( dwarf_cu , die ) ) ;
if ( type_name_cstr & & strchr ( type_name_cstr , ' < ' ) )
{
ClangASTContext : : TemplateParameterInfos template_param_infos ;
if ( ParseTemplateParameterInfos ( dwarf_cu , die , template_param_infos ) )
{
clang : : ClassTemplateDecl * class_template_decl = ParseClassTemplateDecl ( decl_ctx ,
accessibility ,
type_name_cstr ,
tag_decl_kind ,
template_param_infos ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
clang : : ClassTemplateSpecializationDecl * class_specialization_decl = ast . CreateClassTemplateSpecializationDecl ( decl_ctx ,
class_template_decl ,
tag_decl_kind ,
template_param_infos ) ;
clang_type = ast . CreateClassTemplateSpecializationType ( class_specialization_decl ) ;
clang_type_was_created = true ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
GetClangASTContext ( ) . SetMetadata ( class_template_decl , metadata ) ;
GetClangASTContext ( ) . SetMetadata ( class_specialization_decl , metadata ) ;
}
}
if ( ! clang_type_was_created )
{
clang_type_was_created = true ;
clang_type = ast . CreateRecordType ( decl_ctx ,
accessibility ,
type_name_cstr ,
tag_decl_kind ,
class_language ,
& metadata ) ;
}
}
// Store a forward declaration to this class type in case any
// parameters in any class methods need it for the clang
// types for function prototypes.
LinkDeclContextToDIE ( clang_type . GetDeclContextForType ( ) , die ) ;
type_sp . reset ( new Type ( MakeUserID ( die - > GetOffset ( ) ) ,
this ,
type_name_const_str ,
byte_size ,
NULL ,
LLDB_INVALID_UID ,
Type : : eEncodingIsUID ,
& decl ,
clang_type ,
Type : : eResolveStateForward ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
type_sp - > SetIsCompleteObjCClass ( is_complete_objc_class ) ;
// Add our type to the unique type map so we don't
// end up creating many copies of the same type over
// and over in the ASTContext for our module
2014-11-25 16:00:58 -05:00
unique_ast_entry_ap - > m_type_sp = type_sp ;
unique_ast_entry_ap - > m_symfile = this ;
unique_ast_entry_ap - > m_cu = dwarf_cu ;
unique_ast_entry_ap - > m_die = die ;
unique_ast_entry_ap - > m_declaration = decl ;
unique_ast_entry_ap - > m_byte_size = byte_size ;
2013-08-23 13:46:38 -04:00
GetUniqueDWARFASTTypeMap ( ) . Insert ( type_name_const_str ,
2014-11-25 16:00:58 -05:00
* unique_ast_entry_ap ) ;
2013-08-23 13:46:38 -04:00
if ( is_forward_declaration & & die - > HasChildren ( ) )
{
// Check to see if the DIE actually has a definition, some version of GCC will
// emit DIEs with DW_AT_declaration set to true, but yet still have subprogram,
// members, or inheritance, so we can't trust it
const DWARFDebugInfoEntry * child_die = die - > GetFirstChild ( ) ;
while ( child_die )
{
switch ( child_die - > Tag ( ) )
{
case DW_TAG_inheritance :
case DW_TAG_subprogram :
case DW_TAG_member :
case DW_TAG_APPLE_property :
2014-02-18 11:23:10 -05:00
case DW_TAG_class_type :
case DW_TAG_structure_type :
case DW_TAG_enumeration_type :
case DW_TAG_typedef :
case DW_TAG_union_type :
2013-08-23 13:46:38 -04:00
child_die = NULL ;
is_forward_declaration = false ;
break ;
default :
child_die = child_die - > GetSibling ( ) ;
break ;
}
}
}
if ( ! is_forward_declaration )
{
// Always start the definition for a class type so that
// if the class has child classes or types that require
// the class to be created for use as their decl contexts
// the class will be ready to accept these child definitions.
if ( die - > HasChildren ( ) = = false )
{
// No children for this struct/union/class, lets finish it
clang_type . StartTagDeclarationDefinition ( ) ;
clang_type . CompleteTagDeclarationDefinition ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( tag = = DW_TAG_structure_type ) // this only applies in C
{
clang : : RecordDecl * record_decl = clang_type . GetAsRecordDecl ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( record_decl )
2014-11-25 16:00:58 -05:00
m_record_decl_to_layout_map . insert ( std : : make_pair ( record_decl , LayoutInfo ( ) ) ) ;
2013-08-23 13:46:38 -04:00
}
}
else if ( clang_type_was_created )
{
// Start the definition if the class is not objective C since
// the underlying decls respond to isCompleteDefinition(). Objective
2014-11-25 16:00:58 -05:00
// C decls don't respond to isCompleteDefinition() so we can't
// start the declaration definition right away. For C++ class/union/structs
2013-08-23 13:46:38 -04:00
// we want to start the definition in case the class is needed as the
// declaration context for a contained class or type without the need
// to complete that type..
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( class_language ! = eLanguageTypeObjC & &
class_language ! = eLanguageTypeObjC_plus_plus )
clang_type . StartTagDeclarationDefinition ( ) ;
// Leave this as a forward declaration until we need
// to know the details of the type. lldb_private::Type
// will automatically call the SymbolFile virtual function
// "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition(Type *)"
// When the definition needs to be defined.
m_forward_decl_die_to_clang_type [ die ] = clang_type . GetOpaqueQualType ( ) ;
m_forward_decl_clang_type_to_die [ clang_type . RemoveFastQualifiers ( ) . GetOpaqueQualType ( ) ] = die ;
clang_type . SetHasExternalStorage ( true ) ;
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
}
break ;
case DW_TAG_enumeration_type :
{
// Set a bit that lets us know that we are currently parsing this
m_die_to_type [ die ] = DIE_IS_BEING_PARSED ;
lldb : : user_id_t encoding_uid = DW_INVALID_OFFSET ;
const size_t num_attributes = die - > GetAttributes ( this , dwarf_cu , NULL , attributes ) ;
if ( num_attributes > 0 )
{
uint32_t i ;
for ( i = 0 ; i < num_attributes ; + + i )
{
attr = attributes . AttributeAtIndex ( i ) ;
if ( attributes . ExtractFormValueAtIndex ( this , i , form_value ) )
{
switch ( attr )
{
case DW_AT_decl_file : decl . SetFile ( sc . comp_unit - > GetSupportFiles ( ) . GetFileSpecAtIndex ( form_value . Unsigned ( ) ) ) ; break ;
case DW_AT_decl_line : decl . SetLine ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_decl_column : decl . SetColumn ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_name :
type_name_cstr = form_value . AsCString ( & get_debug_str_data ( ) ) ;
type_name_const_str . SetCString ( type_name_cstr ) ;
break ;
2015-02-06 16:38:51 -05:00
case DW_AT_type : encoding_uid = form_value . Reference ( ) ; break ;
2013-08-23 13:46:38 -04:00
case DW_AT_byte_size : byte_size = form_value . Unsigned ( ) ; break ;
case DW_AT_accessibility : break ; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
case DW_AT_declaration : break ; //is_forward_declaration = form_value.Boolean(); break;
case DW_AT_allocated :
case DW_AT_associated :
case DW_AT_bit_stride :
case DW_AT_byte_stride :
case DW_AT_data_location :
case DW_AT_description :
case DW_AT_start_scope :
case DW_AT_visibility :
case DW_AT_specification :
case DW_AT_abstract_origin :
case DW_AT_sibling :
break ;
}
}
}
DEBUG_PRINTF ( " 0x%8.8 " PRIx64 " : %s ( \" %s \" ) \n " , MakeUserID ( die - > GetOffset ( ) ) , DW_TAG_value_to_name ( tag ) , type_name_cstr ) ;
ClangASTType enumerator_clang_type ;
clang_type . SetClangType ( ast . getASTContext ( ) , m_forward_decl_die_to_clang_type . lookup ( die ) ) ;
if ( ! clang_type )
{
if ( encoding_uid ! = DW_INVALID_OFFSET )
{
Type * enumerator_type = ResolveTypeUID ( encoding_uid ) ;
if ( enumerator_type )
enumerator_clang_type = enumerator_type - > GetClangFullType ( ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! enumerator_clang_type )
enumerator_clang_type = ast . GetBuiltinTypeForDWARFEncodingAndBitSize ( NULL ,
DW_ATE_signed ,
byte_size * 8 ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
clang_type = ast . CreateEnumerationType ( type_name_cstr ,
GetClangDeclContextContainingDIE ( dwarf_cu , die , NULL ) ,
decl ,
enumerator_clang_type ) ;
}
else
{
enumerator_clang_type = clang_type . GetEnumerationIntegerType ( ) ;
}
LinkDeclContextToDIE ( clang_type . GetDeclContextForType ( ) , die ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
type_sp . reset ( new Type ( MakeUserID ( die - > GetOffset ( ) ) ,
this ,
type_name_const_str ,
byte_size ,
NULL ,
encoding_uid ,
Type : : eEncodingIsUID ,
& decl ,
clang_type ,
Type : : eResolveStateForward ) ) ;
clang_type . StartTagDeclarationDefinition ( ) ;
if ( die - > HasChildren ( ) )
{
SymbolContext cu_sc ( GetCompUnitForDWARFCompUnit ( dwarf_cu ) ) ;
bool is_signed = false ;
enumerator_clang_type . IsIntegerType ( is_signed ) ;
ParseChildEnumerators ( cu_sc , clang_type , is_signed , type_sp - > GetByteSize ( ) , dwarf_cu , die ) ;
}
clang_type . CompleteTagDeclarationDefinition ( ) ;
}
}
break ;
case DW_TAG_inlined_subroutine :
case DW_TAG_subprogram :
case DW_TAG_subroutine_type :
{
// Set a bit that lets us know that we are currently parsing this
m_die_to_type [ die ] = DIE_IS_BEING_PARSED ;
//const char *mangled = NULL;
dw_offset_t type_die_offset = DW_INVALID_OFFSET ;
bool is_variadic = false ;
bool is_inline = false ;
bool is_static = false ;
bool is_virtual = false ;
bool is_explicit = false ;
bool is_artificial = false ;
dw_offset_t specification_die_offset = DW_INVALID_OFFSET ;
dw_offset_t abstract_origin_die_offset = DW_INVALID_OFFSET ;
dw_offset_t object_pointer_die_offset = DW_INVALID_OFFSET ;
unsigned type_quals = 0 ;
clang : : StorageClass storage = clang : : SC_None ; //, Extern, Static, PrivateExtern
const size_t num_attributes = die - > GetAttributes ( this , dwarf_cu , NULL , attributes ) ;
if ( num_attributes > 0 )
{
uint32_t i ;
for ( i = 0 ; i < num_attributes ; + + i )
{
attr = attributes . AttributeAtIndex ( i ) ;
if ( attributes . ExtractFormValueAtIndex ( this , i , form_value ) )
{
switch ( attr )
{
case DW_AT_decl_file : decl . SetFile ( sc . comp_unit - > GetSupportFiles ( ) . GetFileSpecAtIndex ( form_value . Unsigned ( ) ) ) ; break ;
case DW_AT_decl_line : decl . SetLine ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_decl_column : decl . SetColumn ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_name :
type_name_cstr = form_value . AsCString ( & get_debug_str_data ( ) ) ;
type_name_const_str . SetCString ( type_name_cstr ) ;
break ;
case DW_AT_linkage_name :
case DW_AT_MIPS_linkage_name : break ; // mangled = form_value.AsCString(&get_debug_str_data()); break;
2015-02-06 16:38:51 -05:00
case DW_AT_type : type_die_offset = form_value . Reference ( ) ; break ;
2013-08-23 13:46:38 -04:00
case DW_AT_accessibility : accessibility = DW_ACCESS_to_AccessType ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_declaration : break ; // is_forward_declaration = form_value.Boolean(); break;
case DW_AT_inline : is_inline = form_value . Boolean ( ) ; break ;
case DW_AT_virtuality : is_virtual = form_value . Boolean ( ) ; break ;
case DW_AT_explicit : is_explicit = form_value . Boolean ( ) ; break ;
case DW_AT_artificial : is_artificial = form_value . Boolean ( ) ; break ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
case DW_AT_external :
if ( form_value . Unsigned ( ) )
{
if ( storage = = clang : : SC_None )
storage = clang : : SC_Extern ;
else
storage = clang : : SC_PrivateExtern ;
}
break ;
case DW_AT_specification :
2015-02-06 16:38:51 -05:00
specification_die_offset = form_value . Reference ( ) ;
2013-08-23 13:46:38 -04:00
break ;
case DW_AT_abstract_origin :
2015-02-06 16:38:51 -05:00
abstract_origin_die_offset = form_value . Reference ( ) ;
2013-08-23 13:46:38 -04:00
break ;
case DW_AT_object_pointer :
2015-02-06 16:38:51 -05:00
object_pointer_die_offset = form_value . Reference ( ) ;
2013-08-23 13:46:38 -04:00
break ;
case DW_AT_allocated :
case DW_AT_associated :
case DW_AT_address_class :
case DW_AT_calling_convention :
case DW_AT_data_location :
case DW_AT_elemental :
case DW_AT_entry_pc :
case DW_AT_frame_base :
case DW_AT_high_pc :
case DW_AT_low_pc :
case DW_AT_prototyped :
case DW_AT_pure :
case DW_AT_ranges :
case DW_AT_recursive :
case DW_AT_return_addr :
case DW_AT_segment :
case DW_AT_start_scope :
case DW_AT_static_link :
case DW_AT_trampoline :
case DW_AT_visibility :
case DW_AT_vtable_elem_location :
case DW_AT_description :
case DW_AT_sibling :
break ;
}
}
}
}
std : : string object_pointer_name ;
if ( object_pointer_die_offset ! = DW_INVALID_OFFSET )
{
// Get the name from the object pointer die
StreamString s ;
if ( DWARFDebugInfoEntry : : GetName ( this , dwarf_cu , object_pointer_die_offset , s ) )
{
object_pointer_name . assign ( s . GetData ( ) ) ;
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
DEBUG_PRINTF ( " 0x%8.8 " PRIx64 " : %s ( \" %s \" ) \n " , MakeUserID ( die - > GetOffset ( ) ) , DW_TAG_value_to_name ( tag ) , type_name_cstr ) ;
ClangASTType return_clang_type ;
Type * func_type = NULL ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( type_die_offset ! = DW_INVALID_OFFSET )
func_type = ResolveTypeUID ( type_die_offset ) ;
if ( func_type )
return_clang_type = func_type - > GetClangForwardType ( ) ;
else
return_clang_type = ast . GetBasicType ( eBasicTypeVoid ) ;
std : : vector < ClangASTType > function_param_types ;
std : : vector < clang : : ParmVarDecl * > function_param_decls ;
// Parse the function children for the parameters
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
const DWARFDebugInfoEntry * decl_ctx_die = NULL ;
clang : : DeclContext * containing_decl_ctx = GetClangDeclContextContainingDIE ( dwarf_cu , die , & decl_ctx_die ) ;
const clang : : Decl : : Kind containing_decl_kind = containing_decl_ctx - > getDeclKind ( ) ;
const bool is_cxx_method = DeclKindIsCXXClass ( containing_decl_kind ) ;
// Start off static. This will be set to false in ParseChildParameters(...)
2014-11-25 16:00:58 -05:00
// if we find a "this" parameters as the first parameter
2013-08-23 13:46:38 -04:00
if ( is_cxx_method )
is_static = true ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( die - > HasChildren ( ) )
{
bool skip_artificial = true ;
ParseChildParameters ( sc ,
containing_decl_ctx ,
dwarf_cu ,
die ,
skip_artificial ,
is_static ,
2014-02-25 16:42:16 -05:00
is_variadic ,
2013-08-23 13:46:38 -04:00
function_param_types ,
function_param_decls ,
2014-11-25 16:00:58 -05:00
type_quals ) ;
2013-08-23 13:46:38 -04:00
}
// clang_type will get the function prototype clang type after this call
clang_type = ast . CreateFunctionType ( return_clang_type ,
function_param_types . data ( ) ,
function_param_types . size ( ) ,
is_variadic ,
type_quals ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
bool ignore_containing_context = false ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( type_name_cstr )
{
bool type_handled = false ;
if ( tag = = DW_TAG_subprogram )
{
ObjCLanguageRuntime : : MethodName objc_method ( type_name_cstr , true ) ;
if ( objc_method . IsValid ( true ) )
{
ClangASTType class_opaque_type ;
ConstString class_name ( objc_method . GetClassName ( ) ) ;
if ( class_name )
{
TypeSP complete_objc_class_type_sp ( FindCompleteObjCDefinitionTypeForDIE ( NULL , class_name , false ) ) ;
if ( complete_objc_class_type_sp )
{
ClangASTType type_clang_forward_type = complete_objc_class_type_sp - > GetClangForwardType ( ) ;
if ( type_clang_forward_type . IsObjCObjectOrInterfaceType ( ) )
class_opaque_type = type_clang_forward_type ;
}
}
if ( class_opaque_type )
{
// If accessibility isn't set to anything valid, assume public for
// now...
if ( accessibility = = eAccessNone )
accessibility = eAccessPublic ;
clang : : ObjCMethodDecl * objc_method_decl = class_opaque_type . AddMethodToObjCObjectType ( type_name_cstr ,
clang_type ,
accessibility ,
is_artificial ) ;
type_handled = objc_method_decl ! = NULL ;
if ( type_handled )
{
LinkDeclContextToDIE ( ClangASTContext : : GetAsDeclContext ( objc_method_decl ) , die ) ;
GetClangASTContext ( ) . SetMetadataAsUserID ( objc_method_decl , MakeUserID ( die - > GetOffset ( ) ) ) ;
}
else
{
GetObjectFile ( ) - > GetModule ( ) - > ReportError ( " {0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), please file a bug and attach the file at the start of this error message " ,
die - > GetOffset ( ) ,
tag ,
DW_TAG_value_to_name ( tag ) ) ;
}
}
}
else if ( is_cxx_method )
{
// Look at the parent of this DIE and see if is is
// a class or struct and see if this is actually a
// C++ method
Type * class_type = ResolveType ( dwarf_cu , decl_ctx_die ) ;
if ( class_type )
{
if ( class_type - > GetID ( ) ! = MakeUserID ( decl_ctx_die - > GetOffset ( ) ) )
{
// We uniqued the parent class of this function to another class
// so we now need to associate all dies under "decl_ctx_die" to
// DIEs in the DIE for "class_type"...
SymbolFileDWARF * class_symfile = NULL ;
DWARFCompileUnitSP class_type_cu_sp ;
const DWARFDebugInfoEntry * class_type_die = NULL ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile ( ) ;
if ( debug_map_symfile )
{
class_symfile = debug_map_symfile - > GetSymbolFileByOSOIndex ( SymbolFileDWARFDebugMap : : GetOSOIndexFromUserID ( class_type - > GetID ( ) ) ) ;
class_type_die = class_symfile - > DebugInfo ( ) - > GetDIEPtr ( class_type - > GetID ( ) , & class_type_cu_sp ) ;
}
else
{
class_symfile = this ;
class_type_die = DebugInfo ( ) - > GetDIEPtr ( class_type - > GetID ( ) , & class_type_cu_sp ) ;
}
if ( class_type_die )
{
2014-11-25 16:00:58 -05:00
DWARFDIECollection failures ;
2013-08-23 13:46:38 -04:00
CopyUniqueClassMethodTypes ( class_symfile ,
class_type ,
class_type_cu_sp . get ( ) ,
class_type_die ,
dwarf_cu ,
decl_ctx_die ,
failures ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
// FIXME do something with these failures that's smarter than
// just dropping them on the ground. Unfortunately classes don't
// like having stuff added to them after their definitions are
// complete...
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
type_ptr = m_die_to_type [ die ] ;
if ( type_ptr & & type_ptr ! = DIE_IS_BEING_PARSED )
{
type_sp = type_ptr - > shared_from_this ( ) ;
break ;
}
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( specification_die_offset ! = DW_INVALID_OFFSET )
{
// We have a specification which we are going to base our function
// prototype off of, so we need this type to be completed so that the
// m_die_to_decl_ctx for the method in the specification has a valid
// clang decl context.
class_type - > GetClangForwardType ( ) ;
// If we have a specification, then the function type should have been
// made with the specification and not with this die.
DWARFCompileUnitSP spec_cu_sp ;
const DWARFDebugInfoEntry * spec_die = DebugInfo ( ) - > GetDIEPtr ( specification_die_offset , & spec_cu_sp ) ;
clang : : DeclContext * spec_clang_decl_ctx = GetClangDeclContextForDIE ( sc , dwarf_cu , spec_die ) ;
if ( spec_clang_decl_ctx )
{
LinkDeclContextToDIE ( spec_clang_decl_ctx , die ) ;
}
else
{
GetObjectFile ( ) - > GetModule ( ) - > ReportWarning ( " 0x%8.8 " PRIx64 " : DW_AT_specification(0x%8.8x) has no decl \n " ,
MakeUserID ( die - > GetOffset ( ) ) ,
specification_die_offset ) ;
}
type_handled = true ;
}
else if ( abstract_origin_die_offset ! = DW_INVALID_OFFSET )
{
// We have a specification which we are going to base our function
// prototype off of, so we need this type to be completed so that the
// m_die_to_decl_ctx for the method in the abstract origin has a valid
// clang decl context.
class_type - > GetClangForwardType ( ) ;
DWARFCompileUnitSP abs_cu_sp ;
const DWARFDebugInfoEntry * abs_die = DebugInfo ( ) - > GetDIEPtr ( abstract_origin_die_offset , & abs_cu_sp ) ;
clang : : DeclContext * abs_clang_decl_ctx = GetClangDeclContextForDIE ( sc , dwarf_cu , abs_die ) ;
if ( abs_clang_decl_ctx )
{
LinkDeclContextToDIE ( abs_clang_decl_ctx , die ) ;
}
else
{
GetObjectFile ( ) - > GetModule ( ) - > ReportWarning ( " 0x%8.8 " PRIx64 " : DW_AT_abstract_origin(0x%8.8x) has no decl \n " ,
MakeUserID ( die - > GetOffset ( ) ) ,
abstract_origin_die_offset ) ;
}
type_handled = true ;
}
else
{
ClangASTType class_opaque_type = class_type - > GetClangForwardType ( ) ;
if ( class_opaque_type . IsCXXClassType ( ) )
{
if ( class_opaque_type . IsBeingDefined ( ) )
{
// Neither GCC 4.2 nor clang++ currently set a valid accessibility
// in the DWARF for C++ methods... Default to public for now...
if ( accessibility = = eAccessNone )
accessibility = eAccessPublic ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! is_static & & ! die - > HasChildren ( ) )
{
// We have a C++ member function with no children (this pointer!)
// and clang will get mad if we try and make a function that isn't
// well formed in the DWARF, so we will just skip it...
type_handled = true ;
}
else
{
clang : : CXXMethodDecl * cxx_method_decl ;
// REMOVE THE CRASH DESCRIPTION BELOW
Host : : SetCrashDescriptionWithFormat ( " SymbolFileDWARF::ParseType() is adding a method %s to class %s in DIE 0x%8.8 " PRIx64 " from %s " ,
type_name_cstr ,
class_type - > GetName ( ) . GetCString ( ) ,
MakeUserID ( die - > GetOffset ( ) ) ,
m_obj_file - > GetFileSpec ( ) . GetPath ( ) . c_str ( ) ) ;
const bool is_attr_used = false ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
cxx_method_decl = class_opaque_type . AddMethodToCXXRecordType ( type_name_cstr ,
clang_type ,
accessibility ,
is_virtual ,
is_static ,
is_inline ,
is_explicit ,
is_attr_used ,
is_artificial ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
type_handled = cxx_method_decl ! = NULL ;
if ( type_handled )
{
LinkDeclContextToDIE ( ClangASTContext : : GetAsDeclContext ( cxx_method_decl ) , die ) ;
Host : : SetCrashDescription ( NULL ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
ClangASTMetadata metadata ;
metadata . SetUserID ( MakeUserID ( die - > GetOffset ( ) ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! object_pointer_name . empty ( ) )
{
metadata . SetObjectPtrName ( object_pointer_name . c_str ( ) ) ;
if ( log )
log - > Printf ( " Setting object pointer name: %s on method object %p. \n " ,
object_pointer_name . c_str ( ) ,
2014-11-25 16:00:58 -05:00
static_cast < void * > ( cxx_method_decl ) ) ;
2013-08-23 13:46:38 -04:00
}
GetClangASTContext ( ) . SetMetadata ( cxx_method_decl , metadata ) ;
}
else
{
ignore_containing_context = true ;
}
}
}
else
{
// We were asked to parse the type for a method in a class, yet the
// class hasn't been asked to complete itself through the
// clang::ExternalASTSource protocol, so we need to just have the
// class complete itself and do things the right way, then our
// DIE should then have an entry in the m_die_to_type map. First
// we need to modify the m_die_to_type so it doesn't think we are
// trying to parse this DIE anymore...
m_die_to_type [ die ] = NULL ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
// Now we get the full type to force our class type to complete itself
// using the clang::ExternalASTSource protocol which will parse all
// base classes and all methods (including the method for this DIE).
class_type - > GetClangFullType ( ) ;
// The type for this DIE should have been filled in the function call above
type_ptr = m_die_to_type [ die ] ;
if ( type_ptr & & type_ptr ! = DIE_IS_BEING_PARSED )
{
type_sp = type_ptr - > shared_from_this ( ) ;
break ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
// FIXME This is fixing some even uglier behavior but we really need to
// uniq the methods of each class as well as the class itself.
// <rdar://problem/11240464>
type_handled = true ;
}
}
}
}
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! type_handled )
{
// We just have a function that isn't part of a class
clang : : FunctionDecl * function_decl = ast . CreateFunctionDeclaration ( ignore_containing_context ? GetClangASTContext ( ) . GetTranslationUnitDecl ( ) : containing_decl_ctx ,
type_name_cstr ,
clang_type ,
storage ,
is_inline ) ;
// if (template_param_infos.GetSize() > 0)
// {
// clang::FunctionTemplateDecl *func_template_decl = ast.CreateFunctionTemplateDecl (containing_decl_ctx,
// function_decl,
// type_name_cstr,
// template_param_infos);
//
// ast.CreateFunctionTemplateSpecializationInfo (function_decl,
// func_template_decl,
// template_param_infos);
// }
// Add the decl to our DIE to decl context map
assert ( function_decl ) ;
LinkDeclContextToDIE ( function_decl , die ) ;
if ( ! function_param_decls . empty ( ) )
ast . SetFunctionParameters ( function_decl ,
& function_param_decls . front ( ) ,
function_param_decls . size ( ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
ClangASTMetadata metadata ;
metadata . SetUserID ( MakeUserID ( die - > GetOffset ( ) ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! object_pointer_name . empty ( ) )
{
metadata . SetObjectPtrName ( object_pointer_name . c_str ( ) ) ;
if ( log )
log - > Printf ( " Setting object pointer name: %s on function object %p. " ,
object_pointer_name . c_str ( ) ,
2014-11-25 16:00:58 -05:00
static_cast < void * > ( function_decl ) ) ;
2013-08-23 13:46:38 -04:00
}
GetClangASTContext ( ) . SetMetadata ( function_decl , metadata ) ;
}
}
type_sp . reset ( new Type ( MakeUserID ( die - > GetOffset ( ) ) ,
this ,
type_name_const_str ,
0 ,
NULL ,
LLDB_INVALID_UID ,
Type : : eEncodingIsUID ,
& decl ,
clang_type ,
Type : : eResolveStateFull ) ) ;
assert ( type_sp . get ( ) ) ;
}
break ;
case DW_TAG_array_type :
{
// Set a bit that lets us know that we are currently parsing this
m_die_to_type [ die ] = DIE_IS_BEING_PARSED ;
lldb : : user_id_t type_die_offset = DW_INVALID_OFFSET ;
int64_t first_index = 0 ;
uint32_t byte_stride = 0 ;
uint32_t bit_stride = 0 ;
bool is_vector = false ;
const size_t num_attributes = die - > GetAttributes ( this , dwarf_cu , NULL , attributes ) ;
if ( num_attributes > 0 )
{
uint32_t i ;
for ( i = 0 ; i < num_attributes ; + + i )
{
attr = attributes . AttributeAtIndex ( i ) ;
if ( attributes . ExtractFormValueAtIndex ( this , i , form_value ) )
{
switch ( attr )
{
case DW_AT_decl_file : decl . SetFile ( sc . comp_unit - > GetSupportFiles ( ) . GetFileSpecAtIndex ( form_value . Unsigned ( ) ) ) ; break ;
case DW_AT_decl_line : decl . SetLine ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_decl_column : decl . SetColumn ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_name :
type_name_cstr = form_value . AsCString ( & get_debug_str_data ( ) ) ;
type_name_const_str . SetCString ( type_name_cstr ) ;
break ;
2015-02-06 16:38:51 -05:00
case DW_AT_type : type_die_offset = form_value . Reference ( ) ; break ;
2013-08-23 13:46:38 -04:00
case DW_AT_byte_size : break ; // byte_size = form_value.Unsigned(); break;
case DW_AT_byte_stride : byte_stride = form_value . Unsigned ( ) ; break ;
case DW_AT_bit_stride : bit_stride = form_value . Unsigned ( ) ; break ;
case DW_AT_GNU_vector : is_vector = form_value . Boolean ( ) ; break ;
case DW_AT_accessibility : break ; // accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
case DW_AT_declaration : break ; // is_forward_declaration = form_value.Boolean(); break;
case DW_AT_allocated :
case DW_AT_associated :
case DW_AT_data_location :
case DW_AT_description :
case DW_AT_ordering :
case DW_AT_start_scope :
case DW_AT_visibility :
case DW_AT_specification :
case DW_AT_abstract_origin :
case DW_AT_sibling :
break ;
}
}
}
DEBUG_PRINTF ( " 0x%8.8 " PRIx64 " : %s ( \" %s \" ) \n " , MakeUserID ( die - > GetOffset ( ) ) , DW_TAG_value_to_name ( tag ) , type_name_cstr ) ;
Type * element_type = ResolveTypeUID ( type_die_offset ) ;
if ( element_type )
{
std : : vector < uint64_t > element_orders ;
ParseChildArrayInfo ( sc , dwarf_cu , die , first_index , element_orders , byte_stride , bit_stride ) ;
if ( byte_stride = = 0 & & bit_stride = = 0 )
byte_stride = element_type - > GetByteSize ( ) ;
ClangASTType array_element_type = element_type - > GetClangForwardType ( ) ;
uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride ;
2015-02-06 16:38:51 -05:00
if ( element_orders . size ( ) > 0 )
{
uint64_t num_elements = 0 ;
std : : vector < uint64_t > : : const_reverse_iterator pos ;
std : : vector < uint64_t > : : const_reverse_iterator end = element_orders . rend ( ) ;
for ( pos = element_orders . rbegin ( ) ; pos ! = end ; + + pos )
{
num_elements = * pos ;
clang_type = ast . CreateArrayType ( array_element_type ,
num_elements ,
is_vector ) ;
array_element_type = clang_type ;
array_element_bit_stride = num_elements ?
array_element_bit_stride * num_elements :
array_element_bit_stride ;
}
}
else
2013-08-23 13:46:38 -04:00
{
2015-02-06 16:38:51 -05:00
clang_type = ast . CreateArrayType ( array_element_type , 0 , is_vector ) ;
2013-08-23 13:46:38 -04:00
}
ConstString empty_name ;
type_sp . reset ( new Type ( MakeUserID ( die - > GetOffset ( ) ) ,
this ,
empty_name ,
array_element_bit_stride / 8 ,
NULL ,
type_die_offset ,
Type : : eEncodingIsUID ,
& decl ,
clang_type ,
Type : : eResolveStateFull ) ) ;
type_sp - > SetEncodingType ( element_type ) ;
}
}
}
break ;
case DW_TAG_ptr_to_member_type :
{
dw_offset_t type_die_offset = DW_INVALID_OFFSET ;
dw_offset_t containing_type_die_offset = DW_INVALID_OFFSET ;
const size_t num_attributes = die - > GetAttributes ( this , dwarf_cu , NULL , attributes ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( num_attributes > 0 ) {
uint32_t i ;
for ( i = 0 ; i < num_attributes ; + + i )
{
attr = attributes . AttributeAtIndex ( i ) ;
if ( attributes . ExtractFormValueAtIndex ( this , i , form_value ) )
{
switch ( attr )
{
case DW_AT_type :
2015-02-06 16:38:51 -05:00
type_die_offset = form_value . Reference ( ) ; break ;
2013-08-23 13:46:38 -04:00
case DW_AT_containing_type :
2015-02-06 16:38:51 -05:00
containing_type_die_offset = form_value . Reference ( ) ; break ;
2013-08-23 13:46:38 -04:00
}
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
Type * pointee_type = ResolveTypeUID ( type_die_offset ) ;
Type * class_type = ResolveTypeUID ( containing_type_die_offset ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
ClangASTType pointee_clang_type = pointee_type - > GetClangForwardType ( ) ;
ClangASTType class_clang_type = class_type - > GetClangLayoutType ( ) ;
clang_type = pointee_clang_type . CreateMemberPointerType ( class_clang_type ) ;
2015-02-08 20:44:09 -05:00
byte_size = clang_type . GetByteSize ( nullptr ) ;
2013-08-23 13:46:38 -04:00
type_sp . reset ( new Type ( MakeUserID ( die - > GetOffset ( ) ) ,
this ,
type_name_const_str ,
byte_size ,
NULL ,
LLDB_INVALID_UID ,
Type : : eEncodingIsUID ,
NULL ,
clang_type ,
Type : : eResolveStateForward ) ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
break ;
}
default :
GetObjectFile ( ) - > GetModule ( ) - > ReportError ( " {0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and attach the file at the start of this error message " ,
die - > GetOffset ( ) ,
tag ,
DW_TAG_value_to_name ( tag ) ) ;
break ;
}
if ( type_sp . get ( ) )
{
const DWARFDebugInfoEntry * sc_parent_die = GetParentSymbolContextDIE ( die ) ;
dw_tag_t sc_parent_tag = sc_parent_die ? sc_parent_die - > Tag ( ) : 0 ;
SymbolContextScope * symbol_context_scope = NULL ;
if ( sc_parent_tag = = DW_TAG_compile_unit )
{
symbol_context_scope = sc . comp_unit ;
}
2015-02-06 16:38:51 -05:00
else if ( sc . function ! = NULL & & sc_parent_die )
2013-08-23 13:46:38 -04:00
{
symbol_context_scope = sc . function - > GetBlock ( true ) . FindBlockByID ( MakeUserID ( sc_parent_die - > GetOffset ( ) ) ) ;
if ( symbol_context_scope = = NULL )
symbol_context_scope = sc . function ;
}
if ( symbol_context_scope ! = NULL )
{
type_sp - > SetSymbolContextScope ( symbol_context_scope ) ;
}
// We are ready to put this type into the uniqued list up at the module level
type_list - > Insert ( type_sp ) ;
m_die_to_type [ die ] = type_sp . get ( ) ;
}
}
else if ( type_ptr ! = DIE_IS_BEING_PARSED )
{
type_sp = type_ptr - > shared_from_this ( ) ;
}
}
return type_sp ;
}
size_t
SymbolFileDWARF : : ParseTypes
(
const SymbolContext & sc ,
DWARFCompileUnit * dwarf_cu ,
const DWARFDebugInfoEntry * die ,
bool parse_siblings ,
bool parse_children
)
{
size_t types_added = 0 ;
while ( die ! = NULL )
{
bool type_is_new = false ;
if ( ParseType ( sc , dwarf_cu , die , & type_is_new ) . get ( ) )
{
if ( type_is_new )
+ + types_added ;
}
if ( parse_children & & die - > HasChildren ( ) )
{
if ( die - > Tag ( ) = = DW_TAG_subprogram )
{
SymbolContext child_sc ( sc ) ;
child_sc . function = sc . comp_unit - > FindFunctionByUID ( MakeUserID ( die - > GetOffset ( ) ) ) . get ( ) ;
types_added + = ParseTypes ( child_sc , dwarf_cu , die - > GetFirstChild ( ) , true , true ) ;
}
else
types_added + = ParseTypes ( sc , dwarf_cu , die - > GetFirstChild ( ) , true , true ) ;
}
if ( parse_siblings )
die = die - > GetSibling ( ) ;
else
die = NULL ;
}
return types_added ;
}
size_t
SymbolFileDWARF : : ParseFunctionBlocks ( const SymbolContext & sc )
{
assert ( sc . comp_unit & & sc . function ) ;
size_t functions_added = 0 ;
DWARFCompileUnit * dwarf_cu = GetDWARFCompileUnit ( sc . comp_unit ) ;
if ( dwarf_cu )
{
dw_offset_t function_die_offset = sc . function - > GetID ( ) ;
const DWARFDebugInfoEntry * function_die = dwarf_cu - > GetDIEPtr ( function_die_offset ) ;
if ( function_die )
{
ParseFunctionBlocks ( sc , & sc . function - > GetBlock ( false ) , dwarf_cu , function_die , LLDB_INVALID_ADDRESS , 0 ) ;
}
}
return functions_added ;
}
size_t
SymbolFileDWARF : : ParseTypes ( const SymbolContext & sc )
{
// At least a compile unit must be valid
assert ( sc . comp_unit ) ;
size_t types_added = 0 ;
DWARFCompileUnit * dwarf_cu = GetDWARFCompileUnit ( sc . comp_unit ) ;
if ( dwarf_cu )
{
if ( sc . function )
{
dw_offset_t function_die_offset = sc . function - > GetID ( ) ;
const DWARFDebugInfoEntry * func_die = dwarf_cu - > GetDIEPtr ( function_die_offset ) ;
if ( func_die & & func_die - > HasChildren ( ) )
{
types_added = ParseTypes ( sc , dwarf_cu , func_die - > GetFirstChild ( ) , true , true ) ;
}
}
else
{
const DWARFDebugInfoEntry * dwarf_cu_die = dwarf_cu - > DIE ( ) ;
if ( dwarf_cu_die & & dwarf_cu_die - > HasChildren ( ) )
{
types_added = ParseTypes ( sc , dwarf_cu , dwarf_cu_die - > GetFirstChild ( ) , true , true ) ;
}
}
}
return types_added ;
}
size_t
SymbolFileDWARF : : ParseVariablesForContext ( const SymbolContext & sc )
{
if ( sc . comp_unit ! = NULL )
{
DWARFDebugInfo * info = DebugInfo ( ) ;
if ( info = = NULL )
return 0 ;
if ( sc . function )
{
DWARFCompileUnit * dwarf_cu = info - > GetCompileUnitContainingDIE ( sc . function - > GetID ( ) ) . get ( ) ;
if ( dwarf_cu = = NULL )
return 0 ;
const DWARFDebugInfoEntry * function_die = dwarf_cu - > GetDIEPtr ( sc . function - > GetID ( ) ) ;
dw_addr_t func_lo_pc = function_die - > GetAttributeValueAsUnsigned ( this , dwarf_cu , DW_AT_low_pc , LLDB_INVALID_ADDRESS ) ;
if ( func_lo_pc ! = LLDB_INVALID_ADDRESS )
{
const size_t num_variables = ParseVariables ( sc , dwarf_cu , func_lo_pc , function_die - > GetFirstChild ( ) , true , true ) ;
// Let all blocks know they have parse all their variables
sc . function - > GetBlock ( false ) . SetDidParseVariables ( true , true ) ;
return num_variables ;
}
}
else if ( sc . comp_unit )
{
DWARFCompileUnit * dwarf_cu = info - > GetCompileUnit ( sc . comp_unit - > GetID ( ) ) . get ( ) ;
if ( dwarf_cu = = NULL )
return 0 ;
uint32_t vars_added = 0 ;
VariableListSP variables ( sc . comp_unit - > GetVariableList ( false ) ) ;
if ( variables . get ( ) = = NULL )
{
variables . reset ( new VariableList ( ) ) ;
sc . comp_unit - > SetVariableList ( variables ) ;
DWARFCompileUnit * match_dwarf_cu = NULL ;
const DWARFDebugInfoEntry * die = NULL ;
DIEArray die_offsets ;
if ( m_using_apple_tables )
{
if ( m_apple_names_ap . get ( ) )
{
DWARFMappedHash : : DIEInfoArray hash_data_array ;
if ( m_apple_names_ap - > AppendAllDIEsInRange ( dwarf_cu - > GetOffset ( ) ,
dwarf_cu - > GetNextCompileUnitOffset ( ) ,
hash_data_array ) )
{
DWARFMappedHash : : ExtractDIEArray ( hash_data_array , die_offsets ) ;
}
}
}
else
{
// Index if we already haven't to make sure the compile units
// get indexed and make their global DIE index list
if ( ! m_indexed )
Index ( ) ;
m_global_index . FindAllEntriesForCompileUnit ( dwarf_cu - > GetOffset ( ) ,
dwarf_cu - > GetNextCompileUnitOffset ( ) ,
die_offsets ) ;
}
const size_t num_matches = die_offsets . size ( ) ;
if ( num_matches )
{
DWARFDebugInfo * debug_info = DebugInfo ( ) ;
for ( size_t i = 0 ; i < num_matches ; + + i )
{
const dw_offset_t die_offset = die_offsets [ i ] ;
die = debug_info - > GetDIEPtrWithCompileUnitHint ( die_offset , & match_dwarf_cu ) ;
if ( die )
{
VariableSP var_sp ( ParseVariableDIE ( sc , dwarf_cu , die , LLDB_INVALID_ADDRESS ) ) ;
if ( var_sp )
{
variables - > AddVariableIfUnique ( var_sp ) ;
+ + vars_added ;
}
}
else
{
if ( m_using_apple_tables )
{
GetObjectFile ( ) - > GetModule ( ) - > ReportErrorIfModifyDetected ( " the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x) \n " , die_offset ) ;
}
}
}
}
}
return vars_added ;
}
}
return 0 ;
}
VariableSP
SymbolFileDWARF : : ParseVariableDIE
(
const SymbolContext & sc ,
DWARFCompileUnit * dwarf_cu ,
const DWARFDebugInfoEntry * die ,
const lldb : : addr_t func_low_pc
)
{
VariableSP var_sp ( m_die_to_variable_sp [ die ] ) ;
if ( var_sp )
return var_sp ; // Already been parsed!
const dw_tag_t tag = die - > Tag ( ) ;
2013-11-06 11:48:53 -05:00
ModuleSP module = GetObjectFile ( ) - > GetModule ( ) ;
2013-08-23 13:46:38 -04:00
if ( ( tag = = DW_TAG_variable ) | |
( tag = = DW_TAG_constant ) | |
( tag = = DW_TAG_formal_parameter & & sc . function ) )
{
DWARFDebugInfoEntry : : Attributes attributes ;
const size_t num_attributes = die - > GetAttributes ( this , dwarf_cu , NULL , attributes ) ;
if ( num_attributes > 0 )
{
const char * name = NULL ;
const char * mangled = NULL ;
Declaration decl ;
uint32_t i ;
lldb : : user_id_t type_uid = LLDB_INVALID_UID ;
DWARFExpression location ;
bool is_external = false ;
bool is_artificial = false ;
bool location_is_const_value_data = false ;
bool has_explicit_location = false ;
2014-11-25 16:00:58 -05:00
DWARFFormValue const_value ;
2013-08-23 13:46:38 -04:00
//AccessType accessibility = eAccessNone;
for ( i = 0 ; i < num_attributes ; + + i )
{
dw_attr_t attr = attributes . AttributeAtIndex ( i ) ;
DWARFFormValue form_value ;
2015-02-06 16:38:51 -05:00
2013-08-23 13:46:38 -04:00
if ( attributes . ExtractFormValueAtIndex ( this , i , form_value ) )
{
switch ( attr )
{
case DW_AT_decl_file : decl . SetFile ( sc . comp_unit - > GetSupportFiles ( ) . GetFileSpecAtIndex ( form_value . Unsigned ( ) ) ) ; break ;
case DW_AT_decl_line : decl . SetLine ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_decl_column : decl . SetColumn ( form_value . Unsigned ( ) ) ; break ;
case DW_AT_name : name = form_value . AsCString ( & get_debug_str_data ( ) ) ; break ;
case DW_AT_linkage_name :
case DW_AT_MIPS_linkage_name : mangled = form_value . AsCString ( & get_debug_str_data ( ) ) ; break ;
2015-02-06 16:38:51 -05:00
case DW_AT_type : type_uid = form_value . Reference ( ) ; break ;
2013-08-23 13:46:38 -04:00
case DW_AT_external : is_external = form_value . Boolean ( ) ; break ;
case DW_AT_const_value :
// If we have already found a DW_AT_location attribute, ignore this attribute.
if ( ! has_explicit_location )
{
location_is_const_value_data = true ;
// The constant value will be either a block, a data value or a string.
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor & debug_info_data = get_debug_info_data ( ) ;
2013-08-23 13:46:38 -04:00
if ( DWARFFormValue : : IsBlockForm ( form_value . Form ( ) ) )
{
// Retrieve the value as a block expression.
uint32_t block_offset = form_value . BlockData ( ) - debug_info_data . GetDataStart ( ) ;
uint32_t block_length = form_value . Unsigned ( ) ;
2013-11-06 11:48:53 -05:00
location . CopyOpcodeData ( module , debug_info_data , block_offset , block_length ) ;
2013-08-23 13:46:38 -04:00
}
else if ( DWARFFormValue : : IsDataForm ( form_value . Form ( ) ) )
{
// Retrieve the value as a data expression.
2015-02-06 16:38:51 -05:00
const uint8_t * fixed_form_sizes = DWARFFormValue : : GetFixedFormSizesForAddressSize ( attributes . CompileUnitAtIndex ( i ) - > GetAddressByteSize ( ) , attributes . CompileUnitAtIndex ( i ) - > IsDWARF64 ( ) ) ;
2013-08-23 13:46:38 -04:00
uint32_t data_offset = attributes . DIEOffsetAtIndex ( i ) ;
uint32_t data_length = fixed_form_sizes [ form_value . Form ( ) ] ;
2014-11-25 16:00:58 -05:00
if ( data_length = = 0 )
{
const uint8_t * data_pointer = form_value . BlockData ( ) ;
if ( data_pointer )
{
2015-02-06 16:38:51 -05:00
form_value . Unsigned ( ) ;
2014-11-25 16:00:58 -05:00
}
else if ( DWARFFormValue : : IsDataForm ( form_value . Form ( ) ) )
{
// we need to get the byte size of the type later after we create the variable
const_value = form_value ;
}
}
else
location . CopyOpcodeData ( module , debug_info_data , data_offset , data_length ) ;
2013-08-23 13:46:38 -04:00
}
else
{
// Retrieve the value as a string expression.
if ( form_value . Form ( ) = = DW_FORM_strp )
{
2015-02-06 16:38:51 -05:00
const uint8_t * fixed_form_sizes = DWARFFormValue : : GetFixedFormSizesForAddressSize ( attributes . CompileUnitAtIndex ( i ) - > GetAddressByteSize ( ) , attributes . CompileUnitAtIndex ( i ) - > IsDWARF64 ( ) ) ;
2013-08-23 13:46:38 -04:00
uint32_t data_offset = attributes . DIEOffsetAtIndex ( i ) ;
uint32_t data_length = fixed_form_sizes [ form_value . Form ( ) ] ;
2013-11-06 11:48:53 -05:00
location . CopyOpcodeData ( module , debug_info_data , data_offset , data_length ) ;
2013-08-23 13:46:38 -04:00
}
else
{
const char * str = form_value . AsCString ( & debug_info_data ) ;
uint32_t string_offset = str - ( const char * ) debug_info_data . GetDataStart ( ) ;
uint32_t string_length = strlen ( str ) + 1 ;
2013-11-06 11:48:53 -05:00
location . CopyOpcodeData ( module , debug_info_data , string_offset , string_length ) ;
2013-08-23 13:46:38 -04:00
}
}
}
break ;
case DW_AT_location :
{
location_is_const_value_data = false ;
has_explicit_location = true ;
if ( form_value . BlockData ( ) )
{
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor & debug_info_data = get_debug_info_data ( ) ;
2013-08-23 13:46:38 -04:00
uint32_t block_offset = form_value . BlockData ( ) - debug_info_data . GetDataStart ( ) ;
uint32_t block_length = form_value . Unsigned ( ) ;
2013-11-06 11:48:53 -05:00
location . CopyOpcodeData ( module , get_debug_info_data ( ) , block_offset , block_length ) ;
2013-08-23 13:46:38 -04:00
}
else
{
2013-11-06 11:48:53 -05:00
const DWARFDataExtractor & debug_loc_data = get_debug_loc_data ( ) ;
2013-08-23 13:46:38 -04:00
const dw_offset_t debug_loc_offset = form_value . Unsigned ( ) ;
size_t loc_list_length = DWARFLocationList : : Size ( debug_loc_data , debug_loc_offset ) ;
if ( loc_list_length > 0 )
{
2013-11-06 11:48:53 -05:00
location . CopyOpcodeData ( module , debug_loc_data , debug_loc_offset , loc_list_length ) ;
2013-08-23 13:46:38 -04:00
assert ( func_low_pc ! = LLDB_INVALID_ADDRESS ) ;
2015-02-06 16:38:51 -05:00
location . SetLocationListSlide ( func_low_pc - attributes . CompileUnitAtIndex ( i ) - > GetBaseAddress ( ) ) ;
2013-08-23 13:46:38 -04:00
}
}
}
break ;
case DW_AT_artificial : is_artificial = form_value . Boolean ( ) ; break ;
case DW_AT_accessibility : break ; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
case DW_AT_declaration :
case DW_AT_description :
case DW_AT_endianity :
case DW_AT_segment :
case DW_AT_start_scope :
case DW_AT_visibility :
default :
case DW_AT_abstract_origin :
case DW_AT_sibling :
case DW_AT_specification :
break ;
}
}
}
ValueType scope = eValueTypeInvalid ;
const DWARFDebugInfoEntry * sc_parent_die = GetParentSymbolContextDIE ( die ) ;
dw_tag_t parent_tag = sc_parent_die ? sc_parent_die - > Tag ( ) : 0 ;
SymbolContextScope * symbol_context_scope = NULL ;
2015-07-03 12:57:06 -04:00
if ( ! mangled )
{
// LLDB relies on the mangled name (DW_TAG_linkage_name or DW_AT_MIPS_linkage_name) to
// generate fully qualified names of global variables with commands like "frame var j".
// For example, if j were an int variable holding a value 4 and declared in a namespace
// B which in turn is contained in a namespace A, the command "frame var j" returns
// "(int) A::B::j = 4". If the compiler does not emit a linkage name, we should be able
// to generate a fully qualified name from the declaration context.
if ( die - > GetParent ( ) - > Tag ( ) = = DW_TAG_compile_unit & &
LanguageRuntime : : LanguageIsCPlusPlus ( dwarf_cu - > GetLanguageType ( ) ) )
{
DWARFDeclContext decl_ctx ;
die - > GetDWARFDeclContext ( this , dwarf_cu , decl_ctx ) ;
mangled = decl_ctx . GetQualifiedNameAsConstString ( ) . GetCString ( ) ;
}
}
2013-08-23 13:46:38 -04:00
// DWARF doesn't specify if a DW_TAG_variable is a local, global
// or static variable, so we have to do a little digging by
2014-11-25 16:00:58 -05:00
// looking at the location of a variable to see if it contains
2013-08-23 13:46:38 -04:00
// a DW_OP_addr opcode _somewhere_ in the definition. I say
// somewhere because clang likes to combine small global variables
// into the same symbol and have locations like:
// DW_OP_addr(0x1000), DW_OP_constu(2), DW_OP_plus
// So if we don't have a DW_TAG_formal_parameter, we can look at
// the location to see if it contains a DW_OP_addr opcode, and
// then we can correctly classify our variables.
if ( tag = = DW_TAG_formal_parameter )
scope = eValueTypeVariableArgument ;
else
{
bool op_error = false ;
// Check if the location has a DW_OP_addr with any address value...
lldb : : addr_t location_DW_OP_addr = LLDB_INVALID_ADDRESS ;
if ( ! location_is_const_value_data )
{
location_DW_OP_addr = location . GetLocation_DW_OP_addr ( 0 , op_error ) ;
if ( op_error )
{
StreamString strm ;
location . DumpLocationForAddress ( & strm , eDescriptionLevelFull , 0 , 0 , NULL ) ;
GetObjectFile ( ) - > GetModule ( ) - > ReportError ( " 0x%8.8x: %s has an invalid location: %s " , die - > GetOffset ( ) , DW_TAG_value_to_name ( die - > Tag ( ) ) , strm . GetString ( ) . c_str ( ) ) ;
}
}
if ( location_DW_OP_addr ! = LLDB_INVALID_ADDRESS )
{
if ( is_external )
scope = eValueTypeVariableGlobal ;
else
scope = eValueTypeVariableStatic ;
SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile ( ) ;
if ( debug_map_symfile )
{
// When leaving the DWARF in the .o files on darwin,
// when we have a global variable that wasn't initialized,
// the .o file might not have allocated a virtual
// address for the global variable. In this case it will
// have created a symbol for the global variable
// that is undefined/data and external and the value will
// be the byte size of the variable. When we do the
// address map in SymbolFileDWARFDebugMap we rely on
// having an address, we need to do some magic here
// so we can get the correct address for our global
// variable. The address for all of these entries
// will be zero, and there will be an undefined symbol
// in this object file, and the executable will have
// a matching symbol with a good address. So here we
// dig up the correct address and replace it in the
// location for the variable, and set the variable's
// symbol context scope to be that of the main executable
// so the file address will resolve correctly.
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 ( ) ;
if ( debug_map_symtab )
{
Symbol * exe_symbol = debug_map_symtab - > FindFirstSymbolWithNameAndType ( const_name ,
eSymbolTypeData ,
Symtab : : eDebugYes ,
Symtab : : eVisibilityExtern ) ;
if ( exe_symbol )
{
if ( exe_symbol - > ValueIsAddress ( ) )
{
2015-07-03 12:57:06 -04:00
const addr_t exe_file_addr = exe_symbol - > GetAddressRef ( ) . GetFileAddress ( ) ;
2013-08-23 13:46:38 -04:00
if ( exe_file_addr ! = LLDB_INVALID_ADDRESS )
{
if ( location . Update_DW_OP_addr ( exe_file_addr ) )
{
linked_oso_file_addr = true ;
symbol_context_scope = exe_symbol ;
}
}
}
}
}
}
}
if ( ! linked_oso_file_addr )
{
// The DW_OP_addr is not zero, but it contains a .o file address which
// needs to be linked up correctly.
const lldb : : addr_t exe_file_addr = debug_map_symfile - > LinkOSOFileAddress ( this , location_DW_OP_addr ) ;
if ( exe_file_addr ! = LLDB_INVALID_ADDRESS )
{
// Update the file address for this variable
location . Update_DW_OP_addr ( exe_file_addr ) ;
}
else
{
// Variable didn't make it into the final executable
return var_sp ;
}
}
}
}
else
{
scope = eValueTypeVariableLocal ;
}
}
if ( symbol_context_scope = = NULL )
{
switch ( parent_tag )
{
case DW_TAG_subprogram :
case DW_TAG_inlined_subroutine :
case DW_TAG_lexical_block :
if ( sc . function )
{
symbol_context_scope = sc . function - > GetBlock ( true ) . FindBlockByID ( MakeUserID ( sc_parent_die - > GetOffset ( ) ) ) ;
if ( symbol_context_scope = = NULL )
symbol_context_scope = sc . function ;
}
break ;
default :
symbol_context_scope = sc . comp_unit ;
break ;
}
}
if ( symbol_context_scope )
{
2014-11-25 16:00:58 -05:00
SymbolFileTypeSP type_sp ( new SymbolFileType ( * this , type_uid ) ) ;
if ( const_value . Form ( ) & & type_sp & & type_sp - > GetType ( ) )
location . CopyOpcodeData ( const_value . Unsigned ( ) , type_sp - > GetType ( ) - > GetByteSize ( ) , dwarf_cu - > GetAddressByteSize ( ) ) ;
2013-08-23 13:46:38 -04:00
var_sp . reset ( new Variable ( MakeUserID ( die - > GetOffset ( ) ) ,
name ,
mangled ,
2014-11-25 16:00:58 -05:00
type_sp ,
2013-08-23 13:46:38 -04:00
scope ,
symbol_context_scope ,
& decl ,
location ,
is_external ,
is_artificial ) ) ;
var_sp - > SetLocationIsConstantValueData ( location_is_const_value_data ) ;
}
else
{
// Not ready to parse this variable yet. It might be a global
// or static variable that is in a function scope and the function
// in the symbol context wasn't filled in yet
return var_sp ;
}
}
// Cache var_sp even if NULL (the variable was just a specification or
// was missing vital information to be able to be displayed in the debugger
// (missing location due to optimization, etc)) so we don't re-parse
// this DIE over and over later...
m_die_to_variable_sp [ die ] = var_sp ;
}
return var_sp ;
}
const DWARFDebugInfoEntry *
SymbolFileDWARF : : FindBlockContainingSpecification ( dw_offset_t func_die_offset ,
dw_offset_t spec_block_die_offset ,
DWARFCompileUnit * * result_die_cu_handle )
{
// Give the concrete function die specified by "func_die_offset", find the
// concrete block whose DW_AT_specification or DW_AT_abstract_origin points
// to "spec_block_die_offset"
DWARFDebugInfo * info = DebugInfo ( ) ;
const DWARFDebugInfoEntry * die = info - > GetDIEPtrWithCompileUnitHint ( func_die_offset , result_die_cu_handle ) ;
if ( die )
{
assert ( * result_die_cu_handle ) ;
return FindBlockContainingSpecification ( * result_die_cu_handle , die , spec_block_die_offset , result_die_cu_handle ) ;
}
return NULL ;
}
const DWARFDebugInfoEntry *
SymbolFileDWARF : : FindBlockContainingSpecification ( DWARFCompileUnit * dwarf_cu ,
const DWARFDebugInfoEntry * die ,
dw_offset_t spec_block_die_offset ,
DWARFCompileUnit * * result_die_cu_handle )
{
if ( die )
{
switch ( die - > Tag ( ) )
{
case DW_TAG_subprogram :
case DW_TAG_inlined_subroutine :
case DW_TAG_lexical_block :
{
if ( die - > GetAttributeValueAsReference ( this , dwarf_cu , DW_AT_specification , DW_INVALID_OFFSET ) = = spec_block_die_offset )
{
* result_die_cu_handle = dwarf_cu ;
return die ;
}
if ( die - > GetAttributeValueAsReference ( this , dwarf_cu , DW_AT_abstract_origin , DW_INVALID_OFFSET ) = = spec_block_die_offset )
{
* result_die_cu_handle = dwarf_cu ;
return die ;
}
}
break ;
}
// Give the concrete function die specified by "func_die_offset", find the
// concrete block whose DW_AT_specification or DW_AT_abstract_origin points
// to "spec_block_die_offset"
for ( const DWARFDebugInfoEntry * child_die = die - > GetFirstChild ( ) ; child_die ! = NULL ; child_die = child_die - > GetSibling ( ) )
{
const DWARFDebugInfoEntry * result_die = FindBlockContainingSpecification ( dwarf_cu ,
child_die ,
spec_block_die_offset ,
result_die_cu_handle ) ;
if ( result_die )
return result_die ;
}
}
* result_die_cu_handle = NULL ;
return NULL ;
}
size_t
SymbolFileDWARF : : ParseVariables
(
const SymbolContext & sc ,
DWARFCompileUnit * dwarf_cu ,
const lldb : : addr_t func_low_pc ,
const DWARFDebugInfoEntry * orig_die ,
bool parse_siblings ,
bool parse_children ,
VariableList * cc_variable_list
)
{
if ( orig_die = = NULL )
return 0 ;
VariableListSP variable_list_sp ;
size_t vars_added = 0 ;
const DWARFDebugInfoEntry * die = orig_die ;
while ( die ! = NULL )
{
dw_tag_t tag = die - > Tag ( ) ;
// Check to see if we have already parsed this variable or constant?
if ( m_die_to_variable_sp [ die ] )
{
if ( cc_variable_list )
cc_variable_list - > AddVariableIfUnique ( m_die_to_variable_sp [ die ] ) ;
}
else
{
// We haven't already parsed it, lets do that now.
if ( ( tag = = DW_TAG_variable ) | |
( tag = = DW_TAG_constant ) | |
( tag = = DW_TAG_formal_parameter & & sc . function ) )
{
if ( variable_list_sp . get ( ) = = NULL )
{
const DWARFDebugInfoEntry * sc_parent_die = GetParentSymbolContextDIE ( orig_die ) ;
dw_tag_t parent_tag = sc_parent_die ? sc_parent_die - > Tag ( ) : 0 ;
switch ( parent_tag )
{
case DW_TAG_compile_unit :
if ( sc . comp_unit ! = NULL )
{
variable_list_sp = sc . comp_unit - > GetVariableList ( false ) ;
if ( variable_list_sp . get ( ) = = NULL )
{
variable_list_sp . reset ( new VariableList ( ) ) ;
sc . comp_unit - > SetVariableList ( variable_list_sp ) ;
}
}
else
{
GetObjectFile ( ) - > GetModule ( ) - > ReportError ( " parent 0x%8.8 " PRIx64 " %s with no valid compile unit in symbol context for 0x%8.8 " PRIx64 " %s. \n " ,
MakeUserID ( sc_parent_die - > GetOffset ( ) ) ,
DW_TAG_value_to_name ( parent_tag ) ,
MakeUserID ( orig_die - > GetOffset ( ) ) ,
DW_TAG_value_to_name ( orig_die - > Tag ( ) ) ) ;
}
break ;
case DW_TAG_subprogram :
case DW_TAG_inlined_subroutine :
case DW_TAG_lexical_block :
if ( sc . function ! = NULL )
{
// Check to see if we already have parsed the variables for the given scope
Block * block = sc . function - > GetBlock ( true ) . FindBlockByID ( MakeUserID ( sc_parent_die - > GetOffset ( ) ) ) ;
if ( block = = NULL )
{
// This must be a specification or abstract origin with
2014-11-25 16:00:58 -05:00
// a concrete block counterpart in the current function. We need
2013-08-23 13:46:38 -04:00
// to find the concrete block so we can correctly add the
// variable to it
DWARFCompileUnit * concrete_block_die_cu = dwarf_cu ;
const DWARFDebugInfoEntry * concrete_block_die = FindBlockContainingSpecification ( sc . function - > GetID ( ) ,
sc_parent_die - > GetOffset ( ) ,
& concrete_block_die_cu ) ;
if ( concrete_block_die )
block = sc . function - > GetBlock ( true ) . FindBlockByID ( MakeUserID ( concrete_block_die - > GetOffset ( ) ) ) ;
}
if ( block ! = NULL )
{
const bool can_create = false ;
variable_list_sp = block - > GetBlockVariableList ( can_create ) ;
if ( variable_list_sp . get ( ) = = NULL )
{
variable_list_sp . reset ( new VariableList ( ) ) ;
block - > SetVariableList ( variable_list_sp ) ;
}
}
}
break ;
default :
GetObjectFile ( ) - > GetModule ( ) - > ReportError ( " didn't find appropriate parent DIE for variable list for 0x%8.8 " PRIx64 " %s. \n " ,
MakeUserID ( orig_die - > GetOffset ( ) ) ,
DW_TAG_value_to_name ( orig_die - > Tag ( ) ) ) ;
break ;
}
}
if ( variable_list_sp )
{
VariableSP var_sp ( ParseVariableDIE ( sc , dwarf_cu , die , func_low_pc ) ) ;
if ( var_sp )
{
variable_list_sp - > AddVariableIfUnique ( var_sp ) ;
if ( cc_variable_list )
cc_variable_list - > AddVariableIfUnique ( var_sp ) ;
+ + vars_added ;
}
}
}
}
bool skip_children = ( sc . function = = NULL & & tag = = DW_TAG_subprogram ) ;
if ( ! skip_children & & parse_children & & die - > HasChildren ( ) )
{
vars_added + = ParseVariables ( sc , dwarf_cu , func_low_pc , die - > GetFirstChild ( ) , true , true , cc_variable_list ) ;
}
if ( parse_siblings )
die = die - > GetSibling ( ) ;
else
die = NULL ;
}
return vars_added ;
}
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
ConstString
SymbolFileDWARF : : GetPluginName ( )
{
return GetPluginNameStatic ( ) ;
}
uint32_t
SymbolFileDWARF : : GetPluginVersion ( )
{
return 1 ;
}
void
SymbolFileDWARF : : CompleteTagDecl ( void * baton , clang : : TagDecl * decl )
{
SymbolFileDWARF * symbol_file_dwarf = ( SymbolFileDWARF * ) baton ;
ClangASTType clang_type = symbol_file_dwarf - > GetClangASTContext ( ) . GetTypeForDecl ( decl ) ;
if ( clang_type )
symbol_file_dwarf - > ResolveClangOpaqueTypeDefinition ( clang_type ) ;
}
void
SymbolFileDWARF : : CompleteObjCInterfaceDecl ( void * baton , clang : : ObjCInterfaceDecl * decl )
{
SymbolFileDWARF * symbol_file_dwarf = ( SymbolFileDWARF * ) baton ;
ClangASTType clang_type = symbol_file_dwarf - > GetClangASTContext ( ) . GetTypeForDecl ( decl ) ;
if ( clang_type )
symbol_file_dwarf - > ResolveClangOpaqueTypeDefinition ( clang_type ) ;
}
void
SymbolFileDWARF : : DumpIndexes ( )
{
StreamFile s ( stdout , false ) ;
s . Printf ( " DWARF index for (%s) '%s': " ,
GetObjectFile ( ) - > GetModule ( ) - > GetArchitecture ( ) . GetArchitectureName ( ) ,
GetObjectFile ( ) - > GetFileSpec ( ) . GetPath ( ) . c_str ( ) ) ;
s . Printf ( " \n Function basenames: \n " ) ; m_function_basename_index . Dump ( & s ) ;
s . Printf ( " \n Function fullnames: \n " ) ; m_function_fullname_index . Dump ( & s ) ;
s . Printf ( " \n Function methods: \n " ) ; m_function_method_index . Dump ( & s ) ;
s . Printf ( " \n Function selectors: \n " ) ; m_function_selector_index . Dump ( & s ) ;
s . Printf ( " \n Objective C class selectors: \n " ) ; m_objc_class_selectors_index . Dump ( & s ) ;
s . Printf ( " \n Globals and statics: \n " ) ; m_global_index . Dump ( & s ) ;
s . Printf ( " \n Types: \n " ) ; m_type_index . Dump ( & s ) ;
s . Printf ( " \n Namepaces: \n " ) ; m_namespace_index . Dump ( & s ) ;
}
void
SymbolFileDWARF : : SearchDeclContext ( const clang : : DeclContext * decl_context ,
const char * name ,
llvm : : SmallVectorImpl < clang : : NamedDecl * > * results )
{
DeclContextToDIEMap : : iterator iter = m_decl_ctx_to_die . find ( decl_context ) ;
if ( iter = = m_decl_ctx_to_die . end ( ) )
return ;
for ( DIEPointerSet : : iterator pos = iter - > second . begin ( ) , end = iter - > second . end ( ) ; pos ! = end ; + + pos )
{
const DWARFDebugInfoEntry * context_die = * pos ;
if ( ! results )
return ;
DWARFDebugInfo * info = DebugInfo ( ) ;
DIEArray die_offsets ;
DWARFCompileUnit * dwarf_cu = NULL ;
const DWARFDebugInfoEntry * die = NULL ;
if ( m_using_apple_tables )
{
if ( m_apple_types_ap . get ( ) )
m_apple_types_ap - > FindByName ( name , die_offsets ) ;
}
else
{
if ( ! m_indexed )
Index ( ) ;
m_type_index . Find ( ConstString ( name ) , die_offsets ) ;
}
const size_t num_matches = die_offsets . size ( ) ;
if ( num_matches )
{
for ( size_t i = 0 ; i < num_matches ; + + i )
{
const dw_offset_t die_offset = die_offsets [ i ] ;
die = info - > GetDIEPtrWithCompileUnitHint ( die_offset , & dwarf_cu ) ;
if ( die - > GetParent ( ) ! = context_die )
continue ;
Type * matching_type = ResolveType ( dwarf_cu , die ) ;
clang : : QualType qual_type = matching_type - > GetClangForwardType ( ) . GetQualType ( ) ;
if ( const clang : : TagType * tag_type = llvm : : dyn_cast < clang : : TagType > ( qual_type . getTypePtr ( ) ) )
{
clang : : TagDecl * tag_decl = tag_type - > getDecl ( ) ;
results - > push_back ( tag_decl ) ;
}
else if ( const clang : : TypedefType * typedef_type = llvm : : dyn_cast < clang : : TypedefType > ( qual_type . getTypePtr ( ) ) )
{
clang : : TypedefNameDecl * typedef_decl = typedef_type - > getDecl ( ) ;
results - > push_back ( typedef_decl ) ;
}
}
}
}
}
void
SymbolFileDWARF : : FindExternalVisibleDeclsByName ( void * baton ,
const clang : : DeclContext * decl_context ,
clang : : DeclarationName decl_name ,
llvm : : SmallVectorImpl < clang : : NamedDecl * > * results )
{
switch ( decl_context - > getDeclKind ( ) )
{
case clang : : Decl : : Namespace :
case clang : : Decl : : TranslationUnit :
{
SymbolFileDWARF * symbol_file_dwarf = ( SymbolFileDWARF * ) baton ;
symbol_file_dwarf - > SearchDeclContext ( decl_context , decl_name . getAsString ( ) . c_str ( ) , results ) ;
}
break ;
default :
break ;
}
}
2015-07-03 12:57:06 -04:00
bool
SymbolFileDWARF : : 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
{
SymbolFileDWARF * symbol_file_dwarf = ( SymbolFileDWARF * ) baton ;
return symbol_file_dwarf - > LayoutRecordType ( record_decl , size , alignment , field_offsets , base_offsets , vbase_offsets ) ;
}
2015-07-03 12:57:06 -04:00
bool
SymbolFileDWARF : : LayoutRecordType ( const clang : : RecordDecl * record_decl , uint64_t & bit_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
{
Log * log ( LogChannelDWARF : : GetLogIfAll ( DWARF_LOG_DEBUG_INFO ) ) ;
RecordDeclToLayoutMap : : iterator pos = m_record_decl_to_layout_map . find ( record_decl ) ;
bool success = false ;
base_offsets . clear ( ) ;
vbase_offsets . clear ( ) ;
if ( pos ! = m_record_decl_to_layout_map . end ( ) )
{
bit_size = pos - > second . bit_size ;
alignment = pos - > second . alignment ;
field_offsets . swap ( pos - > second . field_offsets ) ;
base_offsets . swap ( pos - > second . base_offsets ) ;
vbase_offsets . swap ( pos - > second . vbase_offsets ) ;
m_record_decl_to_layout_map . erase ( pos ) ;
success = true ;
}
else
{
bit_size = 0 ;
alignment = 0 ;
field_offsets . clear ( ) ;
}
if ( log )
GetObjectFile ( ) - > GetModule ( ) - > LogMessage ( log ,
" SymbolFileDWARF::LayoutRecordType (record_decl = %p, bit_size = % " PRIu64 " , alignment = % " PRIu64 " , field_offsets[%u],base_offsets[%u], vbase_offsets[%u]) success = %i " ,
2014-11-25 16:00:58 -05:00
static_cast < const void * > ( record_decl ) ,
bit_size , alignment ,
static_cast < uint32_t > ( field_offsets . size ( ) ) ,
static_cast < uint32_t > ( base_offsets . size ( ) ) ,
static_cast < uint32_t > ( vbase_offsets . size ( ) ) ,
2013-08-23 13:46:38 -04:00
success ) ;
return success ;
}
SymbolFileDWARFDebugMap *
SymbolFileDWARF : : GetDebugMapSymfile ( )
{
if ( m_debug_map_symfile = = NULL & & ! m_debug_map_module_wp . expired ( ) )
{
lldb : : ModuleSP module_sp ( m_debug_map_module_wp . lock ( ) ) ;
if ( module_sp )
{
SymbolVendor * sym_vendor = module_sp - > GetSymbolVendor ( ) ;
if ( sym_vendor )
m_debug_map_symfile = ( SymbolFileDWARFDebugMap * ) sym_vendor - > GetSymbolFile ( ) ;
}
}
return m_debug_map_symfile ;
}