Files
llvm/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

7996 lines
362 KiB
C++
Raw Normal View History

//===-- 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"
#include "lldb/Core/Module.h"
#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"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/Block.h"
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
#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>
#include <ctype.h>
#include <string.h>
//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
#ifdef ENABLE_DEBUG_PRINTF
#include <stdio.h>
#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
#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;
}
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)
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 ()
{
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
if (GetDebugMapSymfile ())
return m_debug_map_symfile->GetTypeList();
return m_obj_file->GetModule()->GetTypeList();
}
Added the ability to get a list of types from a SBModule or SBCompileUnit. Sebastien Metrot wanted this, and sent a hollowed out patch. I filled in the blanks and did the low level implementation. The new functions are: //------------------------------------------------------------------ /// Get all types matching \a type_mask from debug info in this /// module. /// /// @param[in] type_mask /// A bitfield that consists of one or more bits logically OR'ed /// together from the lldb::TypeClass enumeration. This allows /// you to request only structure types, or only class, struct /// and union types. Passing in lldb::eTypeClassAny will return /// all types found in the debug information for this module. /// /// @return /// A list of types in this module that match \a type_mask //------------------------------------------------------------------ lldb::SBTypeList SBModule::GetTypes (uint32_t type_mask) //------------------------------------------------------------------ /// Get all types matching \a type_mask from debug info in this /// compile unit. /// /// @param[in] type_mask /// A bitfield that consists of one or more bits logically OR'ed /// together from the lldb::TypeClass enumeration. This allows /// you to request only structure types, or only class, struct /// and union types. Passing in lldb::eTypeClassAny will return /// all types found in the debug information for this compile /// unit. /// /// @return /// A list of types in this compile unit that match \a type_mask //------------------------------------------------------------------ lldb::SBTypeList SBCompileUnit::GetTypes (uint32_t type_mask = lldb::eTypeClassAny); This lets you request types by filling out a mask that contains one or more bits from the lldb::TypeClass enumerations, so you can only get the types you really want. llvm-svn: 184251
2013-06-18 22:51:05 +00:00
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;
Added the ability to get a list of types from a SBModule or SBCompileUnit. Sebastien Metrot wanted this, and sent a hollowed out patch. I filled in the blanks and did the low level implementation. The new functions are: //------------------------------------------------------------------ /// Get all types matching \a type_mask from debug info in this /// module. /// /// @param[in] type_mask /// A bitfield that consists of one or more bits logically OR'ed /// together from the lldb::TypeClass enumeration. This allows /// you to request only structure types, or only class, struct /// and union types. Passing in lldb::eTypeClassAny will return /// all types found in the debug information for this module. /// /// @return /// A list of types in this module that match \a type_mask //------------------------------------------------------------------ lldb::SBTypeList SBModule::GetTypes (uint32_t type_mask) //------------------------------------------------------------------ /// Get all types matching \a type_mask from debug info in this /// compile unit. /// /// @param[in] type_mask /// A bitfield that consists of one or more bits logically OR'ed /// together from the lldb::TypeClass enumeration. This allows /// you to request only structure types, or only class, struct /// and union types. Passing in lldb::eTypeClassAny will return /// all types found in the debug information for this compile /// unit. /// /// @return /// A list of types in this compile unit that match \a type_mask //------------------------------------------------------------------ lldb::SBTypeList SBCompileUnit::GetTypes (uint32_t type_mask = lldb::eTypeClassAny); This lets you request types by filling out a mask that contains one or more bits from the lldb::TypeClass enumerations, so you can only get the types you really want. llvm-svn: 184251
2013-06-18 22:51:05 +00:00
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;
}
Added the ability to get a list of types from a SBModule or SBCompileUnit. Sebastien Metrot wanted this, and sent a hollowed out patch. I filled in the blanks and did the low level implementation. The new functions are: //------------------------------------------------------------------ /// Get all types matching \a type_mask from debug info in this /// module. /// /// @param[in] type_mask /// A bitfield that consists of one or more bits logically OR'ed /// together from the lldb::TypeClass enumeration. This allows /// you to request only structure types, or only class, struct /// and union types. Passing in lldb::eTypeClassAny will return /// all types found in the debug information for this module. /// /// @return /// A list of types in this module that match \a type_mask //------------------------------------------------------------------ lldb::SBTypeList SBModule::GetTypes (uint32_t type_mask) //------------------------------------------------------------------ /// Get all types matching \a type_mask from debug info in this /// compile unit. /// /// @param[in] type_mask /// A bitfield that consists of one or more bits logically OR'ed /// together from the lldb::TypeClass enumeration. This allows /// you to request only structure types, or only class, struct /// and union types. Passing in lldb::eTypeClassAny will return /// all types found in the debug information for this compile /// unit. /// /// @return /// A list of types in this compile unit that match \a type_mask //------------------------------------------------------------------ lldb::SBTypeList SBCompileUnit::GetTypes (uint32_t type_mask = lldb::eTypeClassAny); This lets you request types by filling out a mask that contains one or more bits from the lldb::TypeClass enumerations, so you can only get the types you really want. llvm-svn: 184251
2013-06-18 22:51:05 +00:00
}
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
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
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(),
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
m_indexed (false),
m_is_external_ast_source (false),
m_using_apple_tables (false),
m_supports_DW_AT_APPLE_objc_complete_type (eLazyBoolCalculate),
m_ranges(),
m_unique_ast_type_map ()
{
}
SymbolFileDWARF::~SymbolFileDWARF()
{
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
if (m_is_external_ast_source)
{
ModuleSP module_sp (m_obj_file->GetModule());
if (module_sp)
module_sp->GetClangASTContext().RemoveExternalSource ();
}
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
}
static const ConstString &
GetDWARFMachOSegmentName ()
{
static ConstString g_dwarf_section_name ("__DWARF");
return g_dwarf_section_name;
}
UniqueDWARFASTTypeMap &
SymbolFileDWARF::GetUniqueDWARFASTTypeMap ()
{
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
if (GetDebugMapSymfile ())
return m_debug_map_symfile->GetUniqueDWARFASTTypeMap ();
return m_unique_ast_type_map;
}
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
ClangASTContext &
SymbolFileDWARF::GetClangASTContext ()
{
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
if (GetDebugMapSymfile ())
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
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;
llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_ap (
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
new ClangExternalASTSourceCallbacks (SymbolFileDWARF::CompleteTagDecl,
SymbolFileDWARF::CompleteObjCInterfaceDecl,
SymbolFileDWARF::FindExternalVisibleDeclsByName,
SymbolFileDWARF::LayoutRecordType,
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
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)
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
{
const SectionList *section_list = module_sp->GetSectionList();
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
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);
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
}
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;
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
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;
}
const DWARFDataExtractor&
SymbolFileDWARF::GetCachedSectionData (uint32_t got_flag, SectionType sect_type, DWARFDataExtractor &data)
{
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;
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_abbrev_data()
{
return GetCachedSectionData (flagsGotDebugAbbrevData, eSectionTypeDWARFDebugAbbrev, m_data_debug_abbrev);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_aranges_data()
{
return GetCachedSectionData (flagsGotDebugArangesData, eSectionTypeDWARFDebugAranges, m_data_debug_aranges);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_frame_data()
{
return GetCachedSectionData (flagsGotDebugFrameData, eSectionTypeDWARFDebugFrame, m_data_debug_frame);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_info_data()
{
return GetCachedSectionData (flagsGotDebugInfoData, eSectionTypeDWARFDebugInfo, m_data_debug_info);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_line_data()
{
return GetCachedSectionData (flagsGotDebugLineData, eSectionTypeDWARFDebugLine, m_data_debug_line);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_loc_data()
{
return GetCachedSectionData (flagsGotDebugLocData, eSectionTypeDWARFDebugLoc, m_data_debug_loc);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_ranges_data()
{
return GetCachedSectionData (flagsGotDebugRangesData, eSectionTypeDWARFDebugRanges, m_data_debug_ranges);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_str_data()
{
return GetCachedSectionData (flagsGotDebugStrData, eSectionTypeDWARFDebugStr, m_data_debug_str);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_apple_names_data()
{
return GetCachedSectionData (flagsGotAppleNamesData, eSectionTypeDWARFAppleNames, m_data_apple_names);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_apple_types_data()
{
return GetCachedSectionData (flagsGotAppleTypesData, eSectionTypeDWARFAppleTypes, m_data_apple_types);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_apple_namespaces_data()
{
return GetCachedSectionData (flagsGotAppleNamespacesData, eSectionTypeDWARFAppleNamespaces, m_data_apple_namespaces);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_apple_objc_data()
{
return GetCachedSectionData (flagsGotAppleObjCData, eSectionTypeDWARFAppleObjC, m_data_apple_objc);
}
DWARFDebugAbbrev*
SymbolFileDWARF::DebugAbbrev()
{
if (m_abbr.get() == NULL)
{
const DWARFDataExtractor &debug_abbrev_data = get_debug_abbrev_data();
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)
{
Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p",
__PRETTY_FUNCTION__, static_cast<void*>(this));
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*
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit)
{
DWARFDebugInfo* info = DebugInfo();
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
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.
return info->GetCompileUnit(0).get();
}
else
{
// Just a normal DWARF file whose user ID for the compile unit is
// the DWARF offset itself
return info->GetCompileUnit((dw_offset_t)comp_unit->GetID()).get();
}
}
return NULL;
}
DWARFDebugRanges*
SymbolFileDWARF::DebugRanges()
{
if (m_ranges.get() == NULL)
{
Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p",
__PRETTY_FUNCTION__, static_cast<void*>(this));
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
{
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
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
{
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
ModuleSP module_sp (m_obj_file->GetModule());
if (module_sp)
{
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
const DWARFDebugInfoEntry * cu_die = dwarf_cu->GetCompileUnitDIEOnly ();
if (cu_die)
{
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
const char * cu_die_name = cu_die->GetName(this, dwarf_cu);
const char * cu_comp_dir = cu_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_comp_dir, NULL);
LanguageType cu_language = (LanguageType)cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_language, 0);
if (cu_die_name)
{
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
std::string ramapped_file;
FileSpec cu_file_spec;
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
if (cu_die_name[0] == '/' || cu_comp_dir == NULL || cu_comp_dir[0] == '\0')
{
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00: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 (module_sp->RemapSourceFile(cu_die_name, ramapped_file))
cu_file_spec.SetFile (ramapped_file.c_str(), false);
else
cu_file_spec.SetFile (cu_die_name, false);
}
else
{
// DWARF2/3 suggests the form hostname:pathname for compilation directory.
// Remove the host part if present.
cu_comp_dir = removeHostnameFromPathname(cu_comp_dir);
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
std::string fullpath(cu_comp_dir);
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
if (*fullpath.rbegin() != '/')
fullpath += '/';
fullpath += cu_die_name;
if (module_sp->RemapSourceFile (fullpath.c_str(), ramapped_file))
cu_file_spec.SetFile (ramapped_file.c_str(), false);
else
cu_file_spec.SetFile (fullpath.c_str(), false);
}
cu_sp.reset(new CompileUnit (module_sp,
dwarf_cu,
cu_file_spec,
MakeUserID(dwarf_cu->GetOffset()),
cu_language));
if (cu_sp)
{
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);
}
}
}
}
}
}
}
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);
else if (name)
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;
}
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
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)
{
const uint32_t language = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_language, 0);
if (language)
return (lldb::LanguageType)language;
}
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
}
return eLanguageTypeUnknown;
}
size_t
SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc)
{
assert (sc.comp_unit);
size_t functions_added = 0;
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu)
{
DWARFDIECollection function_dies;
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
const size_t num_functions = dwarf_cu->AppendDIEsWithTag (DW_TAG_subprogram, function_dies);
size_t func_idx;
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
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);
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
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);
// DWARF2/3 suggests the form hostname:pathname for compilation directory.
// Remove the host part if present.
cu_comp_dir = removeHostnameFromPathname(cu_comp_dir);
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;
}
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;
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
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);
}
}
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 ();
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:
{
const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
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))
{
const dw_offset_t type_die_offset = form_value.Reference();
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)
{
}
void
Clear()
{
bit_size = LLDB_INVALID_ADDRESS;
bit_offset = LLDB_INVALID_ADDRESS;
}
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;
const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
uint32_t member_idx = 0;
BitfieldInfo last_field_info;
Added support for reading thread-local storage variables, as defined using the __thread modifier. To make this work this patch extends LLDB to: - Explicitly track the link_map address for each module. This is effectively the module handle, not sure why it wasn't already being stored off anywhere. As an extension later, it would be nice if someone were to add support for printing this as part of the modules list. - Allow reading the per-thread data pointer via ptrace. I have added support for Linux here. I'll be happy to add support for FreeBSD once this is reviewed. OS X does not appear to have __thread variables, so maybe we don't need it there. Windows support should eventually be workable along the same lines. - Make DWARF expressions track which module they originated from. - Add support for the DW_OP_GNU_push_tls_address DWARF opcode, as generated by gcc and recent versions of clang. Earlier versions of clang (such as 3.2, which is default on Ubuntu right now) do not generate TLS debug info correctly so can not be supported here. - Understand the format of the pthread DTV block. This is where it gets tricky. We have three basic options here: 1) Call "dlinfo" or "__tls_get_addr" on the inferior and ask it directly. However this won't work on core dumps, and generally speaking it's not a good idea for the debugger to call functions itself, as it has the potential to not work depending on the state of the target. 2) Use libthread_db. This is what GDB does. However this option requires having a version of libthread_db on the host cross-compiled for each potential target. This places a large burden on the user, and would make it very hard to cross-debug from Windows to Linux, for example. Trying to build a library intended exclusively for one OS on a different one is not pleasant. GDB sidesteps the problem and asks the user to figure it out. 3) Parse the DTV structure ourselves. On initial inspection this seems to be a bad option, as the DTV structure (the format used by the runtime to manage TLS data) is not in fact a kernel data structure, it is implemented entirely in useerland in libc. Therefore the layout of it's fields are version and OS dependent, and are not standardized. However, it turns out not to be such a problem. All OSes use basically the same algorithm (a per-module lookup table) as detailed in Ulrich Drepper's TLS ELF ABI document, so we can easily write code to decode it ourselves. The only question therefore is the exact field layouts required. Happily, the implementors of libpthread expose the structure of the DTV via metadata exported as symbols from the .so itself, designed exactly for this kind of thing. So this patch simply reads that metadata in, and re-implements libthread_db's algorithm itself. We thereby get cross-platform TLS lookup without either requiring third-party libraries, while still being independent of the version of libpthread being used. Test case included. llvm-svn: 192922
2013-10-17 21:14:00 +00:00
ModuleSP module = GetObjectFile()->GetModule();
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;
case DW_AT_type: encoding_uid = form_value.Reference(); break;
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);
const DWARFDataExtractor& debug_info_data = get_debug_info_data();
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 *
Added support for reading thread-local storage variables, as defined using the __thread modifier. To make this work this patch extends LLDB to: - Explicitly track the link_map address for each module. This is effectively the module handle, not sure why it wasn't already being stored off anywhere. As an extension later, it would be nice if someone were to add support for printing this as part of the modules list. - Allow reading the per-thread data pointer via ptrace. I have added support for Linux here. I'll be happy to add support for FreeBSD once this is reviewed. OS X does not appear to have __thread variables, so maybe we don't need it there. Windows support should eventually be workable along the same lines. - Make DWARF expressions track which module they originated from. - Add support for the DW_OP_GNU_push_tls_address DWARF opcode, as generated by gcc and recent versions of clang. Earlier versions of clang (such as 3.2, which is default on Ubuntu right now) do not generate TLS debug info correctly so can not be supported here. - Understand the format of the pthread DTV block. This is where it gets tricky. We have three basic options here: 1) Call "dlinfo" or "__tls_get_addr" on the inferior and ask it directly. However this won't work on core dumps, and generally speaking it's not a good idea for the debugger to call functions itself, as it has the potential to not work depending on the state of the target. 2) Use libthread_db. This is what GDB does. However this option requires having a version of libthread_db on the host cross-compiled for each potential target. This places a large burden on the user, and would make it very hard to cross-debug from Windows to Linux, for example. Trying to build a library intended exclusively for one OS on a different one is not pleasant. GDB sidesteps the problem and asks the user to figure it out. 3) Parse the DTV structure ourselves. On initial inspection this seems to be a bad option, as the DTV structure (the format used by the runtime to manage TLS data) is not in fact a kernel data structure, it is implemented entirely in useerland in libc. Therefore the layout of it's fields are version and OS dependent, and are not standardized. However, it turns out not to be such a problem. All OSes use basically the same algorithm (a per-module lookup table) as detailed in Ulrich Drepper's TLS ELF ABI document, so we can easily write code to decode it ourselves. The only question therefore is the exact field layouts required. Happily, the implementors of libpthread expose the structure of the DTV via metadata exported as symbols from the .so itself, designed exactly for this kind of thing. So this patch simply reads that metadata in, and re-implements libthread_db's algorithm itself. We thereby get cross-platform TLS lookup without either requiring third-party libraries, while still being independent of the version of libpthread being used. Test case included. llvm-svn: 192922
2013-10-17 21:14:00 +00:00
module,
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;
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
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);
uint64_t field_bit_offset = (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8));
if (bit_size > 0)
{
BitfieldInfo this_field_info;
this_field_info.bit_offset = field_bit_offset;
this_field_info.bit_size = bit_size;
/////////////////////////////////////////////////////////////
// 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.
/////////////////////////////////////////////////////////////
if (byte_size == 0)
byte_size = member_type->GetByteSize();
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;
}
// Update the field bit offset we will report for layout
field_bit_offset = this_field_info.bit_offset;
// 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;
// Objective-C has invalid DW_AT_bit_offset values in older versions
2014-07-08 18:05:41 +00:00
// of clang, so we have to be careful and only insert unnamed bitfields
// 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);
layout_info.field_offsets.insert(std::make_pair(unnamed_bitfield_decl, anon_field_info.bit_offset));
}
}
last_field_info = this_field_info;
}
else
{
last_field_info.Clear();
}
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);
Added a mechanism for keeping track of where in the debug information individual Decls came from. We've had a metadata infrastructure for a while, which was intended to solve a problem we've since dealt with in a different way. (It was meant to keep track of which definition of an Objective-C class was the "true" definition, but we now find it by searching the symbols for the class symbol.) The metadata is attached to the ExternalASTSource, which means it has a one-to-one correspondence with AST contexts. I've repurposed the metadata infrastructure to hold the object file and DIE offset for the DWARF information corresponding to a Decl. There are methods in ClangASTContext that get and set this metadata, and the ClangASTImporter is capable of tracking down the metadata for Decls that have been copied out of the debug information into the parser's AST context without using any additional memory. To see the metadata, you just have to enable the expression log: - (lldb) log enable lldb expr - and watch the import messages. The high 32 bits of the metadata indicate the index of the object file in its containing DWARFDebugMap; I have also added a log which you can use to track that mapping: - (lldb) log enable dwarf map - This adds 64 bits per Decl, which in my testing hasn't turned out to be very much (debugging Clang produces around 6500 Decls in my tests). To track how much data is being consumed, I've also added a global variable g_TotalSizeOfMetadata which tracks the total number of Decls that have metadata in all active AST contexts. Right now this metadata is enormously useful for tracking down bugs in the debug info parser. In the future I also want to use this information to provide more intelligent error messages instead of printing empty source lines wherever Clang refers to the location where something is defined. llvm-svn: 154634
2012-04-13 00:10:03 +00:00
GetClangASTContext().SetMetadataAsUserID (field_decl, MakeUserID(die->GetOffset()));
layout_info.field_offsets.insert(std::make_pair(field_decl, field_bit_offset));
}
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);
}
}
if (prop_name != NULL)
{
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));
Added a mechanism for keeping track of where in the debug information individual Decls came from. We've had a metadata infrastructure for a while, which was intended to solve a problem we've since dealt with in a different way. (It was meant to keep track of which definition of an Objective-C class was the "true" definition, but we now find it by searching the symbols for the class symbol.) The metadata is attached to the ExternalASTSource, which means it has a one-to-one correspondence with AST contexts. I've repurposed the metadata infrastructure to hold the object file and DIE offset for the DWARF information corresponding to a Decl. There are methods in ClangASTContext that get and set this metadata, and the ClangASTImporter is capable of tracking down the metadata for Decls that have been copied out of the debug information into the parser's AST context without using any additional memory. To see the metadata, you just have to enable the expression log: - (lldb) log enable lldb expr - and watch the import messages. The high 32 bits of the metadata indicate the index of the object file in its containing DWARFDebugMap; I have also added a log which you can use to track that mapping: - (lldb) log enable dwarf map - This adds 64 bits per Decl, which in my testing hasn't turned out to be very much (debugging Clang produces around 6500 Decls in my tests). To track how much data is being consumed, I've also added a global variable g_TotalSizeOfMetadata which tracks the total number of Decls that have metadata in all active AST contexts. Right now this metadata is enormously useful for tracking down bugs in the debug info parser. In the future I also want to use this information to provide more intelligent error messages instead of printing empty source lines wherever Clang refers to the location where something is defined. llvm-svn: 154634
2012-04-13 00:10:03 +00:00
if (ivar_decl)
GetClangASTContext().SetMetadataAsUserID (ivar_decl, MakeUserID(die->GetOffset()));
}
}
}
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
++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;
case DW_AT_type: encoding_uid = form_value.Reference(); break;
case DW_AT_data_member_location:
if (form_value.BlockData())
{
Value initialValue(0);
Value memberOffset(0);
const DWARFDataExtractor& debug_info_data = get_debug_info_data();
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,
Added support for reading thread-local storage variables, as defined using the __thread modifier. To make this work this patch extends LLDB to: - Explicitly track the link_map address for each module. This is effectively the module handle, not sure why it wasn't already being stored off anywhere. As an extension later, it would be nice if someone were to add support for printing this as part of the modules list. - Allow reading the per-thread data pointer via ptrace. I have added support for Linux here. I'll be happy to add support for FreeBSD once this is reviewed. OS X does not appear to have __thread variables, so maybe we don't need it there. Windows support should eventually be workable along the same lines. - Make DWARF expressions track which module they originated from. - Add support for the DW_OP_GNU_push_tls_address DWARF opcode, as generated by gcc and recent versions of clang. Earlier versions of clang (such as 3.2, which is default on Ubuntu right now) do not generate TLS debug info correctly so can not be supported here. - Understand the format of the pthread DTV block. This is where it gets tricky. We have three basic options here: 1) Call "dlinfo" or "__tls_get_addr" on the inferior and ask it directly. However this won't work on core dumps, and generally speaking it's not a good idea for the debugger to call functions itself, as it has the potential to not work depending on the state of the target. 2) Use libthread_db. This is what GDB does. However this option requires having a version of libthread_db on the host cross-compiled for each potential target. This places a large burden on the user, and would make it very hard to cross-debug from Windows to Linux, for example. Trying to build a library intended exclusively for one OS on a different one is not pleasant. GDB sidesteps the problem and asks the user to figure it out. 3) Parse the DTV structure ourselves. On initial inspection this seems to be a bad option, as the DTV structure (the format used by the runtime to manage TLS data) is not in fact a kernel data structure, it is implemented entirely in useerland in libc. Therefore the layout of it's fields are version and OS dependent, and are not standardized. However, it turns out not to be such a problem. All OSes use basically the same algorithm (a per-module lookup table) as detailed in Ulrich Drepper's TLS ELF ABI document, so we can easily write code to decode it ourselves. The only question therefore is the exact field layouts required. Happily, the implementors of libpthread expose the structure of the DTV via metadata exported as symbols from the .so itself, designed exactly for this kind of thing. So this patch simply reads that metadata in, and re-implements libthread_db's algorithm itself. We thereby get cross-platform TLS lookup without either requiring third-party libraries, while still being independent of the version of libpthread being used. Test case included. llvm-svn: 192922
2013-10-17 21:14:00 +00:00
module,
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);
assert(base_class_type);
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)
{
// 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.
}
else
{
layout_info.base_offsets.insert(std::make_pair(base_class_clang_type.GetAsCXXRecordDecl(),
clang::CharUnits::fromQuantity(member_byte_offset)));
}
}
}
}
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;
}
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
// 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)
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
{
ClangASTType clang_type_no_qualifiers = clang_type.RemoveFastQualifiers();
const DWARFDebugInfoEntry* die = m_forward_decl_clang_type_to_die.lookup (clang_type_no_qualifiers.GetOpaqueQualType());
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
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;
{
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 ();
}
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;
}
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;
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);
// 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));
}
}
if (class_language == eLanguageTypeObjC)
{
ConstString class_name (clang_type.GetTypeName());
if (class_name)
{
DIEArray method_die_offsets;
if (m_using_apple_tables)
{
if (m_apple_objc_ap.get())
m_apple_objc_ap->FindByName(class_name.GetCString(), method_die_offsets);
}
else
{
if (!m_indexed)
Index ();
m_objc_class_selectors_index.Find (class_name, method_die_offsets);
}
if (!method_die_offsets.empty())
{
DWARFDebugInfo* debug_info = DebugInfo();
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);
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",
die_offset, class_name.GetCString());
}
}
}
}
for (DelayedPropertyList::iterator pi = delayed_properties.begin(), pe = delayed_properties.end();
pi != pe;
++pi)
pi->Finalize();
}
}
// 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);
}
// 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());
}
if (!base_classes.empty())
{
// 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.\nPlease 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-07-01 21:22:11 +00:00
// class and other classes will be fine, this is the best we can do
// short of crashing.
base_class_type.StartTagDeclarationDefinition ();
base_class_type.CompleteTagDeclarationDefinition ();
}
}
}
clang_type.SetBaseClassesForClassType (&base_classes.front(),
base_classes.size());
// Clang will copy each CXXBaseSpecifier in "base_classes"
// so we have to free them all.
ClangASTType::DeleteBaseClassSpecifiers (&base_classes.front(),
base_classes.size());
}
}
}
clang_type.BuildIndirectFields ();
clang_type.CompleteTagDeclarationDefinition ();
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;
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])",
static_cast<void*>(clang_type.GetOpaqueQualType()),
static_cast<void*>(record_decl),
layout_info.bit_size,
layout_info.alignment,
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()));
uint32_t idx;
{
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)
{
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());
}
}
{
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());
}
}
{
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());
}
}
}
m_record_decl_to_layout_map.insert(std::make_pair(record_decl, layout_info));
}
}
}
return (bool)clang_type;
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 ();
return (bool)clang_type;
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;
}
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;
}
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)",
static_cast<void*>(so_addr.GetSection().get()),
so_addr.GetOffset(), resolve_scope);
uint32_t resolved = 0;
if (resolve_scope & ( eSymbolContextCompUnit |
eSymbolContextFunction |
eSymbolContextBlock |
eSymbolContextLineEntry |
eSymbolContextVariable ))
{
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);
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
{
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);
const bool full_match = (bool)file_spec.GetDirectory();
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00: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()));
else if (function_die != NULL)
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)",
GetObjectFile()->GetFileSpec().GetFilename().AsCString("<Unknown>"));
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("\nFunction basenames:\n"); m_function_basename_index.Dump (&s);
s.Printf("\nFunction fullnames:\n"); m_function_fullname_index.Dump (&s);
s.Printf("\nFunction methods:\n"); m_function_method_index.Dump (&s);
s.Printf("\nFunction selectors:\n"); m_function_selector_index.Dump (&s);
s.Printf("\nObjective C class selectors:\n"); m_objc_class_selectors_index.Dump (&s);
s.Printf("\nGlobals and statics:\n"); m_global_index.Dump (&s);
s.Printf("\nTypes:\n"); m_type_index.Dump (&s);
s.Printf("\nNamepaces:\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-07-08 18:05:41 +00:00
// No namespace specified, so the answer is
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-07-01 21:22:11 +00:00
// So as long the contained decl context DIE isn't a namespace
// 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(),
static_cast<const void*>(namespace_decl),
append, max_matches);
if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl))
return 0;
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())
{
const char *name_cstr = name.GetCString();
llvm::StringRef basename;
llvm::StringRef context;
if (!CPPLanguageRuntime::ExtractContextAndIdentifier(name_cstr, context, basename))
basename = name_cstr;
m_apple_names_ap->FindByName (basename.data(), die_offsets);
}
}
else
{
// Index the DWARF if we haven't already
if (!m_indexed)
Index ();
m_global_index.Find (name, die_offsets);
}
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);
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;
case DW_TAG_variable:
{
sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX);
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",
name.GetCString(),
static_cast<const void*>(namespace_decl),
append, max_matches,
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));
if (log)
{
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::FindGlobalVariables (regex=\"%s\", append=%u, max_matches=%u, variables)",
regex.GetText(), append,
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())
Added a new class called lldb_private::SymbolFileType which is designed to take a SymbolFile reference and a lldb::user_id_t and be used in objects which represent things in debug symbols that have types where we don't need to know the true type yet, such as in lldb_private::Variable objects. This allows us to defer resolving the type until something is used. More specifically this allows us to get 1000 local variables from the current function, and if the user types "frame variable argc", we end up _only_ resolving the type for "argc" and not for the 999 other local variables. We can expand the use of this as needed in the future. Modified the DWARFMappedHash class to be able to read the HashData that has more than just the DIE offset. It currently will read the atoms in the header definition and read the data correctly. Currently only the DIE offset and type flags are supported. This is needed for adding type flags to the .apple_types hash accelerator tables. Fixed a assertion crash that would happen if we have a variable that had a DW_AT_const_value instead of a location where "location.LocationContains_DW_OP_addr()" would end up asserting when it tried to parse the variable location as a DWARF opcode list. Decreased the amount of memory that LLDB would use when evaluating an expression by 3x - 4x for clang. There was a place in the namespace lookup code that was parsing all namespaces with a certain name in a DWARF file instead of stopping when it found the first match. This was causing all of the compile units with a matching namespace to get parsed into memory and causing unnecessary memory bloat. Improved "Target::EvaluateExpression(...)" to not try and find a variable when the expression contains characters that would certainly cause an expression to need to be evaluated by the debugger. llvm-svn: 146130
2011-12-08 02:13:16 +00:00
{
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,
SymbolContextList& sc_list)
{
const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
return ResolveFunction (dwarf_cu, die, sc_list);
}
bool
SymbolFileDWARF::ResolveFunction (DWARFCompileUnit *cu,
const DWARFDebugInfoEntry *die,
SymbolContextList& sc_list)
{
SymbolContext sc;
if (die == NULL)
return false;
// If we were passed a die that is not a function, just return false...
if (die->Tag() != DW_TAG_subprogram && die->Tag() != DW_TAG_inlined_subroutine)
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;
}
}
assert (die && die->Tag() == DW_TAG_subprogram);
if (GetFunction (cu, die, sc))
{
Address addr;
// Parse all blocks if needed
if (inlined_die)
{
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)
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,
SymbolContextList& sc_list)
{
DIEArray die_offsets;
if (name_to_die.Find (name, die_offsets))
{
ParseFunctions (die_offsets, sc_list);
}
}
void
SymbolFileDWARF::FindFunctions (const RegularExpression &regex,
const NameToDIE &name_to_die,
SymbolContextList& sc_list)
{
DIEArray die_offsets;
if (name_to_die.Find (regex, die_offsets))
{
ParseFunctions (die_offsets, sc_list);
}
}
void
SymbolFileDWARF::FindFunctions (const RegularExpression &regex,
const DWARFMappedHash::MemoryTable &memory_table,
SymbolContextList& sc_list)
{
DIEArray die_offsets;
Added a new class called lldb_private::SymbolFileType which is designed to take a SymbolFile reference and a lldb::user_id_t and be used in objects which represent things in debug symbols that have types where we don't need to know the true type yet, such as in lldb_private::Variable objects. This allows us to defer resolving the type until something is used. More specifically this allows us to get 1000 local variables from the current function, and if the user types "frame variable argc", we end up _only_ resolving the type for "argc" and not for the 999 other local variables. We can expand the use of this as needed in the future. Modified the DWARFMappedHash class to be able to read the HashData that has more than just the DIE offset. It currently will read the atoms in the header definition and read the data correctly. Currently only the DIE offset and type flags are supported. This is needed for adding type flags to the .apple_types hash accelerator tables. Fixed a assertion crash that would happen if we have a variable that had a DW_AT_const_value instead of a location where "location.LocationContains_DW_OP_addr()" would end up asserting when it tried to parse the variable location as a DWARF opcode list. Decreased the amount of memory that LLDB would use when evaluating an expression by 3x - 4x for clang. There was a place in the namespace lookup code that was parsing all namespaces with a certain name in a DWARF file instead of stopping when it found the first match. This was causing all of the compile units with a matching namespace to get parsed into memory and causing unnecessary memory bloat. Improved "Target::EvaluateExpression(...)" to not try and find a variable when the expression contains characters that would certainly cause an expression to need to be evaluated by the debugger. llvm-svn: 146130
2011-12-08 02:13:16 +00:00
DWARFMappedHash::DIEInfoArray hash_data_array;
if (memory_table.AppendAllDIEsThatMatchingRegex (regex, hash_data_array))
{
Added a new class called lldb_private::SymbolFileType which is designed to take a SymbolFile reference and a lldb::user_id_t and be used in objects which represent things in debug symbols that have types where we don't need to know the true type yet, such as in lldb_private::Variable objects. This allows us to defer resolving the type until something is used. More specifically this allows us to get 1000 local variables from the current function, and if the user types "frame variable argc", we end up _only_ resolving the type for "argc" and not for the 999 other local variables. We can expand the use of this as needed in the future. Modified the DWARFMappedHash class to be able to read the HashData that has more than just the DIE offset. It currently will read the atoms in the header definition and read the data correctly. Currently only the DIE offset and type flags are supported. This is needed for adding type flags to the .apple_types hash accelerator tables. Fixed a assertion crash that would happen if we have a variable that had a DW_AT_const_value instead of a location where "location.LocationContains_DW_OP_addr()" would end up asserting when it tried to parse the variable location as a DWARF opcode list. Decreased the amount of memory that LLDB would use when evaluating an expression by 3x - 4x for clang. There was a place in the namespace lookup code that was parsing all namespaces with a certain name in a DWARF file instead of stopping when it found the first match. This was causing all of the compile units with a matching namespace to get parsed into memory and causing unnecessary memory bloat. Improved "Target::EvaluateExpression(...)" to not try and find a variable when the expression contains characters that would certainly cause an expression to need to be evaluated by the debugger. llvm-svn: 146130
2011-12-08 02:13:16 +00:00
DWARFMappedHash::ExtractDIEArray (hash_data_array, die_offsets);
ParseFunctions (die_offsets, sc_list);
}
}
void
SymbolFileDWARF::ParseFunctions (const DIEArray &die_offsets,
SymbolContextList& sc_list)
{
const size_t num_matches = die_offsets.size();
if (num_matches)
{
SymbolContext sc;
DWARFCompileUnit* dwarf_cu = NULL;
for (size_t i=0; i<num_matches; ++i)
{
const dw_offset_t die_offset = die_offsets[i];
ResolveFunction (die_offset, dwarf_cu, sc_list);
}
}
}
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);
}
}
if (best_name.GetDemangledName())
{
const char *demangled = best_name.GetDemangledName().GetCString();
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;
Added function name types to allow us to set breakpoints by name more intelligently. The four name types we currently have are: eFunctionNameTypeFull = (1 << 1), // The function name. // For C this is the same as just the name of the function // For C++ this is the demangled version of the mangled name. // For ObjC this is the full function signature with the + or // - and the square brackets and the class and selector eFunctionNameTypeBase = (1 << 2), // The function name only, no namespaces or arguments and no class // methods or selectors will be searched. eFunctionNameTypeMethod = (1 << 3), // Find function by method name (C++) with no namespace or arguments eFunctionNameTypeSelector = (1 << 4) // Find function by selector name (ObjC) names this allows much more flexibility when setting breakoints: (lldb) breakpoint set --name main --basename (lldb) breakpoint set --name main --fullname (lldb) breakpoint set --name main --method (lldb) breakpoint set --name main --selector The default: (lldb) breakpoint set --name main will inspect the name "main" and look for any parens, or if the name starts with "-[" or "+[" and if any are found then a full name search will happen. Else a basename search will be the default. Fixed some command option structures so not all options are required when they shouldn't be. Cleaned up the breakpoint output summary. Made the "image lookup --address <addr>" output much more verbose so it shows all the important symbol context results. Added a GetDescription method to many of the SymbolContext objects for the more verbose output. llvm-svn: 107075
2010-06-28 21:30:43 +00:00
}
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)
Added function name types to allow us to set breakpoints by name more intelligently. The four name types we currently have are: eFunctionNameTypeFull = (1 << 1), // The function name. // For C this is the same as just the name of the function // For C++ this is the demangled version of the mangled name. // For ObjC this is the full function signature with the + or // - and the square brackets and the class and selector eFunctionNameTypeBase = (1 << 2), // The function name only, no namespaces or arguments and no class // methods or selectors will be searched. eFunctionNameTypeMethod = (1 << 3), // Find function by method name (C++) with no namespace or arguments eFunctionNameTypeSelector = (1 << 4) // Find function by selector name (ObjC) names this allows much more flexibility when setting breakoints: (lldb) breakpoint set --name main --basename (lldb) breakpoint set --name main --fullname (lldb) breakpoint set --name main --method (lldb) breakpoint set --name main --selector The default: (lldb) breakpoint set --name main will inspect the name "main" and look for any parens, or if the name starts with "-[" or "+[" and if any are found then a full name search will happen. Else a basename search will be the default. Fixed some command option structures so not all options are required when they shouldn't be. Cleaned up the breakpoint output summary. Made the "image lookup --address <addr>" output much more verbose so it shows all the important symbol context results. Added a GetDescription method to many of the SymbolContext objects for the more verbose output. llvm-svn: 107075
2010-06-28 21:30:43 +00:00
{
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);
}
Added function name types to allow us to set breakpoints by name more intelligently. The four name types we currently have are: eFunctionNameTypeFull = (1 << 1), // The function name. // For C this is the same as just the name of the function // For C++ this is the demangled version of the mangled name. // For ObjC this is the full function signature with the + or // - and the square brackets and the class and selector eFunctionNameTypeBase = (1 << 2), // The function name only, no namespaces or arguments and no class // methods or selectors will be searched. eFunctionNameTypeMethod = (1 << 3), // Find function by method name (C++) with no namespace or arguments eFunctionNameTypeSelector = (1 << 4) // Find function by selector name (ObjC) names this allows much more flexibility when setting breakoints: (lldb) breakpoint set --name main --basename (lldb) breakpoint set --name main --fullname (lldb) breakpoint set --name main --method (lldb) breakpoint set --name main --selector The default: (lldb) breakpoint set --name main will inspect the name "main" and look for any parens, or if the name starts with "-[" or "+[" and if any are found then a full name search will happen. Else a basename search will be the default. Fixed some command option structures so not all options are required when they shouldn't be. Cleaned up the breakpoint output summary. Made the "image lookup --address <addr>" output much more verbose so it shows all the important symbol context results. Added a GetDescription method to many of the SymbolContext objects for the more verbose output. llvm-svn: 107075
2010-06-28 21:30:43 +00:00
// If we aren't appending the results to this list, then clear the list
if (!append)
sc_list.Clear();
if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl))
return 0;
// If name is empty then we won't find anything.
if (name.IsEmpty())
return 0;
Added function name types to allow us to set breakpoints by name more intelligently. The four name types we currently have are: eFunctionNameTypeFull = (1 << 1), // The function name. // For C this is the same as just the name of the function // For C++ this is the demangled version of the mangled name. // For ObjC this is the full function signature with the + or // - and the square brackets and the class and selector eFunctionNameTypeBase = (1 << 2), // The function name only, no namespaces or arguments and no class // methods or selectors will be searched. eFunctionNameTypeMethod = (1 << 3), // Find function by method name (C++) with no namespace or arguments eFunctionNameTypeSelector = (1 << 4) // Find function by selector name (ObjC) names this allows much more flexibility when setting breakoints: (lldb) breakpoint set --name main --basename (lldb) breakpoint set --name main --fullname (lldb) breakpoint set --name main --method (lldb) breakpoint set --name main --selector The default: (lldb) breakpoint set --name main will inspect the name "main" and look for any parens, or if the name starts with "-[" or "+[" and if any are found then a full name search will happen. Else a basename search will be the default. Fixed some command option structures so not all options are required when they shouldn't be. Cleaned up the breakpoint output summary. Made the "image lookup --address <addr>" output much more verbose so it shows all the important symbol context results. Added a GetDescription method to many of the SymbolContext objects for the more verbose output. llvm-svn: 107075
2010-06-28 21:30:43 +00:00
// 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 (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
continue;
if (resolved_dies.find(die) == resolved_dies.end())
{
if (ResolveFunction (dwarf_cu, die, sc_list))
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 (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
continue;
if (resolved_dies.find(die) == resolved_dies.end())
{
if (ResolveFunction (dwarf_cu, die, sc_list))
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 (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
continue;
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())
if (ResolveFunction (dwarf_cu, die, sc_list))
{
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();
if (type)
{
clang::DeclContext* decl_ctx = GetClangDeclContextContainingTypeUID (type->GetID());
if (decl_ctx->isRecord())
{
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;
}
}
}
else
{
GetObjectFile()->GetModule()->ReportWarning ("function at die offset 0x%8.8x had no function type",
die_offset);
}
}
}
}
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
{
Added function name types to allow us to set breakpoints by name more intelligently. The four name types we currently have are: eFunctionNameTypeFull = (1 << 1), // The function name. // For C this is the same as just the name of the function // For C++ this is the demangled version of the mangled name. // For ObjC this is the full function signature with the + or // - and the square brackets and the class and selector eFunctionNameTypeBase = (1 << 2), // The function name only, no namespaces or arguments and no class // methods or selectors will be searched. eFunctionNameTypeMethod = (1 << 3), // Find function by method name (C++) with no namespace or arguments eFunctionNameTypeSelector = (1 << 4) // Find function by selector name (ObjC) names this allows much more flexibility when setting breakoints: (lldb) breakpoint set --name main --basename (lldb) breakpoint set --name main --fullname (lldb) breakpoint set --name main --method (lldb) breakpoint set --name main --selector The default: (lldb) breakpoint set --name main will inspect the name "main" and look for any parens, or if the name starts with "-[" or "+[" and if any are found then a full name search will happen. Else a basename search will be the default. Fixed some command option structures so not all options are required when they shouldn't be. Cleaned up the breakpoint output summary. Made the "image lookup --address <addr>" output much more verbose so it shows all the important symbol context results. Added a GetDescription method to many of the SymbolContext objects for the more verbose output. llvm-svn: 107075
2010-06-28 21:30:43 +00:00
// Index the DWARF if we haven't already
if (!m_indexed)
Index ();
Added function name types to allow us to set breakpoints by name more intelligently. The four name types we currently have are: eFunctionNameTypeFull = (1 << 1), // The function name. // For C this is the same as just the name of the function // For C++ this is the demangled version of the mangled name. // For ObjC this is the full function signature with the + or // - and the square brackets and the class and selector eFunctionNameTypeBase = (1 << 2), // The function name only, no namespaces or arguments and no class // methods or selectors will be searched. eFunctionNameTypeMethod = (1 << 3), // Find function by method name (C++) with no namespace or arguments eFunctionNameTypeSelector = (1 << 4) // Find function by selector name (ObjC) names this allows much more flexibility when setting breakoints: (lldb) breakpoint set --name main --basename (lldb) breakpoint set --name main --fullname (lldb) breakpoint set --name main --method (lldb) breakpoint set --name main --selector The default: (lldb) breakpoint set --name main will inspect the name "main" and look for any parens, or if the name starts with "-[" or "+[" and if any are found then a full name search will happen. Else a basename search will be the default. Fixed some command option structures so not all options are required when they shouldn't be. Cleaned up the breakpoint output summary. Made the "image lookup --address <addr>" output much more verbose so it shows all the important symbol context results. Added a GetDescription method to many of the SymbolContext objects for the more verbose output. llvm-svn: 107075
2010-06-28 21:30:43 +00:00
if (name_type_mask & eFunctionNameTypeFull)
{
FindFunctions (name, m_function_fullname_index, sc_list);
Added function name types to allow us to set breakpoints by name more intelligently. The four name types we currently have are: eFunctionNameTypeFull = (1 << 1), // The function name. // For C this is the same as just the name of the function // For C++ this is the demangled version of the mangled name. // For ObjC this is the full function signature with the + or // - and the square brackets and the class and selector eFunctionNameTypeBase = (1 << 2), // The function name only, no namespaces or arguments and no class // methods or selectors will be searched. eFunctionNameTypeMethod = (1 << 3), // Find function by method name (C++) with no namespace or arguments eFunctionNameTypeSelector = (1 << 4) // Find function by selector name (ObjC) names this allows much more flexibility when setting breakoints: (lldb) breakpoint set --name main --basename (lldb) breakpoint set --name main --fullname (lldb) breakpoint set --name main --method (lldb) breakpoint set --name main --selector The default: (lldb) breakpoint set --name main will inspect the name "main" and look for any parens, or if the name starts with "-[" or "+[" and if any are found then a full name search will happen. Else a basename search will be the default. Fixed some command option structures so not all options are required when they shouldn't be. Cleaned up the breakpoint output summary. Made the "image lookup --address <addr>" output much more verbose so it shows all the important symbol context results. Added a GetDescription method to many of the SymbolContext objects for the more verbose output. llvm-svn: 107075
2010-06-28 21:30:43 +00:00
// FIXME Temporary workaround for global/anonymous namespace
// functions on FreeBSD and Linux
#if defined (__FreeBSD__) || defined (__linux__)
// If we didn't find any functions in the global namespace try
// looking in the basename index but ignore any returned
// functions that have a namespace (ie. mangled names starting with
// '_ZN') but keep functions which have an anonymous namespace
if (sc_list.GetSize() == 0)
{
SymbolContextList temp_sc_list;
FindFunctions (name, m_function_basename_index, temp_sc_list);
if (!namespace_decl)
{
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);
if (strncmp(mangled_name.GetCString(), "_ZN", 3) ||
!strncmp(demangled_name.GetCString(), "(anonymous namespace)", 21))
{
sc_list.Append(sc);
}
}
}
}
}
#endif
}
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 (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
continue;
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())
{
if (ResolveFunction (dwarf_cu, die, sc_list))
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 (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
continue;
// If we get to here, the die is good, and we should add it:
if (resolved_dies.find(die) == resolved_dies.end())
{
if (ResolveFunction (dwarf_cu, die, sc_list))
resolved_dies.insert(die);
}
}
}
}
die_offsets.clear();
}
Added function name types to allow us to set breakpoints by name more intelligently. The four name types we currently have are: eFunctionNameTypeFull = (1 << 1), // The function name. // For C this is the same as just the name of the function // For C++ this is the demangled version of the mangled name. // For ObjC this is the full function signature with the + or // - and the square brackets and the class and selector eFunctionNameTypeBase = (1 << 2), // The function name only, no namespaces or arguments and no class // methods or selectors will be searched. eFunctionNameTypeMethod = (1 << 3), // Find function by method name (C++) with no namespace or arguments eFunctionNameTypeSelector = (1 << 4) // Find function by selector name (ObjC) names this allows much more flexibility when setting breakoints: (lldb) breakpoint set --name main --basename (lldb) breakpoint set --name main --fullname (lldb) breakpoint set --name main --method (lldb) breakpoint set --name main --selector The default: (lldb) breakpoint set --name main will inspect the name "main" and look for any parens, or if the name starts with "-[" or "+[" and if any are found then a full name search will happen. Else a basename search will be the default. Fixed some command option structures so not all options are required when they shouldn't be. Cleaned up the breakpoint output summary. Made the "image lookup --address <addr>" output much more verbose so it shows all the important symbol context results. Added a GetDescription method to many of the SymbolContext objects for the more verbose output. llvm-svn: 107075
2010-06-28 21:30:43 +00:00
if ((name_type_mask & eFunctionNameTypeSelector) && (!namespace_decl || !*namespace_decl))
{
FindFunctions (name, m_function_selector_index, sc_list);
}
}
// 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,
"SymbolFileDWARF::FindFunctions (name=\"%s\", name_type_mask=0x%x, append=%u, sc_list) => %u",
name.GetCString(),
name_type_mask,
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())
FindFunctions (regex, *m_apple_names_ap, sc_list);
}
else
{
// Index the DWARF if we haven't already
if (!m_indexed)
Index ();
FindFunctions (regex, m_function_basename_index, sc_list);
FindFunctions (regex, m_function_fullname_index, sc_list);
}
// Return the number of variable that were appended to the list
return sc_list.GetSize() - original_size;
}
uint32_t
Added a new class called lldb_private::SymbolFileType which is designed to take a SymbolFile reference and a lldb::user_id_t and be used in objects which represent things in debug symbols that have types where we don't need to know the true type yet, such as in lldb_private::Variable objects. This allows us to defer resolving the type until something is used. More specifically this allows us to get 1000 local variables from the current function, and if the user types "frame variable argc", we end up _only_ resolving the type for "argc" and not for the 999 other local variables. We can expand the use of this as needed in the future. Modified the DWARFMappedHash class to be able to read the HashData that has more than just the DIE offset. It currently will read the atoms in the header definition and read the data correctly. Currently only the DIE offset and type flags are supported. This is needed for adding type flags to the .apple_types hash accelerator tables. Fixed a assertion crash that would happen if we have a variable that had a DW_AT_const_value instead of a location where "location.LocationContains_DW_OP_addr()" would end up asserting when it tried to parse the variable location as a DWARF opcode list. Decreased the amount of memory that LLDB would use when evaluating an expression by 3x - 4x for clang. There was a place in the namespace lookup code that was parsing all namespaces with a certain name in a DWARF file instead of stopping when it found the first match. This was causing all of the compile units with a matching namespace to get parsed into memory and causing unnecessary memory bloat. Improved "Target::EvaluateExpression(...)" to not try and find a variable when the expression contains characters that would certainly cause an expression to need to be evaluated by the debugger. llvm-svn: 146130
2011-12-08 02:13:16 +00:00
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));
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(),
static_cast<void*>(namespace_decl->GetNamespaceDecl()),
namespace_decl->GetQualifiedName().c_str(),
append, max_matches);
else
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(NULL), append=%u, max_matches=%u, type_list)",
name.GetCString(), append,
max_matches);
}
// If we aren't appending the results to this list, then clear the list
if (!append)
types.Clear();
if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl))
return 0;
DIEArray die_offsets;
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 ();
m_type_index.Find (name, die_offsets);
}
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;
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(),
static_cast<void*>(namespace_decl->GetNamespaceDecl()),
namespace_decl->GetQualifiedName().c_str(),
append, max_matches,
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(),
append, max_matches,
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))
return ClangNamespaceDecl();
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);
Added a new class called lldb_private::SymbolFileType which is designed to take a SymbolFile reference and a lldb::user_id_t and be used in objects which represent things in debug symbols that have types where we don't need to know the true type yet, such as in lldb_private::Variable objects. This allows us to defer resolving the type until something is used. More specifically this allows us to get 1000 local variables from the current function, and if the user types "frame variable argc", we end up _only_ resolving the type for "argc" and not for the 999 other local variables. We can expand the use of this as needed in the future. Modified the DWARFMappedHash class to be able to read the HashData that has more than just the DIE offset. It currently will read the atoms in the header definition and read the data correctly. Currently only the DIE offset and type flags are supported. This is needed for adding type flags to the .apple_types hash accelerator tables. Fixed a assertion crash that would happen if we have a variable that had a DW_AT_const_value instead of a location where "location.LocationContains_DW_OP_addr()" would end up asserting when it tried to parse the variable location as a DWARF opcode list. Decreased the amount of memory that LLDB would use when evaluating an expression by 3x - 4x for clang. There was a place in the namespace lookup code that was parsing all namespaces with a certain name in a DWARF file instead of stopping when it found the first match. This was causing all of the compile units with a matching namespace to get parsed into memory and causing unnecessary memory bloat. Improved "Target::EvaluateExpression(...)" to not try and find a variable when the expression contains characters that would certainly cause an expression to need to be evaluated by the debugger. llvm-svn: 146130
2011-12-08 02:13:16 +00:00
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(),
static_cast<const void*>(namespace_decl.GetNamespaceDecl()),
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,
bool &is_variadic,
TypeList* type_list,
std::vector<ClangASTType>& function_param_types,
std::vector<clang::ParmVarDecl*>& function_param_decls,
unsigned &type_quals) // ,
// ClangASTContext::TemplateParameterInfos &template_param_infos))
{
if (parent_die == NULL)
return 0;
const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
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;
case DW_AT_type: param_type_die_offset = form_value.Reference(); break;
case DW_AT_artificial: is_artificial = form_value.Boolean(); break;
case DW_AT_location:
// if (form_value.BlockData())
// {
// const DWARFDataExtractor& debug_info_data = debug_info();
// uint32_t block_length = form_value.Unsigned();
// DWARFDataExtractor location(debug_info_data, form_value.BlockData() - debug_info_data.GetDataStart(), block_length);
// }
// 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);
Added a mechanism for keeping track of where in the debug information individual Decls came from. We've had a metadata infrastructure for a while, which was intended to solve a problem we've since dealt with in a different way. (It was meant to keep track of which definition of an Objective-C class was the "true" definition, but we now find it by searching the symbols for the class symbol.) The metadata is attached to the ExternalASTSource, which means it has a one-to-one correspondence with AST contexts. I've repurposed the metadata infrastructure to hold the object file and DIE offset for the DWARF information corresponding to a Decl. There are methods in ClangASTContext that get and set this metadata, and the ClangASTImporter is capable of tracking down the metadata for Decls that have been copied out of the debug information into the parser's AST context without using any additional memory. To see the metadata, you just have to enable the expression log: - (lldb) log enable lldb expr - and watch the import messages. The high 32 bits of the metadata indicate the index of the object file in its containing DWARFDebugMap; I have also added a log which you can use to track that mapping: - (lldb) log enable dwarf map - This adds 64 bits per Decl, which in my testing hasn't turned out to be very much (debugging Clang produces around 6500 Decls in my tests). To track how much data is being consumed, I've also added a global variable g_TotalSizeOfMetadata which tracks the total number of Decls that have metadata in all active AST contexts. Right now this metadata is enormously useful for tracking down bugs in the debug info parser. In the future I also want to use this information to provide more intelligent error messages instead of printing empty source lines wherever Clang refers to the location where something is defined. llvm-svn: 154634
2012-04-13 00:10:03 +00:00
GetClangASTContext().SetMetadataAsUserID (param_var_decl, MakeUserID(die->GetOffset()));
}
}
}
arg_idx++;
}
break;
case DW_TAG_unspecified_parameters:
is_variadic = true;
break;
case DW_TAG_template_type_parameter:
case DW_TAG_template_value_parameter:
// 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);
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;
const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
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;
const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
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)",
static_cast<void*>(GetClangASTContext().getASTContext()),
MakeUserID(die->GetOffset()),
namespace_name,
static_cast<void*>(namespace_decl),
static_cast<void*>(namespace_decl->getOriginalNamespace()));
}
else
{
GetObjectFile()->GetModule()->LogMessage (log,
"ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p (original = %p)",
static_cast<void*>(GetClangASTContext().getASTContext()),
MakeUserID(die->GetOffset()),
static_cast<void*>(namespace_decl),
static_cast<void*>(namespace_decl->getOriginalNamespace()));
}
}
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;
}
}
}
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
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)
{
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);
if (try_resolving_type)
{
Type *resolved_type = ResolveType (type_cu, type_die, false);
if (resolved_type && resolved_type != DIE_IS_BEING_PARSED)
{
DEBUG_PRINTF ("resolved 0x%8.8" PRIx64 " from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n",
MakeUserID(die->GetOffset()),
m_obj_file->GetFileSpec().GetFilename().AsCString("<Unknown>"),
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-07-01 21:22:11 +00:00
// Make sure the DW_TAG values match all the way back up the
// 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!
Removed all of the "#ifndef SWIG" from the SB header files since we are using interface (.i) files for each class. Changed the FindFunction class from: uint32_t SBTarget::FindFunctions (const char *name, uint32_t name_type_mask, bool append, lldb::SBSymbolContextList& sc_list) uint32_t SBModule::FindFunctions (const char *name, uint32_t name_type_mask, bool append, lldb::SBSymbolContextList& sc_list) To: lldb::SBSymbolContextList SBTarget::FindFunctions (const char *name, uint32_t name_type_mask = lldb::eFunctionNameTypeAny); lldb::SBSymbolContextList SBModule::FindFunctions (const char *name, uint32_t name_type_mask = lldb::eFunctionNameTypeAny); This makes the API easier to use from python. Also added the ability to append a SBSymbolContext or a SBSymbolContextList to a SBSymbolContextList. Exposed properties for lldb.SBSymbolContextList in python: lldb.SBSymbolContextList.modules => list() or all lldb.SBModule objects in the list lldb.SBSymbolContextList.compile_units => list() or all lldb.SBCompileUnits objects in the list lldb.SBSymbolContextList.functions => list() or all lldb.SBFunction objects in the list lldb.SBSymbolContextList.blocks => list() or all lldb.SBBlock objects in the list lldb.SBSymbolContextList.line_entries => list() or all lldb.SBLineEntry objects in the list lldb.SBSymbolContextList.symbols => list() or all lldb.SBSymbol objects in the list This allows a call to the SBTarget::FindFunctions(...) and SBModule::FindFunctions(...) and then the result can be used to extract the desired information: sc_list = lldb.target.FindFunctions("erase") for function in sc_list.functions: print function for symbol in sc_list.symbols: print symbol Exposed properties for the lldb.SBSymbolContext objects in python: lldb.SBSymbolContext.module => lldb.SBModule lldb.SBSymbolContext.compile_unit => lldb.SBCompileUnit lldb.SBSymbolContext.function => lldb.SBFunction lldb.SBSymbolContext.block => lldb.SBBlock lldb.SBSymbolContext.line_entry => lldb.SBLineEntry lldb.SBSymbolContext.symbol => lldb.SBSymbol Exposed properties for the lldb.SBBlock objects in python: lldb.SBBlock.parent => lldb.SBBlock for the parent block that contains lldb.SBBlock.sibling => lldb.SBBlock for the sibling block to the current block lldb.SBBlock.first_child => lldb.SBBlock for the first child block to the current block lldb.SBBlock.call_site => for inline functions, return a lldb.declaration object that gives the call site file, line and column lldb.SBBlock.name => for inline functions this is the name of the inline function that this block represents lldb.SBBlock.inlined_block => returns the inlined function block that contains this block (might return itself if the current block is an inlined block) lldb.SBBlock.range[int] => access the address ranges for a block by index, a list() with start and end address is returned lldb.SBBlock.ranges => an array or all address ranges for this block lldb.SBBlock.num_ranges => the number of address ranges for this blcok SBFunction objects can now get the SBType and the SBBlock that represents the top scope of the function. SBBlock objects can now get the variable list from the current block. The value list returned allows varaibles to be viewed prior with no process if code wants to check the variables in a function. There are two ways to get a variable list from a SBBlock: lldb::SBValueList SBBlock::GetVariables (lldb::SBFrame& frame, bool arguments, bool locals, bool statics, lldb::DynamicValueType use_dynamic); lldb::SBValueList SBBlock::GetVariables (lldb::SBTarget& target, bool arguments, bool locals, bool statics); When a SBFrame is used, the values returned will be locked down to the frame and the values will be evaluated in the context of that frame. When a SBTarget is used, global an static variables can be viewed without a running process. llvm-svn: 149853
2012-02-06 01:44:54 +00:00
if (name1 == name2)
continue;
// Name pointers are not equal, so only compare the strings
// if both are not NULL.
if (name1 && name2)
{
Removed all of the "#ifndef SWIG" from the SB header files since we are using interface (.i) files for each class. Changed the FindFunction class from: uint32_t SBTarget::FindFunctions (const char *name, uint32_t name_type_mask, bool append, lldb::SBSymbolContextList& sc_list) uint32_t SBModule::FindFunctions (const char *name, uint32_t name_type_mask, bool append, lldb::SBSymbolContextList& sc_list) To: lldb::SBSymbolContextList SBTarget::FindFunctions (const char *name, uint32_t name_type_mask = lldb::eFunctionNameTypeAny); lldb::SBSymbolContextList SBModule::FindFunctions (const char *name, uint32_t name_type_mask = lldb::eFunctionNameTypeAny); This makes the API easier to use from python. Also added the ability to append a SBSymbolContext or a SBSymbolContextList to a SBSymbolContextList. Exposed properties for lldb.SBSymbolContextList in python: lldb.SBSymbolContextList.modules => list() or all lldb.SBModule objects in the list lldb.SBSymbolContextList.compile_units => list() or all lldb.SBCompileUnits objects in the list lldb.SBSymbolContextList.functions => list() or all lldb.SBFunction objects in the list lldb.SBSymbolContextList.blocks => list() or all lldb.SBBlock objects in the list lldb.SBSymbolContextList.line_entries => list() or all lldb.SBLineEntry objects in the list lldb.SBSymbolContextList.symbols => list() or all lldb.SBSymbol objects in the list This allows a call to the SBTarget::FindFunctions(...) and SBModule::FindFunctions(...) and then the result can be used to extract the desired information: sc_list = lldb.target.FindFunctions("erase") for function in sc_list.functions: print function for symbol in sc_list.symbols: print symbol Exposed properties for the lldb.SBSymbolContext objects in python: lldb.SBSymbolContext.module => lldb.SBModule lldb.SBSymbolContext.compile_unit => lldb.SBCompileUnit lldb.SBSymbolContext.function => lldb.SBFunction lldb.SBSymbolContext.block => lldb.SBBlock lldb.SBSymbolContext.line_entry => lldb.SBLineEntry lldb.SBSymbolContext.symbol => lldb.SBSymbol Exposed properties for the lldb.SBBlock objects in python: lldb.SBBlock.parent => lldb.SBBlock for the parent block that contains lldb.SBBlock.sibling => lldb.SBBlock for the sibling block to the current block lldb.SBBlock.first_child => lldb.SBBlock for the first child block to the current block lldb.SBBlock.call_site => for inline functions, return a lldb.declaration object that gives the call site file, line and column lldb.SBBlock.name => for inline functions this is the name of the inline function that this block represents lldb.SBBlock.inlined_block => returns the inlined function block that contains this block (might return itself if the current block is an inlined block) lldb.SBBlock.range[int] => access the address ranges for a block by index, a list() with start and end address is returned lldb.SBBlock.ranges => an array or all address ranges for this block lldb.SBBlock.num_ranges => the number of address ranges for this blcok SBFunction objects can now get the SBType and the SBBlock that represents the top scope of the function. SBBlock objects can now get the variable list from the current block. The value list returned allows varaibles to be viewed prior with no process if code wants to check the variables in a function. There are two ways to get a variable list from a SBBlock: lldb::SBValueList SBBlock::GetVariables (lldb::SBFrame& frame, bool arguments, bool locals, bool statics, lldb::DynamicValueType use_dynamic); lldb::SBValueList SBBlock::GetVariables (lldb::SBTarget& target, bool arguments, bool locals, bool statics); When a SBFrame is used, the values returned will be locked down to the frame and the values will be evaluated in the context of that frame. When a SBTarget is used, global an static variables can be viewed without a running process. llvm-svn: 149853
2012-02-06 01:44:54 +00:00
// If the strings don't compare, we are done...
if (strcmp(name1, name2) != 0)
return false;
Removed all of the "#ifndef SWIG" from the SB header files since we are using interface (.i) files for each class. Changed the FindFunction class from: uint32_t SBTarget::FindFunctions (const char *name, uint32_t name_type_mask, bool append, lldb::SBSymbolContextList& sc_list) uint32_t SBModule::FindFunctions (const char *name, uint32_t name_type_mask, bool append, lldb::SBSymbolContextList& sc_list) To: lldb::SBSymbolContextList SBTarget::FindFunctions (const char *name, uint32_t name_type_mask = lldb::eFunctionNameTypeAny); lldb::SBSymbolContextList SBModule::FindFunctions (const char *name, uint32_t name_type_mask = lldb::eFunctionNameTypeAny); This makes the API easier to use from python. Also added the ability to append a SBSymbolContext or a SBSymbolContextList to a SBSymbolContextList. Exposed properties for lldb.SBSymbolContextList in python: lldb.SBSymbolContextList.modules => list() or all lldb.SBModule objects in the list lldb.SBSymbolContextList.compile_units => list() or all lldb.SBCompileUnits objects in the list lldb.SBSymbolContextList.functions => list() or all lldb.SBFunction objects in the list lldb.SBSymbolContextList.blocks => list() or all lldb.SBBlock objects in the list lldb.SBSymbolContextList.line_entries => list() or all lldb.SBLineEntry objects in the list lldb.SBSymbolContextList.symbols => list() or all lldb.SBSymbol objects in the list This allows a call to the SBTarget::FindFunctions(...) and SBModule::FindFunctions(...) and then the result can be used to extract the desired information: sc_list = lldb.target.FindFunctions("erase") for function in sc_list.functions: print function for symbol in sc_list.symbols: print symbol Exposed properties for the lldb.SBSymbolContext objects in python: lldb.SBSymbolContext.module => lldb.SBModule lldb.SBSymbolContext.compile_unit => lldb.SBCompileUnit lldb.SBSymbolContext.function => lldb.SBFunction lldb.SBSymbolContext.block => lldb.SBBlock lldb.SBSymbolContext.line_entry => lldb.SBLineEntry lldb.SBSymbolContext.symbol => lldb.SBSymbol Exposed properties for the lldb.SBBlock objects in python: lldb.SBBlock.parent => lldb.SBBlock for the parent block that contains lldb.SBBlock.sibling => lldb.SBBlock for the sibling block to the current block lldb.SBBlock.first_child => lldb.SBBlock for the first child block to the current block lldb.SBBlock.call_site => for inline functions, return a lldb.declaration object that gives the call site file, line and column lldb.SBBlock.name => for inline functions this is the name of the inline function that this block represents lldb.SBBlock.inlined_block => returns the inlined function block that contains this block (might return itself if the current block is an inlined block) lldb.SBBlock.range[int] => access the address ranges for a block by index, a list() with start and end address is returned lldb.SBBlock.ranges => an array or all address ranges for this block lldb.SBBlock.num_ranges => the number of address ranges for this blcok SBFunction objects can now get the SBType and the SBBlock that represents the top scope of the function. SBBlock objects can now get the variable list from the current block. The value list returned allows varaibles to be viewed prior with no process if code wants to check the variables in a function. There are two ways to get a variable list from a SBBlock: lldb::SBValueList SBBlock::GetVariables (lldb::SBFrame& frame, bool arguments, bool locals, bool statics, lldb::DynamicValueType use_dynamic); lldb::SBValueList SBBlock::GetVariables (lldb::SBTarget& target, bool arguments, bool locals, bool statics); When a SBFrame is used, the values returned will be locked down to the frame and the values will be evaluated in the context of that frame. When a SBTarget is used, global an static variables can be viewed without a running process. llvm-svn: 149853
2012-02-06 01:44:54 +00:00
}
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,
DWARFDIECollection &failures)
{
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;
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);
}
fast_path = false;
}
uint32_t idx;
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;
}
const char *src_name = src_die->GetMangledName (src_symfile, src_cu);
const char *dst_name = dst_die->GetMangledName (this, dst_cu);
// 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);
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);
clang::DeclContext *src_decl_ctx = src_symfile->m_die_to_decl_ctx[src_die];
if (src_decl_ctx)
{
if (log)
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());
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());
}
Type *src_child_type = m_die_to_type[src_die];
if (src_child_type)
{
if (log)
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());
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.
if (!src_name_to_die.IsEmpty() && !dst_name_to_die.IsEmpty())
{
src_name_to_die.Sort();
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);
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)
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());
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());
}
Type *src_child_type = m_die_to_type[src_die];
if (src_child_type)
{
if (log)
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());
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());
failures.Append(dst_die);
}
}
}
}
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();
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);
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)
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());
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());
}
Type *src_child_type = m_die_to_type[src_die];
if (src_child_type)
{
if (log)
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());
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);
failures.Append(dst_die);
}
}
return (failures.Size() != 0);
}
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;
#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
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);
GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die 0x%8.8x)) %s name = '%s')",
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)
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());
//
// }
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;
DWARFFormValue form_value;
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:
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;
case DW_AT_type: encoding_uid = form_value.Reference(); break;
default:
case DW_AT_sibling:
break;
}
}
}
}
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);
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);
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");
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".
DWARFDebugInfoEntry* encoding_die = dwarf_cu->GetDIEPtr(encoding_uid);
if (encoding_die && encoding_die->Tag() == DW_TAG_structure_type)
{
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;
}
}
}
}
}
}
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));
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())
{
// 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.
decl.SetFile(FileSpec ("<invalid>", false));
}
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;
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;
}
}
}
}
// 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());
// 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,
*unique_ast_entry_ap))
{
// 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.
type_sp = unique_ast_entry_ap->m_type_sp;
if (type_sp)
{
m_die_to_type[die] = type_sp.get();
return type_sp;
Modified the PluginManager to be ready for loading plug-ins from a system LLDB plugin directory and a user LLDB plugin directory. We currently still need to work out at what layer the plug-ins will be, but at least we are prepared for plug-ins. Plug-ins will attempt to be loaded from the "/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Plugins" folder, and from the "~/Library/Application Support/LLDB/Plugins" folder on MacOSX. Each plugin will be scanned for: extern "C" bool LLDBPluginInitialize(void); extern "C" void LLDBPluginTerminate(void); If at least LLDBPluginInitialize is found, the plug-in will be loaded. The LLDBPluginInitialize function returns a bool that indicates if the plug-in should stay loaded or not (plug-ins might check the current OS, current hardware, or anything else and determine they don't want to run on the current host). The plug-in is uniqued by path and added to a static loaded plug-in map. The plug-in scanning happens during "lldb_private::Initialize()" which calls to the PluginManager::Initialize() function. Likewise with termination lldb_private::Terminate() calls PluginManager::Terminate(). The paths for the plug-in directories is fetched through new Host calls: bool Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec); bool Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec); This way linux and other systems can define their own appropriate locations for plug-ins to be loaded. To allow dynamic shared library loading, the Host layer has also been modified to include shared library open, close and get symbol: static void * Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error); static Error Host::DynamicLibraryClose (void *dynamic_library_handle); static void * Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error); lldb_private::FileSpec also has been modified to support directory enumeration in an attempt to abstract the directory enumeration into one spot in the code. The directory enumertion function is static and takes a callback: typedef enum EnumerateDirectoryResult { eEnumerateDirectoryResultNext, // Enumerate next entry in the current directory eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not eEnumerateDirectoryResultExit, // Exit from the current directory at the current level. eEnumerateDirectoryResultQuit // Stop directory enumerations at any level }; typedef FileSpec::EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, FileSpec::FileType file_type, const FileSpec &spec); static FileSpec::EnumerateDirectoryResult FileSpec::EnumerateDirectory (const char *dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton); This allow clients to specify the directory to search, and specifies if only files, directories or other (pipe, symlink, fifo, etc) files will cause the callback to be called. The callback also gets to return with the action that should be performed after this directory entry. eEnumerateDirectoryResultNext specifies to continue enumerating through a directory with the next entry. eEnumerateDirectoryResultEnter specifies to recurse down into a directory entry, or if the file is not a directory or symlink/alias to a directory, then just iterate to the next entry. eEnumerateDirectoryResultExit specifies to exit the current directory and skip any entries that might be remaining, yet continue enumerating to the next entry in the parent directory. And finally eEnumerateDirectoryResultQuit means to abort all directory enumerations at all levels. Modified the Declaration class to not include column information currently since we don't have any compilers that currently support column based declaration information. Columns support can be re-enabled with the additions of a #define. Added the ability to find an EmulateInstruction plug-in given a target triple and optional plug-in name in the plug-in manager. Fixed a few cases where opendir/readdir was being used, but yet not closedir was being used. Soon these will be deprecated in favor of the new directory enumeration call that was added to the FileSpec class. llvm-svn: 124716
2011-02-02 02:24:04 +00: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;
}
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;
}
Modified the PluginManager to be ready for loading plug-ins from a system LLDB plugin directory and a user LLDB plugin directory. We currently still need to work out at what layer the plug-ins will be, but at least we are prepared for plug-ins. Plug-ins will attempt to be loaded from the "/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Plugins" folder, and from the "~/Library/Application Support/LLDB/Plugins" folder on MacOSX. Each plugin will be scanned for: extern "C" bool LLDBPluginInitialize(void); extern "C" void LLDBPluginTerminate(void); If at least LLDBPluginInitialize is found, the plug-in will be loaded. The LLDBPluginInitialize function returns a bool that indicates if the plug-in should stay loaded or not (plug-ins might check the current OS, current hardware, or anything else and determine they don't want to run on the current host). The plug-in is uniqued by path and added to a static loaded plug-in map. The plug-in scanning happens during "lldb_private::Initialize()" which calls to the PluginManager::Initialize() function. Likewise with termination lldb_private::Terminate() calls PluginManager::Terminate(). The paths for the plug-in directories is fetched through new Host calls: bool Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec); bool Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec); This way linux and other systems can define their own appropriate locations for plug-ins to be loaded. To allow dynamic shared library loading, the Host layer has also been modified to include shared library open, close and get symbol: static void * Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error); static Error Host::DynamicLibraryClose (void *dynamic_library_handle); static void * Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error); lldb_private::FileSpec also has been modified to support directory enumeration in an attempt to abstract the directory enumeration into one spot in the code. The directory enumertion function is static and takes a callback: typedef enum EnumerateDirectoryResult { eEnumerateDirectoryResultNext, // Enumerate next entry in the current directory eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not eEnumerateDirectoryResultExit, // Exit from the current directory at the current level. eEnumerateDirectoryResultQuit // Stop directory enumerations at any level }; typedef FileSpec::EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, FileSpec::FileType file_type, const FileSpec &spec); static FileSpec::EnumerateDirectoryResult FileSpec::EnumerateDirectory (const char *dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton); This allow clients to specify the directory to search, and specifies if only files, directories or other (pipe, symlink, fifo, etc) files will cause the callback to be called. The callback also gets to return with the action that should be performed after this directory entry. eEnumerateDirectoryResultNext specifies to continue enumerating through a directory with the next entry. eEnumerateDirectoryResultEnter specifies to recurse down into a directory entry, or if the file is not a directory or symlink/alias to a directory, then just iterate to the next entry. eEnumerateDirectoryResultExit specifies to exit the current directory and skip any entries that might be remaining, yet continue enumerating to the next entry in the parent directory. And finally eEnumerateDirectoryResultQuit means to abort all directory enumerations at all levels. Modified the Declaration class to not include column information currently since we don't have any compilers that currently support column based declaration information. Columns support can be re-enabled with the additions of a #define. Added the ability to find an EmulateInstruction plug-in given a target triple and optional plug-in name in the plug-in manager. Fixed a few cases where opendir/readdir was being used, but yet not closedir was being used. Soon these will be deprecated in favor of the new directory enumeration call that was added to the FileSpec class. llvm-svn: 124716
2011-02-02 02:24:04 +00:00
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);
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
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);
}
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,
static_cast<void*>(this),
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;
}
}
}
Modified the PluginManager to be ready for loading plug-ins from a system LLDB plugin directory and a user LLDB plugin directory. We currently still need to work out at what layer the plug-ins will be, but at least we are prepared for plug-ins. Plug-ins will attempt to be loaded from the "/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Plugins" folder, and from the "~/Library/Application Support/LLDB/Plugins" folder on MacOSX. Each plugin will be scanned for: extern "C" bool LLDBPluginInitialize(void); extern "C" void LLDBPluginTerminate(void); If at least LLDBPluginInitialize is found, the plug-in will be loaded. The LLDBPluginInitialize function returns a bool that indicates if the plug-in should stay loaded or not (plug-ins might check the current OS, current hardware, or anything else and determine they don't want to run on the current host). The plug-in is uniqued by path and added to a static loaded plug-in map. The plug-in scanning happens during "lldb_private::Initialize()" which calls to the PluginManager::Initialize() function. Likewise with termination lldb_private::Terminate() calls PluginManager::Terminate(). The paths for the plug-in directories is fetched through new Host calls: bool Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec); bool Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec); This way linux and other systems can define their own appropriate locations for plug-ins to be loaded. To allow dynamic shared library loading, the Host layer has also been modified to include shared library open, close and get symbol: static void * Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error); static Error Host::DynamicLibraryClose (void *dynamic_library_handle); static void * Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error); lldb_private::FileSpec also has been modified to support directory enumeration in an attempt to abstract the directory enumeration into one spot in the code. The directory enumertion function is static and takes a callback: typedef enum EnumerateDirectoryResult { eEnumerateDirectoryResultNext, // Enumerate next entry in the current directory eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not eEnumerateDirectoryResultExit, // Exit from the current directory at the current level. eEnumerateDirectoryResultQuit // Stop directory enumerations at any level }; typedef FileSpec::EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, FileSpec::FileType file_type, const FileSpec &spec); static FileSpec::EnumerateDirectoryResult FileSpec::EnumerateDirectory (const char *dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton); This allow clients to specify the directory to search, and specifies if only files, directories or other (pipe, symlink, fifo, etc) files will cause the callback to be called. The callback also gets to return with the action that should be performed after this directory entry. eEnumerateDirectoryResultNext specifies to continue enumerating through a directory with the next entry. eEnumerateDirectoryResultEnter specifies to recurse down into a directory entry, or if the file is not a directory or symlink/alias to a directory, then just iterate to the next entry. eEnumerateDirectoryResultExit specifies to exit the current directory and skip any entries that might be remaining, yet continue enumerating to the next entry in the parent directory. And finally eEnumerateDirectoryResultQuit means to abort all directory enumerations at all levels. Modified the Declaration class to not include column information currently since we don't have any compilers that currently support column based declaration information. Columns support can be re-enabled with the additions of a #define. Added the ability to find an EmulateInstruction plug-in given a target triple and optional plug-in name in the plug-in manager. Fixed a few cases where opendir/readdir was being used, but yet not closedir was being used. Soon these will be deprecated in favor of the new directory enumeration call that was added to the FileSpec class. llvm-svn: 124716
2011-02-02 02:24:04 +00: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",
static_cast<void*>(this),
die->GetOffset(),
DW_TAG_value_to_name(tag),
type_name_cstr);
}
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);
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
if (!type_sp && GetDebugMapSymfile ())
Modified the PluginManager to be ready for loading plug-ins from a system LLDB plugin directory and a user LLDB plugin directory. We currently still need to work out at what layer the plug-ins will be, but at least we are prepared for plug-ins. Plug-ins will attempt to be loaded from the "/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Plugins" folder, and from the "~/Library/Application Support/LLDB/Plugins" folder on MacOSX. Each plugin will be scanned for: extern "C" bool LLDBPluginInitialize(void); extern "C" void LLDBPluginTerminate(void); If at least LLDBPluginInitialize is found, the plug-in will be loaded. The LLDBPluginInitialize function returns a bool that indicates if the plug-in should stay loaded or not (plug-ins might check the current OS, current hardware, or anything else and determine they don't want to run on the current host). The plug-in is uniqued by path and added to a static loaded plug-in map. The plug-in scanning happens during "lldb_private::Initialize()" which calls to the PluginManager::Initialize() function. Likewise with termination lldb_private::Terminate() calls PluginManager::Terminate(). The paths for the plug-in directories is fetched through new Host calls: bool Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec); bool Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec); This way linux and other systems can define their own appropriate locations for plug-ins to be loaded. To allow dynamic shared library loading, the Host layer has also been modified to include shared library open, close and get symbol: static void * Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error); static Error Host::DynamicLibraryClose (void *dynamic_library_handle); static void * Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error); lldb_private::FileSpec also has been modified to support directory enumeration in an attempt to abstract the directory enumeration into one spot in the code. The directory enumertion function is static and takes a callback: typedef enum EnumerateDirectoryResult { eEnumerateDirectoryResultNext, // Enumerate next entry in the current directory eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not eEnumerateDirectoryResultExit, // Exit from the current directory at the current level. eEnumerateDirectoryResultQuit // Stop directory enumerations at any level }; typedef FileSpec::EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, FileSpec::FileType file_type, const FileSpec &spec); static FileSpec::EnumerateDirectoryResult FileSpec::EnumerateDirectory (const char *dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton); This allow clients to specify the directory to search, and specifies if only files, directories or other (pipe, symlink, fifo, etc) files will cause the callback to be called. The callback also gets to return with the action that should be performed after this directory entry. eEnumerateDirectoryResultNext specifies to continue enumerating through a directory with the next entry. eEnumerateDirectoryResultEnter specifies to recurse down into a directory entry, or if the file is not a directory or symlink/alias to a directory, then just iterate to the next entry. eEnumerateDirectoryResultExit specifies to exit the current directory and skip any entries that might be remaining, yet continue enumerating to the next entry in the parent directory. And finally eEnumerateDirectoryResultQuit means to abort all directory enumerations at all levels. Modified the Declaration class to not include column information currently since we don't have any compilers that currently support column based declaration information. Columns support can be re-enabled with the additions of a #define. Added the ability to find an EmulateInstruction plug-in given a target triple and optional plug-in name in the plug-in manager. Fixed a few cases where opendir/readdir was being used, but yet not closedir was being used. Soon these will be deprecated in favor of the new directory enumeration call that was added to the FileSpec class. llvm-svn: 124716
2011-02-02 02:24:04 +00:00
{
// 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);
Modified the PluginManager to be ready for loading plug-ins from a system LLDB plugin directory and a user LLDB plugin directory. We currently still need to work out at what layer the plug-ins will be, but at least we are prepared for plug-ins. Plug-ins will attempt to be loaded from the "/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Plugins" folder, and from the "~/Library/Application Support/LLDB/Plugins" folder on MacOSX. Each plugin will be scanned for: extern "C" bool LLDBPluginInitialize(void); extern "C" void LLDBPluginTerminate(void); If at least LLDBPluginInitialize is found, the plug-in will be loaded. The LLDBPluginInitialize function returns a bool that indicates if the plug-in should stay loaded or not (plug-ins might check the current OS, current hardware, or anything else and determine they don't want to run on the current host). The plug-in is uniqued by path and added to a static loaded plug-in map. The plug-in scanning happens during "lldb_private::Initialize()" which calls to the PluginManager::Initialize() function. Likewise with termination lldb_private::Terminate() calls PluginManager::Terminate(). The paths for the plug-in directories is fetched through new Host calls: bool Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec); bool Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec); This way linux and other systems can define their own appropriate locations for plug-ins to be loaded. To allow dynamic shared library loading, the Host layer has also been modified to include shared library open, close and get symbol: static void * Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error); static Error Host::DynamicLibraryClose (void *dynamic_library_handle); static void * Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error); lldb_private::FileSpec also has been modified to support directory enumeration in an attempt to abstract the directory enumeration into one spot in the code. The directory enumertion function is static and takes a callback: typedef enum EnumerateDirectoryResult { eEnumerateDirectoryResultNext, // Enumerate next entry in the current directory eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not eEnumerateDirectoryResultExit, // Exit from the current directory at the current level. eEnumerateDirectoryResultQuit // Stop directory enumerations at any level }; typedef FileSpec::EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, FileSpec::FileType file_type, const FileSpec &spec); static FileSpec::EnumerateDirectoryResult FileSpec::EnumerateDirectory (const char *dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton); This allow clients to specify the directory to search, and specifies if only files, directories or other (pipe, symlink, fifo, etc) files will cause the callback to be called. The callback also gets to return with the action that should be performed after this directory entry. eEnumerateDirectoryResultNext specifies to continue enumerating through a directory with the next entry. eEnumerateDirectoryResultEnter specifies to recurse down into a directory entry, or if the file is not a directory or symlink/alias to a directory, then just iterate to the next entry. eEnumerateDirectoryResultExit specifies to exit the current directory and skip any entries that might be remaining, yet continue enumerating to the next entry in the parent directory. And finally eEnumerateDirectoryResultQuit means to abort all directory enumerations at all levels. Modified the Declaration class to not include column information currently since we don't have any compilers that currently support column based declaration information. Columns support can be re-enabled with the additions of a #define. Added the ability to find an EmulateInstruction plug-in given a target triple and optional plug-in name in the plug-in manager. Fixed a few cases where opendir/readdir was being used, but yet not closedir was being used. Soon these will be deprecated in favor of the new directory enumeration call that was added to the FileSpec class. llvm-svn: 124716
2011-02-02 02:24:04 +00:00
}
if (type_sp)
Modified the PluginManager to be ready for loading plug-ins from a system LLDB plugin directory and a user LLDB plugin directory. We currently still need to work out at what layer the plug-ins will be, but at least we are prepared for plug-ins. Plug-ins will attempt to be loaded from the "/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Plugins" folder, and from the "~/Library/Application Support/LLDB/Plugins" folder on MacOSX. Each plugin will be scanned for: extern "C" bool LLDBPluginInitialize(void); extern "C" void LLDBPluginTerminate(void); If at least LLDBPluginInitialize is found, the plug-in will be loaded. The LLDBPluginInitialize function returns a bool that indicates if the plug-in should stay loaded or not (plug-ins might check the current OS, current hardware, or anything else and determine they don't want to run on the current host). The plug-in is uniqued by path and added to a static loaded plug-in map. The plug-in scanning happens during "lldb_private::Initialize()" which calls to the PluginManager::Initialize() function. Likewise with termination lldb_private::Terminate() calls PluginManager::Terminate(). The paths for the plug-in directories is fetched through new Host calls: bool Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec); bool Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec); This way linux and other systems can define their own appropriate locations for plug-ins to be loaded. To allow dynamic shared library loading, the Host layer has also been modified to include shared library open, close and get symbol: static void * Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error); static Error Host::DynamicLibraryClose (void *dynamic_library_handle); static void * Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error); lldb_private::FileSpec also has been modified to support directory enumeration in an attempt to abstract the directory enumeration into one spot in the code. The directory enumertion function is static and takes a callback: typedef enum EnumerateDirectoryResult { eEnumerateDirectoryResultNext, // Enumerate next entry in the current directory eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not eEnumerateDirectoryResultExit, // Exit from the current directory at the current level. eEnumerateDirectoryResultQuit // Stop directory enumerations at any level }; typedef FileSpec::EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, FileSpec::FileType file_type, const FileSpec &spec); static FileSpec::EnumerateDirectoryResult FileSpec::EnumerateDirectory (const char *dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton); This allow clients to specify the directory to search, and specifies if only files, directories or other (pipe, symlink, fifo, etc) files will cause the callback to be called. The callback also gets to return with the action that should be performed after this directory entry. eEnumerateDirectoryResultNext specifies to continue enumerating through a directory with the next entry. eEnumerateDirectoryResultEnter specifies to recurse down into a directory entry, or if the file is not a directory or symlink/alias to a directory, then just iterate to the next entry. eEnumerateDirectoryResultExit specifies to exit the current directory and skip any entries that might be remaining, yet continue enumerating to the next entry in the parent directory. And finally eEnumerateDirectoryResultQuit means to abort all directory enumerations at all levels. Modified the Declaration class to not include column information currently since we don't have any compilers that currently support column based declaration information. Columns support can be re-enabled with the additions of a #define. Added the ability to find an EmulateInstruction plug-in given a target triple and optional plug-in name in the plug-in manager. Fixed a few cases where opendir/readdir was being used, but yet not closedir was being used. Soon these will be deprecated in favor of the new directory enumeration call that was added to the FileSpec class. llvm-svn: 124716
2011-02-02 02:24:04 +00:00
{
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,
static_cast<void*>(this),
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;
Modified the PluginManager to be ready for loading plug-ins from a system LLDB plugin directory and a user LLDB plugin directory. We currently still need to work out at what layer the plug-ins will be, but at least we are prepared for plug-ins. Plug-ins will attempt to be loaded from the "/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Plugins" folder, and from the "~/Library/Application Support/LLDB/Plugins" folder on MacOSX. Each plugin will be scanned for: extern "C" bool LLDBPluginInitialize(void); extern "C" void LLDBPluginTerminate(void); If at least LLDBPluginInitialize is found, the plug-in will be loaded. The LLDBPluginInitialize function returns a bool that indicates if the plug-in should stay loaded or not (plug-ins might check the current OS, current hardware, or anything else and determine they don't want to run on the current host). The plug-in is uniqued by path and added to a static loaded plug-in map. The plug-in scanning happens during "lldb_private::Initialize()" which calls to the PluginManager::Initialize() function. Likewise with termination lldb_private::Terminate() calls PluginManager::Terminate(). The paths for the plug-in directories is fetched through new Host calls: bool Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec); bool Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec); This way linux and other systems can define their own appropriate locations for plug-ins to be loaded. To allow dynamic shared library loading, the Host layer has also been modified to include shared library open, close and get symbol: static void * Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error); static Error Host::DynamicLibraryClose (void *dynamic_library_handle); static void * Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error); lldb_private::FileSpec also has been modified to support directory enumeration in an attempt to abstract the directory enumeration into one spot in the code. The directory enumertion function is static and takes a callback: typedef enum EnumerateDirectoryResult { eEnumerateDirectoryResultNext, // Enumerate next entry in the current directory eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not eEnumerateDirectoryResultExit, // Exit from the current directory at the current level. eEnumerateDirectoryResultQuit // Stop directory enumerations at any level }; typedef FileSpec::EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, FileSpec::FileType file_type, const FileSpec &spec); static FileSpec::EnumerateDirectoryResult FileSpec::EnumerateDirectory (const char *dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton); This allow clients to specify the directory to search, and specifies if only files, directories or other (pipe, symlink, fifo, etc) files will cause the callback to be called. The callback also gets to return with the action that should be performed after this directory entry. eEnumerateDirectoryResultNext specifies to continue enumerating through a directory with the next entry. eEnumerateDirectoryResultEnter specifies to recurse down into a directory entry, or if the file is not a directory or symlink/alias to a directory, then just iterate to the next entry. eEnumerateDirectoryResultExit specifies to exit the current directory and skip any entries that might be remaining, yet continue enumerating to the next entry in the parent directory. And finally eEnumerateDirectoryResultQuit means to abort all directory enumerations at all levels. Modified the Declaration class to not include column information currently since we don't have any compilers that currently support column based declaration information. Columns support can be re-enabled with the additions of a #define. Added the ability to find an EmulateInstruction plug-in given a target triple and optional plug-in name in the plug-in manager. Fixed a few cases where opendir/readdir was being used, but yet not closedir was being used. Soon these will be deprecated in favor of the new directory enumeration call that was added to the FileSpec class. llvm-svn: 124716
2011-02-02 02:24:04 +00:00
}
}
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;
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-07-01 21:22:11 +00:00
// If it is a class we must give it an accessibility.
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);
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;
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,
Added a mechanism for keeping track of where in the debug information individual Decls came from. We've had a metadata infrastructure for a while, which was intended to solve a problem we've since dealt with in a different way. (It was meant to keep track of which definition of an Objective-C class was the "true" definition, but we now find it by searching the symbols for the class symbol.) The metadata is attached to the ExternalASTSource, which means it has a one-to-one correspondence with AST contexts. I've repurposed the metadata infrastructure to hold the object file and DIE offset for the DWARF information corresponding to a Decl. There are methods in ClangASTContext that get and set this metadata, and the ClangASTImporter is capable of tracking down the metadata for Decls that have been copied out of the debug information into the parser's AST context without using any additional memory. To see the metadata, you just have to enable the expression log: - (lldb) log enable lldb expr - and watch the import messages. The high 32 bits of the metadata indicate the index of the object file in its containing DWARFDebugMap; I have also added a log which you can use to track that mapping: - (lldb) log enable dwarf map - This adds 64 bits per Decl, which in my testing hasn't turned out to be very much (debugging Clang produces around 6500 Decls in my tests). To track how much data is being consumed, I've also added a global variable g_TotalSizeOfMetadata which tracks the total number of Decls that have metadata in all active AST contexts. Right now this metadata is enormously useful for tracking down bugs in the debug info parser. In the future I also want to use this information to provide more intelligent error messages instead of printing empty source lines wherever Clang refers to the location where something is defined. llvm-svn: 154634
2012-04-13 00:10:03 +00:00
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));
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
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;
GetUniqueDWARFASTTypeMap().Insert (type_name_const_str,
*unique_ast_entry_ap);
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:
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_enumeration_type:
case DW_TAG_typedef:
case DW_TAG_union_type:
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 ();
if (tag == DW_TAG_structure_type) // this only applies in C
{
clang::RecordDecl *record_decl = clang_type.GetAsRecordDecl();
if (record_decl)
m_record_decl_to_layout_map.insert(std::make_pair(record_decl, LayoutInfo()));
}
}
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-07-08 18:05:41 +00:00
// C decls don't respond to isCompleteDefinition() so we can't
2014-07-01 21:22:11 +00:00
// start the declaration definition right away. For C++ class/union/structs
// 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..
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);
}
}
}
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;
case DW_AT_type: encoding_uid = form_value.Reference(); break;
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();
}
if (!enumerator_clang_type)
enumerator_clang_type = ast.GetBuiltinTypeForDWARFEncodingAndBitSize (NULL,
DW_ATE_signed,
byte_size * 8);
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);
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 ();
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
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);
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
}
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;
case DW_AT_type: type_die_offset = form_value.Reference(); break;
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;
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:
specification_die_offset = form_value.Reference();
break;
case DW_AT_abstract_origin:
abstract_origin_die_offset = form_value.Reference();
break;
case DW_AT_object_pointer:
object_pointer_die_offset = form_value.Reference();
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());
}
}
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;
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
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-07-01 21:22:11 +00:00
// if we find a "this" parameters as the first parameter
if (is_cxx_method)
is_static = true;
if (die->HasChildren())
{
bool skip_artificial = true;
ParseChildParameters (sc,
containing_decl_ctx,
dwarf_cu,
die,
skip_artificial,
is_static,
is_variadic,
type_list,
function_param_types,
function_param_decls,
type_quals);
}
// 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);
bool ignore_containing_context = false;
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;
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)
{
DWARFDIECollection failures;
CopyUniqueClassMethodTypes (class_symfile,
class_type,
class_type_cu_sp.get(),
class_type_die,
dwarf_cu,
decl_ctx_die,
failures);
// 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...
type_ptr = m_die_to_type[die];
if (type_ptr && type_ptr != DIE_IS_BEING_PARSED)
{
type_sp = type_ptr->shared_from_this();
break;
}
}
}
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;
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;
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);
type_handled = cxx_method_decl != NULL;
if (type_handled)
{
LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(cxx_method_decl), die);
Host::SetCrashDescription (NULL);
ClangASTMetadata metadata;
metadata.SetUserID(MakeUserID(die->GetOffset()));
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(),
static_cast<void*>(cxx_method_decl));
}
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;
// 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;
}
// 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;
}
}
}
}
}
}
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());
ClangASTMetadata metadata;
metadata.SetUserID(MakeUserID(die->GetOffset()));
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(),
static_cast<void*>(function_decl));
}
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;
case DW_AT_type: type_die_offset = form_value.Reference(); break;
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;
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
{
clang_type = ast.CreateArrayType (array_element_type, 0, is_vector);
}
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);
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:
type_die_offset = form_value.Reference(); break;
case DW_AT_containing_type:
containing_type_die_offset = form_value.Reference(); break;
}
}
}
Type *pointee_type = ResolveTypeUID(type_die_offset);
Type *class_type = ResolveTypeUID(containing_type_die_offset);
ClangASTType pointee_clang_type = pointee_type->GetClangForwardType();
ClangASTType class_clang_type = class_type->GetClangLayoutType();
clang_type = pointee_clang_type.CreateMemberPointerType(class_clang_type);
byte_size = clang_type.GetByteSize();
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));
}
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;
}
else if (sc.function != NULL && sc_parent_die)
{
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;
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
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;
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
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());
Looking at some of the test suite failures in DWARF in .o files with the debug map showed that the location lists in the .o files needed some refactoring in order to work. The case that was failing was where a function that was in the "__TEXT.__textcoal_nt" in the .o file, and in the "__TEXT.__text" section in the main executable. This made symbol lookup fail due to the way we were finding a real address in the debug map which was by finding the section that the function was in in the .o file and trying to find this in the main executable. Now the section list supports finding a linked address in a section or any child sections. After fixing this, we ran into issue that were due to DWARF and how it represents locations lists. DWARF makes a list of address ranges and expressions that go along with those address ranges. The location addresses are expressed in terms of a compile unit address + offset. This works fine as long as nothing moves around. When stuff moves around and offsets change between the remapped compile unit base address and the new function address, then we can run into trouble. To deal with this, we now store supply a location list slide amount to any location list expressions that will allow us to make the location list addresses into zero based offsets from the object that owns the location list (always a function in our case). With these fixes we can now re-link random address ranges inside the debugger for use with our DWARF + debug map, incremental linking, and more. Another issue that arose when doing the DWARF in the .o files was that GCC 4.2 emits a ".debug_aranges" that only mentions functions that are externally visible. This makes .debug_aranges useless to us and we now generate a real address range lookup table in the DWARF parser at the same time as we index the name tables (that are needed because .debug_pubnames is just as useless). llvm-gcc doesn't generate a .debug_aranges section, though this could be fixed, we aren't going to rely upon it. Renamed a bunch of "UINT_MAX" to "UINT32_MAX". llvm-svn: 113829
2010-09-14 02:20:48 +00:00
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())
Added a new class called lldb_private::SymbolFileType which is designed to take a SymbolFile reference and a lldb::user_id_t and be used in objects which represent things in debug symbols that have types where we don't need to know the true type yet, such as in lldb_private::Variable objects. This allows us to defer resolving the type until something is used. More specifically this allows us to get 1000 local variables from the current function, and if the user types "frame variable argc", we end up _only_ resolving the type for "argc" and not for the 999 other local variables. We can expand the use of this as needed in the future. Modified the DWARFMappedHash class to be able to read the HashData that has more than just the DIE offset. It currently will read the atoms in the header definition and read the data correctly. Currently only the DIE offset and type flags are supported. This is needed for adding type flags to the .apple_types hash accelerator tables. Fixed a assertion crash that would happen if we have a variable that had a DW_AT_const_value instead of a location where "location.LocationContains_DW_OP_addr()" would end up asserting when it tried to parse the variable location as a DWARF opcode list. Decreased the amount of memory that LLDB would use when evaluating an expression by 3x - 4x for clang. There was a place in the namespace lookup code that was parsing all namespaces with a certain name in a DWARF file instead of stopping when it found the first match. This was causing all of the compile units with a matching namespace to get parsed into memory and causing unnecessary memory bloat. Improved "Target::EvaluateExpression(...)" to not try and find a variable when the expression contains characters that would certainly cause an expression to need to be evaluated by the debugger. llvm-svn: 146130
2011-12-08 02:13:16 +00:00
{
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,
Looking at some of the test suite failures in DWARF in .o files with the debug map showed that the location lists in the .o files needed some refactoring in order to work. The case that was failing was where a function that was in the "__TEXT.__textcoal_nt" in the .o file, and in the "__TEXT.__text" section in the main executable. This made symbol lookup fail due to the way we were finding a real address in the debug map which was by finding the section that the function was in in the .o file and trying to find this in the main executable. Now the section list supports finding a linked address in a section or any child sections. After fixing this, we ran into issue that were due to DWARF and how it represents locations lists. DWARF makes a list of address ranges and expressions that go along with those address ranges. The location addresses are expressed in terms of a compile unit address + offset. This works fine as long as nothing moves around. When stuff moves around and offsets change between the remapped compile unit base address and the new function address, then we can run into trouble. To deal with this, we now store supply a location list slide amount to any location list expressions that will allow us to make the location list addresses into zero based offsets from the object that owns the location list (always a function in our case). With these fixes we can now re-link random address ranges inside the debugger for use with our DWARF + debug map, incremental linking, and more. Another issue that arose when doing the DWARF in the .o files was that GCC 4.2 emits a ".debug_aranges" that only mentions functions that are externally visible. This makes .debug_aranges useless to us and we now generate a real address range lookup table in the DWARF parser at the same time as we index the name tables (that are needed because .debug_pubnames is just as useless). llvm-gcc doesn't generate a .debug_aranges section, though this could be fixed, we aren't going to rely upon it. Renamed a bunch of "UINT_MAX" to "UINT32_MAX". llvm-svn: 113829
2010-09-14 02:20:48 +00:00
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();
Added support for reading thread-local storage variables, as defined using the __thread modifier. To make this work this patch extends LLDB to: - Explicitly track the link_map address for each module. This is effectively the module handle, not sure why it wasn't already being stored off anywhere. As an extension later, it would be nice if someone were to add support for printing this as part of the modules list. - Allow reading the per-thread data pointer via ptrace. I have added support for Linux here. I'll be happy to add support for FreeBSD once this is reviewed. OS X does not appear to have __thread variables, so maybe we don't need it there. Windows support should eventually be workable along the same lines. - Make DWARF expressions track which module they originated from. - Add support for the DW_OP_GNU_push_tls_address DWARF opcode, as generated by gcc and recent versions of clang. Earlier versions of clang (such as 3.2, which is default on Ubuntu right now) do not generate TLS debug info correctly so can not be supported here. - Understand the format of the pthread DTV block. This is where it gets tricky. We have three basic options here: 1) Call "dlinfo" or "__tls_get_addr" on the inferior and ask it directly. However this won't work on core dumps, and generally speaking it's not a good idea for the debugger to call functions itself, as it has the potential to not work depending on the state of the target. 2) Use libthread_db. This is what GDB does. However this option requires having a version of libthread_db on the host cross-compiled for each potential target. This places a large burden on the user, and would make it very hard to cross-debug from Windows to Linux, for example. Trying to build a library intended exclusively for one OS on a different one is not pleasant. GDB sidesteps the problem and asks the user to figure it out. 3) Parse the DTV structure ourselves. On initial inspection this seems to be a bad option, as the DTV structure (the format used by the runtime to manage TLS data) is not in fact a kernel data structure, it is implemented entirely in useerland in libc. Therefore the layout of it's fields are version and OS dependent, and are not standardized. However, it turns out not to be such a problem. All OSes use basically the same algorithm (a per-module lookup table) as detailed in Ulrich Drepper's TLS ELF ABI document, so we can easily write code to decode it ourselves. The only question therefore is the exact field layouts required. Happily, the implementors of libpthread expose the structure of the DTV via metadata exported as symbols from the .so itself, designed exactly for this kind of thing. So this patch simply reads that metadata in, and re-implements libthread_db's algorithm itself. We thereby get cross-platform TLS lookup without either requiring third-party libraries, while still being independent of the version of libpthread being used. Test case included. llvm-svn: 192922
2013-10-17 21:14:00 +00:00
ModuleSP module = GetObjectFile()->GetModule();
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;
Added a new class called lldb_private::SymbolFileType which is designed to take a SymbolFile reference and a lldb::user_id_t and be used in objects which represent things in debug symbols that have types where we don't need to know the true type yet, such as in lldb_private::Variable objects. This allows us to defer resolving the type until something is used. More specifically this allows us to get 1000 local variables from the current function, and if the user types "frame variable argc", we end up _only_ resolving the type for "argc" and not for the 999 other local variables. We can expand the use of this as needed in the future. Modified the DWARFMappedHash class to be able to read the HashData that has more than just the DIE offset. It currently will read the atoms in the header definition and read the data correctly. Currently only the DIE offset and type flags are supported. This is needed for adding type flags to the .apple_types hash accelerator tables. Fixed a assertion crash that would happen if we have a variable that had a DW_AT_const_value instead of a location where "location.LocationContains_DW_OP_addr()" would end up asserting when it tried to parse the variable location as a DWARF opcode list. Decreased the amount of memory that LLDB would use when evaluating an expression by 3x - 4x for clang. There was a place in the namespace lookup code that was parsing all namespaces with a certain name in a DWARF file instead of stopping when it found the first match. This was causing all of the compile units with a matching namespace to get parsed into memory and causing unnecessary memory bloat. Improved "Target::EvaluateExpression(...)" to not try and find a variable when the expression contains characters that would certainly cause an expression to need to be evaluated by the debugger. llvm-svn: 146130
2011-12-08 02:13:16 +00:00
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;
DWARFFormValue const_value;
//AccessType accessibility = eAccessNone;
for (i=0; i<num_attributes; ++i)
{
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;
case DW_AT_linkage_name:
case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break;
case DW_AT_type: type_uid = form_value.Reference(); break;
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.
const DWARFDataExtractor& debug_info_data = get_debug_info_data();
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();
Added support for reading thread-local storage variables, as defined using the __thread modifier. To make this work this patch extends LLDB to: - Explicitly track the link_map address for each module. This is effectively the module handle, not sure why it wasn't already being stored off anywhere. As an extension later, it would be nice if someone were to add support for printing this as part of the modules list. - Allow reading the per-thread data pointer via ptrace. I have added support for Linux here. I'll be happy to add support for FreeBSD once this is reviewed. OS X does not appear to have __thread variables, so maybe we don't need it there. Windows support should eventually be workable along the same lines. - Make DWARF expressions track which module they originated from. - Add support for the DW_OP_GNU_push_tls_address DWARF opcode, as generated by gcc and recent versions of clang. Earlier versions of clang (such as 3.2, which is default on Ubuntu right now) do not generate TLS debug info correctly so can not be supported here. - Understand the format of the pthread DTV block. This is where it gets tricky. We have three basic options here: 1) Call "dlinfo" or "__tls_get_addr" on the inferior and ask it directly. However this won't work on core dumps, and generally speaking it's not a good idea for the debugger to call functions itself, as it has the potential to not work depending on the state of the target. 2) Use libthread_db. This is what GDB does. However this option requires having a version of libthread_db on the host cross-compiled for each potential target. This places a large burden on the user, and would make it very hard to cross-debug from Windows to Linux, for example. Trying to build a library intended exclusively for one OS on a different one is not pleasant. GDB sidesteps the problem and asks the user to figure it out. 3) Parse the DTV structure ourselves. On initial inspection this seems to be a bad option, as the DTV structure (the format used by the runtime to manage TLS data) is not in fact a kernel data structure, it is implemented entirely in useerland in libc. Therefore the layout of it's fields are version and OS dependent, and are not standardized. However, it turns out not to be such a problem. All OSes use basically the same algorithm (a per-module lookup table) as detailed in Ulrich Drepper's TLS ELF ABI document, so we can easily write code to decode it ourselves. The only question therefore is the exact field layouts required. Happily, the implementors of libpthread expose the structure of the DTV via metadata exported as symbols from the .so itself, designed exactly for this kind of thing. So this patch simply reads that metadata in, and re-implements libthread_db's algorithm itself. We thereby get cross-platform TLS lookup without either requiring third-party libraries, while still being independent of the version of libpthread being used. Test case included. llvm-svn: 192922
2013-10-17 21:14:00 +00:00
location.CopyOpcodeData(module, debug_info_data, block_offset, block_length);
}
else if (DWARFFormValue::IsDataForm(form_value.Form()))
{
// Retrieve the value as a data expression.
const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), attributes.CompileUnitAtIndex(i)->IsDWARF64());
uint32_t data_offset = attributes.DIEOffsetAtIndex(i);
uint32_t data_length = fixed_form_sizes[form_value.Form()];
if (data_length == 0)
{
const uint8_t *data_pointer = form_value.BlockData();
if (data_pointer)
{
form_value.Unsigned();
}
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);
}
else
{
// Retrieve the value as a string expression.
if (form_value.Form() == DW_FORM_strp)
{
const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), attributes.CompileUnitAtIndex(i)->IsDWARF64());
uint32_t data_offset = attributes.DIEOffsetAtIndex(i);
uint32_t data_length = fixed_form_sizes[form_value.Form()];
Added support for reading thread-local storage variables, as defined using the __thread modifier. To make this work this patch extends LLDB to: - Explicitly track the link_map address for each module. This is effectively the module handle, not sure why it wasn't already being stored off anywhere. As an extension later, it would be nice if someone were to add support for printing this as part of the modules list. - Allow reading the per-thread data pointer via ptrace. I have added support for Linux here. I'll be happy to add support for FreeBSD once this is reviewed. OS X does not appear to have __thread variables, so maybe we don't need it there. Windows support should eventually be workable along the same lines. - Make DWARF expressions track which module they originated from. - Add support for the DW_OP_GNU_push_tls_address DWARF opcode, as generated by gcc and recent versions of clang. Earlier versions of clang (such as 3.2, which is default on Ubuntu right now) do not generate TLS debug info correctly so can not be supported here. - Understand the format of the pthread DTV block. This is where it gets tricky. We have three basic options here: 1) Call "dlinfo" or "__tls_get_addr" on the inferior and ask it directly. However this won't work on core dumps, and generally speaking it's not a good idea for the debugger to call functions itself, as it has the potential to not work depending on the state of the target. 2) Use libthread_db. This is what GDB does. However this option requires having a version of libthread_db on the host cross-compiled for each potential target. This places a large burden on the user, and would make it very hard to cross-debug from Windows to Linux, for example. Trying to build a library intended exclusively for one OS on a different one is not pleasant. GDB sidesteps the problem and asks the user to figure it out. 3) Parse the DTV structure ourselves. On initial inspection this seems to be a bad option, as the DTV structure (the format used by the runtime to manage TLS data) is not in fact a kernel data structure, it is implemented entirely in useerland in libc. Therefore the layout of it's fields are version and OS dependent, and are not standardized. However, it turns out not to be such a problem. All OSes use basically the same algorithm (a per-module lookup table) as detailed in Ulrich Drepper's TLS ELF ABI document, so we can easily write code to decode it ourselves. The only question therefore is the exact field layouts required. Happily, the implementors of libpthread expose the structure of the DTV via metadata exported as symbols from the .so itself, designed exactly for this kind of thing. So this patch simply reads that metadata in, and re-implements libthread_db's algorithm itself. We thereby get cross-platform TLS lookup without either requiring third-party libraries, while still being independent of the version of libpthread being used. Test case included. llvm-svn: 192922
2013-10-17 21:14:00 +00:00
location.CopyOpcodeData(module, debug_info_data, data_offset, data_length);
}
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;
Added support for reading thread-local storage variables, as defined using the __thread modifier. To make this work this patch extends LLDB to: - Explicitly track the link_map address for each module. This is effectively the module handle, not sure why it wasn't already being stored off anywhere. As an extension later, it would be nice if someone were to add support for printing this as part of the modules list. - Allow reading the per-thread data pointer via ptrace. I have added support for Linux here. I'll be happy to add support for FreeBSD once this is reviewed. OS X does not appear to have __thread variables, so maybe we don't need it there. Windows support should eventually be workable along the same lines. - Make DWARF expressions track which module they originated from. - Add support for the DW_OP_GNU_push_tls_address DWARF opcode, as generated by gcc and recent versions of clang. Earlier versions of clang (such as 3.2, which is default on Ubuntu right now) do not generate TLS debug info correctly so can not be supported here. - Understand the format of the pthread DTV block. This is where it gets tricky. We have three basic options here: 1) Call "dlinfo" or "__tls_get_addr" on the inferior and ask it directly. However this won't work on core dumps, and generally speaking it's not a good idea for the debugger to call functions itself, as it has the potential to not work depending on the state of the target. 2) Use libthread_db. This is what GDB does. However this option requires having a version of libthread_db on the host cross-compiled for each potential target. This places a large burden on the user, and would make it very hard to cross-debug from Windows to Linux, for example. Trying to build a library intended exclusively for one OS on a different one is not pleasant. GDB sidesteps the problem and asks the user to figure it out. 3) Parse the DTV structure ourselves. On initial inspection this seems to be a bad option, as the DTV structure (the format used by the runtime to manage TLS data) is not in fact a kernel data structure, it is implemented entirely in useerland in libc. Therefore the layout of it's fields are version and OS dependent, and are not standardized. However, it turns out not to be such a problem. All OSes use basically the same algorithm (a per-module lookup table) as detailed in Ulrich Drepper's TLS ELF ABI document, so we can easily write code to decode it ourselves. The only question therefore is the exact field layouts required. Happily, the implementors of libpthread expose the structure of the DTV via metadata exported as symbols from the .so itself, designed exactly for this kind of thing. So this patch simply reads that metadata in, and re-implements libthread_db's algorithm itself. We thereby get cross-platform TLS lookup without either requiring third-party libraries, while still being independent of the version of libpthread being used. Test case included. llvm-svn: 192922
2013-10-17 21:14:00 +00:00
location.CopyOpcodeData(module, debug_info_data, string_offset, string_length);
}
}
}
break;
case DW_AT_location:
{
location_is_const_value_data = false;
has_explicit_location = true;
if (form_value.BlockData())
{
const DWARFDataExtractor& debug_info_data = get_debug_info_data();
uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
uint32_t block_length = form_value.Unsigned();
Added support for reading thread-local storage variables, as defined using the __thread modifier. To make this work this patch extends LLDB to: - Explicitly track the link_map address for each module. This is effectively the module handle, not sure why it wasn't already being stored off anywhere. As an extension later, it would be nice if someone were to add support for printing this as part of the modules list. - Allow reading the per-thread data pointer via ptrace. I have added support for Linux here. I'll be happy to add support for FreeBSD once this is reviewed. OS X does not appear to have __thread variables, so maybe we don't need it there. Windows support should eventually be workable along the same lines. - Make DWARF expressions track which module they originated from. - Add support for the DW_OP_GNU_push_tls_address DWARF opcode, as generated by gcc and recent versions of clang. Earlier versions of clang (such as 3.2, which is default on Ubuntu right now) do not generate TLS debug info correctly so can not be supported here. - Understand the format of the pthread DTV block. This is where it gets tricky. We have three basic options here: 1) Call "dlinfo" or "__tls_get_addr" on the inferior and ask it directly. However this won't work on core dumps, and generally speaking it's not a good idea for the debugger to call functions itself, as it has the potential to not work depending on the state of the target. 2) Use libthread_db. This is what GDB does. However this option requires having a version of libthread_db on the host cross-compiled for each potential target. This places a large burden on the user, and would make it very hard to cross-debug from Windows to Linux, for example. Trying to build a library intended exclusively for one OS on a different one is not pleasant. GDB sidesteps the problem and asks the user to figure it out. 3) Parse the DTV structure ourselves. On initial inspection this seems to be a bad option, as the DTV structure (the format used by the runtime to manage TLS data) is not in fact a kernel data structure, it is implemented entirely in useerland in libc. Therefore the layout of it's fields are version and OS dependent, and are not standardized. However, it turns out not to be such a problem. All OSes use basically the same algorithm (a per-module lookup table) as detailed in Ulrich Drepper's TLS ELF ABI document, so we can easily write code to decode it ourselves. The only question therefore is the exact field layouts required. Happily, the implementors of libpthread expose the structure of the DTV via metadata exported as symbols from the .so itself, designed exactly for this kind of thing. So this patch simply reads that metadata in, and re-implements libthread_db's algorithm itself. We thereby get cross-platform TLS lookup without either requiring third-party libraries, while still being independent of the version of libpthread being used. Test case included. llvm-svn: 192922
2013-10-17 21:14:00 +00:00
location.CopyOpcodeData(module, get_debug_info_data(), block_offset, block_length);
}
else
{
const DWARFDataExtractor& debug_loc_data = get_debug_loc_data();
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)
{
Added support for reading thread-local storage variables, as defined using the __thread modifier. To make this work this patch extends LLDB to: - Explicitly track the link_map address for each module. This is effectively the module handle, not sure why it wasn't already being stored off anywhere. As an extension later, it would be nice if someone were to add support for printing this as part of the modules list. - Allow reading the per-thread data pointer via ptrace. I have added support for Linux here. I'll be happy to add support for FreeBSD once this is reviewed. OS X does not appear to have __thread variables, so maybe we don't need it there. Windows support should eventually be workable along the same lines. - Make DWARF expressions track which module they originated from. - Add support for the DW_OP_GNU_push_tls_address DWARF opcode, as generated by gcc and recent versions of clang. Earlier versions of clang (such as 3.2, which is default on Ubuntu right now) do not generate TLS debug info correctly so can not be supported here. - Understand the format of the pthread DTV block. This is where it gets tricky. We have three basic options here: 1) Call "dlinfo" or "__tls_get_addr" on the inferior and ask it directly. However this won't work on core dumps, and generally speaking it's not a good idea for the debugger to call functions itself, as it has the potential to not work depending on the state of the target. 2) Use libthread_db. This is what GDB does. However this option requires having a version of libthread_db on the host cross-compiled for each potential target. This places a large burden on the user, and would make it very hard to cross-debug from Windows to Linux, for example. Trying to build a library intended exclusively for one OS on a different one is not pleasant. GDB sidesteps the problem and asks the user to figure it out. 3) Parse the DTV structure ourselves. On initial inspection this seems to be a bad option, as the DTV structure (the format used by the runtime to manage TLS data) is not in fact a kernel data structure, it is implemented entirely in useerland in libc. Therefore the layout of it's fields are version and OS dependent, and are not standardized. However, it turns out not to be such a problem. All OSes use basically the same algorithm (a per-module lookup table) as detailed in Ulrich Drepper's TLS ELF ABI document, so we can easily write code to decode it ourselves. The only question therefore is the exact field layouts required. Happily, the implementors of libpthread expose the structure of the DTV via metadata exported as symbols from the .so itself, designed exactly for this kind of thing. So this patch simply reads that metadata in, and re-implements libthread_db's algorithm itself. We thereby get cross-platform TLS lookup without either requiring third-party libraries, while still being independent of the version of libpthread being used. Test case included. llvm-svn: 192922
2013-10-17 21:14:00 +00:00
location.CopyOpcodeData(module, debug_loc_data, debug_loc_offset, loc_list_length);
assert (func_low_pc != LLDB_INVALID_ADDRESS);
location.SetLocationListSlide (func_low_pc - attributes.CompileUnitAtIndex(i)->GetBaseAddress());
}
}
}
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;
// 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-07-01 21:22:11 +00:00
// looking at the location of a variable to see if it contains
// 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)
<rdar://problem/10338439> This is the actual fix for the above radar where global variables that weren't initialized were not being shown correctly when leaving the DWARF in the .o files. Global variables that aren't intialized have symbols in the .o files that specify they are undefined and external to the .o file, yet document the size of the variable. This allows the compiler to emit a single copy, but makes it harder for our DWARF in .o files with the executable having a debug map because the symbol for the global in the .o file doesn't exist in a section that we can assign a fixed up linked address to, and also the DWARF contains an invalid address in the "DW_OP_addr" location (always zero). This means that the DWARF is incorrect and actually maps all such global varaibles to the first file address in the .o file which is usually the first function. So we can fix this in either of two ways: make a new fake section in the .o file so that we have a file address in the .o file that we can relink, or fix the the variable as it is created in the .o file DWARF parser and actually give it the file address from the executable. Each variable contains a SymbolContextScope, or a single pointer that helps us to recreate where the variables came from (which module, file, function, etc). This context helps us to resolve any file addresses that might be in the location description of the variable by pointing us to which file the file address comes from, so we can just replace the SymbolContextScope and also fix up the location, which we would have had to do for the other case as well, and update the file address. Now globals display correctly. The above changes made it possible to determine if a variable is a global or static variable when parsing DWARF. The DWARF emits a DW_TAG_variable tag for each variable (local, global, or static), yet DWARF provides no way for us to classify these variables into these categories. We can now detect when a variable has a simple address expressions as its location and this will help us classify these correctly. While making the above changes I also noticed that we had two symbol types: eSymbolTypeExtern and eSymbolTypeUndefined which mean essentially the same thing: the symbol is not defined in the current object file. Symbol objects also have a bit that specifies if a symbol is externally visible, so I got rid of the eSymbolTypeExtern symbol type and moved all code locations that used it to use the eSymbolTypeUndefined type. llvm-svn: 144489
2011-11-13 04:15:56 +00:00
{
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());
}
}
Added a new class called lldb_private::SymbolFileType which is designed to take a SymbolFile reference and a lldb::user_id_t and be used in objects which represent things in debug symbols that have types where we don't need to know the true type yet, such as in lldb_private::Variable objects. This allows us to defer resolving the type until something is used. More specifically this allows us to get 1000 local variables from the current function, and if the user types "frame variable argc", we end up _only_ resolving the type for "argc" and not for the 999 other local variables. We can expand the use of this as needed in the future. Modified the DWARFMappedHash class to be able to read the HashData that has more than just the DIE offset. It currently will read the atoms in the header definition and read the data correctly. Currently only the DIE offset and type flags are supported. This is needed for adding type flags to the .apple_types hash accelerator tables. Fixed a assertion crash that would happen if we have a variable that had a DW_AT_const_value instead of a location where "location.LocationContains_DW_OP_addr()" would end up asserting when it tried to parse the variable location as a DWARF opcode list. Decreased the amount of memory that LLDB would use when evaluating an expression by 3x - 4x for clang. There was a place in the namespace lookup code that was parsing all namespaces with a certain name in a DWARF file instead of stopping when it found the first match. This was causing all of the compile units with a matching namespace to get parsed into memory and causing unnecessary memory bloat. Improved "Target::EvaluateExpression(...)" to not try and find a variable when the expression contains characters that would certainly cause an expression to need to be evaluated by the debugger. llvm-svn: 146130
2011-12-08 02:13:16 +00:00
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)
<rdar://problem/10338439> This is the actual fix for the above radar where global variables that weren't initialized were not being shown correctly when leaving the DWARF in the .o files. Global variables that aren't intialized have symbols in the .o files that specify they are undefined and external to the .o file, yet document the size of the variable. This allows the compiler to emit a single copy, but makes it harder for our DWARF in .o files with the executable having a debug map because the symbol for the global in the .o file doesn't exist in a section that we can assign a fixed up linked address to, and also the DWARF contains an invalid address in the "DW_OP_addr" location (always zero). This means that the DWARF is incorrect and actually maps all such global varaibles to the first file address in the .o file which is usually the first function. So we can fix this in either of two ways: make a new fake section in the .o file so that we have a file address in the .o file that we can relink, or fix the the variable as it is created in the .o file DWARF parser and actually give it the file address from the executable. Each variable contains a SymbolContextScope, or a single pointer that helps us to recreate where the variables came from (which module, file, function, etc). This context helps us to resolve any file addresses that might be in the location description of the variable by pointing us to which file the file address comes from, so we can just replace the SymbolContextScope and also fix up the location, which we would have had to do for the other case as well, and update the file address. Now globals display correctly. The above changes made it possible to determine if a variable is a global or static variable when parsing DWARF. The DWARF emits a DW_TAG_variable tag for each variable (local, global, or static), yet DWARF provides no way for us to classify these variables into these categories. We can now detect when a variable has a simple address expressions as its location and this will help us classify these correctly. While making the above changes I also noticed that we had two symbol types: eSymbolTypeExtern and eSymbolTypeUndefined which mean essentially the same thing: the symbol is not defined in the current object file. Symbol objects also have a bit that specifies if a symbol is externally visible, so I got rid of the eSymbolTypeExtern symbol type and moved all code locations that used it to use the eSymbolTypeUndefined type. llvm-svn: 144489
2011-11-13 04:15:56 +00:00
{
// 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)
<rdar://problem/10338439> This is the actual fix for the above radar where global variables that weren't initialized were not being shown correctly when leaving the DWARF in the .o files. Global variables that aren't intialized have symbols in the .o files that specify they are undefined and external to the .o file, yet document the size of the variable. This allows the compiler to emit a single copy, but makes it harder for our DWARF in .o files with the executable having a debug map because the symbol for the global in the .o file doesn't exist in a section that we can assign a fixed up linked address to, and also the DWARF contains an invalid address in the "DW_OP_addr" location (always zero). This means that the DWARF is incorrect and actually maps all such global varaibles to the first file address in the .o file which is usually the first function. So we can fix this in either of two ways: make a new fake section in the .o file so that we have a file address in the .o file that we can relink, or fix the the variable as it is created in the .o file DWARF parser and actually give it the file address from the executable. Each variable contains a SymbolContextScope, or a single pointer that helps us to recreate where the variables came from (which module, file, function, etc). This context helps us to resolve any file addresses that might be in the location description of the variable by pointing us to which file the file address comes from, so we can just replace the SymbolContextScope and also fix up the location, which we would have had to do for the other case as well, and update the file address. Now globals display correctly. The above changes made it possible to determine if a variable is a global or static variable when parsing DWARF. The DWARF emits a DW_TAG_variable tag for each variable (local, global, or static), yet DWARF provides no way for us to classify these variables into these categories. We can now detect when a variable has a simple address expressions as its location and this will help us classify these correctly. While making the above changes I also noticed that we had two symbol types: eSymbolTypeExtern and eSymbolTypeUndefined which mean essentially the same thing: the symbol is not defined in the current object file. Symbol objects also have a bit that specifies if a symbol is externally visible, so I got rid of the eSymbolTypeExtern symbol type and moved all code locations that used it to use the eSymbolTypeUndefined type. llvm-svn: 144489
2011-11-13 04:15:56 +00:00
{
Symtab *debug_map_symtab = debug_map_objfile->GetSymtab();
if (debug_map_symtab)
<rdar://problem/10338439> This is the actual fix for the above radar where global variables that weren't initialized were not being shown correctly when leaving the DWARF in the .o files. Global variables that aren't intialized have symbols in the .o files that specify they are undefined and external to the .o file, yet document the size of the variable. This allows the compiler to emit a single copy, but makes it harder for our DWARF in .o files with the executable having a debug map because the symbol for the global in the .o file doesn't exist in a section that we can assign a fixed up linked address to, and also the DWARF contains an invalid address in the "DW_OP_addr" location (always zero). This means that the DWARF is incorrect and actually maps all such global varaibles to the first file address in the .o file which is usually the first function. So we can fix this in either of two ways: make a new fake section in the .o file so that we have a file address in the .o file that we can relink, or fix the the variable as it is created in the .o file DWARF parser and actually give it the file address from the executable. Each variable contains a SymbolContextScope, or a single pointer that helps us to recreate where the variables came from (which module, file, function, etc). This context helps us to resolve any file addresses that might be in the location description of the variable by pointing us to which file the file address comes from, so we can just replace the SymbolContextScope and also fix up the location, which we would have had to do for the other case as well, and update the file address. Now globals display correctly. The above changes made it possible to determine if a variable is a global or static variable when parsing DWARF. The DWARF emits a DW_TAG_variable tag for each variable (local, global, or static), yet DWARF provides no way for us to classify these variables into these categories. We can now detect when a variable has a simple address expressions as its location and this will help us classify these correctly. While making the above changes I also noticed that we had two symbol types: eSymbolTypeExtern and eSymbolTypeUndefined which mean essentially the same thing: the symbol is not defined in the current object file. Symbol objects also have a bit that specifies if a symbol is externally visible, so I got rid of the eSymbolTypeExtern symbol type and moved all code locations that used it to use the eSymbolTypeUndefined type. llvm-svn: 144489
2011-11-13 04:15:56 +00:00
{
Symbol *exe_symbol = debug_map_symtab->FindFirstSymbolWithNameAndType (const_name,
eSymbolTypeData,
Symtab::eDebugYes,
Symtab::eVisibilityExtern);
if (exe_symbol)
<rdar://problem/10338439> This is the actual fix for the above radar where global variables that weren't initialized were not being shown correctly when leaving the DWARF in the .o files. Global variables that aren't intialized have symbols in the .o files that specify they are undefined and external to the .o file, yet document the size of the variable. This allows the compiler to emit a single copy, but makes it harder for our DWARF in .o files with the executable having a debug map because the symbol for the global in the .o file doesn't exist in a section that we can assign a fixed up linked address to, and also the DWARF contains an invalid address in the "DW_OP_addr" location (always zero). This means that the DWARF is incorrect and actually maps all such global varaibles to the first file address in the .o file which is usually the first function. So we can fix this in either of two ways: make a new fake section in the .o file so that we have a file address in the .o file that we can relink, or fix the the variable as it is created in the .o file DWARF parser and actually give it the file address from the executable. Each variable contains a SymbolContextScope, or a single pointer that helps us to recreate where the variables came from (which module, file, function, etc). This context helps us to resolve any file addresses that might be in the location description of the variable by pointing us to which file the file address comes from, so we can just replace the SymbolContextScope and also fix up the location, which we would have had to do for the other case as well, and update the file address. Now globals display correctly. The above changes made it possible to determine if a variable is a global or static variable when parsing DWARF. The DWARF emits a DW_TAG_variable tag for each variable (local, global, or static), yet DWARF provides no way for us to classify these variables into these categories. We can now detect when a variable has a simple address expressions as its location and this will help us classify these correctly. While making the above changes I also noticed that we had two symbol types: eSymbolTypeExtern and eSymbolTypeUndefined which mean essentially the same thing: the symbol is not defined in the current object file. Symbol objects also have a bit that specifies if a symbol is externally visible, so I got rid of the eSymbolTypeExtern symbol type and moved all code locations that used it to use the eSymbolTypeUndefined type. llvm-svn: 144489
2011-11-13 04:15:56 +00:00
{
if (exe_symbol->ValueIsAddress())
<rdar://problem/10338439> This is the actual fix for the above radar where global variables that weren't initialized were not being shown correctly when leaving the DWARF in the .o files. Global variables that aren't intialized have symbols in the .o files that specify they are undefined and external to the .o file, yet document the size of the variable. This allows the compiler to emit a single copy, but makes it harder for our DWARF in .o files with the executable having a debug map because the symbol for the global in the .o file doesn't exist in a section that we can assign a fixed up linked address to, and also the DWARF contains an invalid address in the "DW_OP_addr" location (always zero). This means that the DWARF is incorrect and actually maps all such global varaibles to the first file address in the .o file which is usually the first function. So we can fix this in either of two ways: make a new fake section in the .o file so that we have a file address in the .o file that we can relink, or fix the the variable as it is created in the .o file DWARF parser and actually give it the file address from the executable. Each variable contains a SymbolContextScope, or a single pointer that helps us to recreate where the variables came from (which module, file, function, etc). This context helps us to resolve any file addresses that might be in the location description of the variable by pointing us to which file the file address comes from, so we can just replace the SymbolContextScope and also fix up the location, which we would have had to do for the other case as well, and update the file address. Now globals display correctly. The above changes made it possible to determine if a variable is a global or static variable when parsing DWARF. The DWARF emits a DW_TAG_variable tag for each variable (local, global, or static), yet DWARF provides no way for us to classify these variables into these categories. We can now detect when a variable has a simple address expressions as its location and this will help us classify these correctly. While making the above changes I also noticed that we had two symbol types: eSymbolTypeExtern and eSymbolTypeUndefined which mean essentially the same thing: the symbol is not defined in the current object file. Symbol objects also have a bit that specifies if a symbol is externally visible, so I got rid of the eSymbolTypeExtern symbol type and moved all code locations that used it to use the eSymbolTypeUndefined type. llvm-svn: 144489
2011-11-13 04:15:56 +00:00
{
const addr_t exe_file_addr = exe_symbol->GetAddress().GetFileAddress();
if (exe_file_addr != LLDB_INVALID_ADDRESS)
<rdar://problem/10338439> This is the actual fix for the above radar where global variables that weren't initialized were not being shown correctly when leaving the DWARF in the .o files. Global variables that aren't intialized have symbols in the .o files that specify they are undefined and external to the .o file, yet document the size of the variable. This allows the compiler to emit a single copy, but makes it harder for our DWARF in .o files with the executable having a debug map because the symbol for the global in the .o file doesn't exist in a section that we can assign a fixed up linked address to, and also the DWARF contains an invalid address in the "DW_OP_addr" location (always zero). This means that the DWARF is incorrect and actually maps all such global varaibles to the first file address in the .o file which is usually the first function. So we can fix this in either of two ways: make a new fake section in the .o file so that we have a file address in the .o file that we can relink, or fix the the variable as it is created in the .o file DWARF parser and actually give it the file address from the executable. Each variable contains a SymbolContextScope, or a single pointer that helps us to recreate where the variables came from (which module, file, function, etc). This context helps us to resolve any file addresses that might be in the location description of the variable by pointing us to which file the file address comes from, so we can just replace the SymbolContextScope and also fix up the location, which we would have had to do for the other case as well, and update the file address. Now globals display correctly. The above changes made it possible to determine if a variable is a global or static variable when parsing DWARF. The DWARF emits a DW_TAG_variable tag for each variable (local, global, or static), yet DWARF provides no way for us to classify these variables into these categories. We can now detect when a variable has a simple address expressions as its location and this will help us classify these correctly. While making the above changes I also noticed that we had two symbol types: eSymbolTypeExtern and eSymbolTypeUndefined which mean essentially the same thing: the symbol is not defined in the current object file. Symbol objects also have a bit that specifies if a symbol is externally visible, so I got rid of the eSymbolTypeExtern symbol type and moved all code locations that used it to use the eSymbolTypeUndefined type. llvm-svn: 144489
2011-11-13 04:15:56 +00:00
{
if (location.Update_DW_OP_addr (exe_file_addr))
<rdar://problem/10338439> This is the actual fix for the above radar where global variables that weren't initialized were not being shown correctly when leaving the DWARF in the .o files. Global variables that aren't intialized have symbols in the .o files that specify they are undefined and external to the .o file, yet document the size of the variable. This allows the compiler to emit a single copy, but makes it harder for our DWARF in .o files with the executable having a debug map because the symbol for the global in the .o file doesn't exist in a section that we can assign a fixed up linked address to, and also the DWARF contains an invalid address in the "DW_OP_addr" location (always zero). This means that the DWARF is incorrect and actually maps all such global varaibles to the first file address in the .o file which is usually the first function. So we can fix this in either of two ways: make a new fake section in the .o file so that we have a file address in the .o file that we can relink, or fix the the variable as it is created in the .o file DWARF parser and actually give it the file address from the executable. Each variable contains a SymbolContextScope, or a single pointer that helps us to recreate where the variables came from (which module, file, function, etc). This context helps us to resolve any file addresses that might be in the location description of the variable by pointing us to which file the file address comes from, so we can just replace the SymbolContextScope and also fix up the location, which we would have had to do for the other case as well, and update the file address. Now globals display correctly. The above changes made it possible to determine if a variable is a global or static variable when parsing DWARF. The DWARF emits a DW_TAG_variable tag for each variable (local, global, or static), yet DWARF provides no way for us to classify these variables into these categories. We can now detect when a variable has a simple address expressions as its location and this will help us classify these correctly. While making the above changes I also noticed that we had two symbol types: eSymbolTypeExtern and eSymbolTypeUndefined which mean essentially the same thing: the symbol is not defined in the current object file. Symbol objects also have a bit that specifies if a symbol is externally visible, so I got rid of the eSymbolTypeExtern symbol type and moved all code locations that used it to use the eSymbolTypeUndefined type. llvm-svn: 144489
2011-11-13 04:15:56 +00:00
{
linked_oso_file_addr = true;
symbol_context_scope = exe_symbol;
<rdar://problem/10338439> This is the actual fix for the above radar where global variables that weren't initialized were not being shown correctly when leaving the DWARF in the .o files. Global variables that aren't intialized have symbols in the .o files that specify they are undefined and external to the .o file, yet document the size of the variable. This allows the compiler to emit a single copy, but makes it harder for our DWARF in .o files with the executable having a debug map because the symbol for the global in the .o file doesn't exist in a section that we can assign a fixed up linked address to, and also the DWARF contains an invalid address in the "DW_OP_addr" location (always zero). This means that the DWARF is incorrect and actually maps all such global varaibles to the first file address in the .o file which is usually the first function. So we can fix this in either of two ways: make a new fake section in the .o file so that we have a file address in the .o file that we can relink, or fix the the variable as it is created in the .o file DWARF parser and actually give it the file address from the executable. Each variable contains a SymbolContextScope, or a single pointer that helps us to recreate where the variables came from (which module, file, function, etc). This context helps us to resolve any file addresses that might be in the location description of the variable by pointing us to which file the file address comes from, so we can just replace the SymbolContextScope and also fix up the location, which we would have had to do for the other case as well, and update the file address. Now globals display correctly. The above changes made it possible to determine if a variable is a global or static variable when parsing DWARF. The DWARF emits a DW_TAG_variable tag for each variable (local, global, or static), yet DWARF provides no way for us to classify these variables into these categories. We can now detect when a variable has a simple address expressions as its location and this will help us classify these correctly. While making the above changes I also noticed that we had two symbol types: eSymbolTypeExtern and eSymbolTypeUndefined which mean essentially the same thing: the symbol is not defined in the current object file. Symbol objects also have a bit that specifies if a symbol is externally visible, so I got rid of the eSymbolTypeExtern symbol type and moved all code locations that used it to use the eSymbolTypeUndefined type. llvm-svn: 144489
2011-11-13 04:15:56 +00:00
}
}
}
}
}
}
}
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;
}
Added a new class called lldb_private::SymbolFileType which is designed to take a SymbolFile reference and a lldb::user_id_t and be used in objects which represent things in debug symbols that have types where we don't need to know the true type yet, such as in lldb_private::Variable objects. This allows us to defer resolving the type until something is used. More specifically this allows us to get 1000 local variables from the current function, and if the user types "frame variable argc", we end up _only_ resolving the type for "argc" and not for the 999 other local variables. We can expand the use of this as needed in the future. Modified the DWARFMappedHash class to be able to read the HashData that has more than just the DIE offset. It currently will read the atoms in the header definition and read the data correctly. Currently only the DIE offset and type flags are supported. This is needed for adding type flags to the .apple_types hash accelerator tables. Fixed a assertion crash that would happen if we have a variable that had a DW_AT_const_value instead of a location where "location.LocationContains_DW_OP_addr()" would end up asserting when it tried to parse the variable location as a DWARF opcode list. Decreased the amount of memory that LLDB would use when evaluating an expression by 3x - 4x for clang. There was a place in the namespace lookup code that was parsing all namespaces with a certain name in a DWARF file instead of stopping when it found the first match. This was causing all of the compile units with a matching namespace to get parsed into memory and causing unnecessary memory bloat. Improved "Target::EvaluateExpression(...)" to not try and find a variable when the expression contains characters that would certainly cause an expression to need to be evaluated by the debugger. llvm-svn: 146130
2011-12-08 02:13:16 +00:00
}
<rdar://problem/10338439> This is the actual fix for the above radar where global variables that weren't initialized were not being shown correctly when leaving the DWARF in the .o files. Global variables that aren't intialized have symbols in the .o files that specify they are undefined and external to the .o file, yet document the size of the variable. This allows the compiler to emit a single copy, but makes it harder for our DWARF in .o files with the executable having a debug map because the symbol for the global in the .o file doesn't exist in a section that we can assign a fixed up linked address to, and also the DWARF contains an invalid address in the "DW_OP_addr" location (always zero). This means that the DWARF is incorrect and actually maps all such global varaibles to the first file address in the .o file which is usually the first function. So we can fix this in either of two ways: make a new fake section in the .o file so that we have a file address in the .o file that we can relink, or fix the the variable as it is created in the .o file DWARF parser and actually give it the file address from the executable. Each variable contains a SymbolContextScope, or a single pointer that helps us to recreate where the variables came from (which module, file, function, etc). This context helps us to resolve any file addresses that might be in the location description of the variable by pointing us to which file the file address comes from, so we can just replace the SymbolContextScope and also fix up the location, which we would have had to do for the other case as well, and update the file address. Now globals display correctly. The above changes made it possible to determine if a variable is a global or static variable when parsing DWARF. The DWARF emits a DW_TAG_variable tag for each variable (local, global, or static), yet DWARF provides no way for us to classify these variables into these categories. We can now detect when a variable has a simple address expressions as its location and this will help us classify these correctly. While making the above changes I also noticed that we had two symbol types: eSymbolTypeExtern and eSymbolTypeUndefined which mean essentially the same thing: the symbol is not defined in the current object file. Symbol objects also have a bit that specifies if a symbol is externally visible, so I got rid of the eSymbolTypeExtern symbol type and moved all code locations that used it to use the eSymbolTypeUndefined type. llvm-svn: 144489
2011-11-13 04:15:56 +00:00
}
}
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)
{
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());
var_sp.reset (new Variable (MakeUserID(die->GetOffset()),
name,
mangled,
type_sp,
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,
Looking at some of the test suite failures in DWARF in .o files with the debug map showed that the location lists in the .o files needed some refactoring in order to work. The case that was failing was where a function that was in the "__TEXT.__textcoal_nt" in the .o file, and in the "__TEXT.__text" section in the main executable. This made symbol lookup fail due to the way we were finding a real address in the debug map which was by finding the section that the function was in in the .o file and trying to find this in the main executable. Now the section list supports finding a linked address in a section or any child sections. After fixing this, we ran into issue that were due to DWARF and how it represents locations lists. DWARF makes a list of address ranges and expressions that go along with those address ranges. The location addresses are expressed in terms of a compile unit address + offset. This works fine as long as nothing moves around. When stuff moves around and offsets change between the remapped compile unit base address and the new function address, then we can run into trouble. To deal with this, we now store supply a location list slide amount to any location list expressions that will allow us to make the location list addresses into zero based offsets from the object that owns the location list (always a function in our case). With these fixes we can now re-link random address ranges inside the debugger for use with our DWARF + debug map, incremental linking, and more. Another issue that arose when doing the DWARF in the .o files was that GCC 4.2 emits a ".debug_aranges" that only mentions functions that are externally visible. This makes .debug_aranges useless to us and we now generate a real address range lookup table in the DWARF parser at the same time as we index the name tables (that are needed because .debug_pubnames is just as useless). llvm-gcc doesn't generate a .debug_aranges section, though this could be fixed, we aren't going to rely upon it. Renamed a bunch of "UINT_MAX" to "UINT32_MAX". llvm-svn: 113829
2010-09-14 02:20:48 +00:00
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-07-01 21:22:11 +00:00
// a concrete block counterpart in the current function. We need
// 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;
}
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
void
SymbolFileDWARF::CompleteTagDecl (void *baton, clang::TagDecl *decl)
{
SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton;
ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl);
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
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);
A few of the issue I have been trying to track down and fix have been due to the way LLDB lazily gets complete definitions for types within the debug info. When we run across a class/struct/union definition in the DWARF, we will only parse the full definition if we need to. This works fine for top level types that are assigned directly to variables and arguments, but when we have a variable with a class, lets say "A" for this example, that has a member: "B *m_b". Initially we don't need to hunt down a definition for this class unless we are ever asked to do something with it ("expr m_b->getDecl()" for example). With my previous approach to lazy type completion, we would be able to take a "A *a" and get a complete type for it, but we wouldn't be able to then do an "a->m_b->getDecl()" unless we always expanded all types within a class prior to handing out the type. Expanding everything is very costly and it would be great if there were a better way. A few months ago I worked with the llvm/clang folks to have the ExternalASTSource class be able to complete classes if there weren't completed yet: class ExternalASTSource { .... virtual void CompleteType (clang::TagDecl *Tag); virtual void CompleteType (clang::ObjCInterfaceDecl *Class); }; This was great, because we can now have the class that is producing the AST (SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources and the object that creates the forward declaration types can now also complete them anywhere within the clang type system. This patch makes a few major changes: - lldb_private::Module classes now own the AST context. Previously the TypeList objects did. - The DWARF parsers now sign up as an external AST sources so they can complete types. - All of the pure clang type system wrapper code we have in LLDB (ClangASTContext, ClangASTType, and more) can now be iterating through children of any type, and if a class/union/struct type (clang::RecordType or ObjC interface) is found that is incomplete, we can ask the AST to get the definition. - The SymbolFileDWARFDebugMap class now will create and use a single AST that all child SymbolFileDWARF classes will share (much like what happens when we have a complete linked DWARF for an executable). We will need to modify some of the ClangUserExpression code to take more advantage of this completion ability in the near future. Meanwhile we should be better off now that we can be accessing any children of variables through pointers and always be able to resolve the clang type if needed. llvm-svn: 123613
2011-01-17 03:46:26 +00:00
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("\nFunction basenames:\n"); m_function_basename_index.Dump (&s);
s.Printf("\nFunction fullnames:\n"); m_function_fullname_index.Dump (&s);
s.Printf("\nFunction methods:\n"); m_function_method_index.Dump (&s);
s.Printf("\nFunction selectors:\n"); m_function_selector_index.Dump (&s);
s.Printf("\nObjective C class selectors:\n"); m_objc_class_selectors_index.Dump (&s);
s.Printf("\nGlobals and statics:\n"); m_global_index.Dump (&s);
s.Printf("\nTypes:\n"); m_type_index.Dump (&s);
s.Printf("\nNamepaces:\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;
}
}
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)
{
SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton;
return symbol_file_dwarf->LayoutRecordType (record_decl, size, alignment, field_offsets, base_offsets, vbase_offsets);
}
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)
{
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",
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()),
success);
return success;
}
<rdar://problem/11757916> Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes: - Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file". - modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly - Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was. - modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile() Cleaned up header includes a bit as well. llvm-svn: 162860
2012-08-29 21:13:06 +00:00
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;
}