<rdar://problem/13338643>

DWARF with .o files now uses 40-60% less memory!

Big fixes include:
- Change line table internal representation to contain "file addresses". Since each line table is owned by a compile unit that is owned by a module, it makes address translation into lldb_private::Address easy to do when needed.
- Removed linked address members/methods from lldb_private::Section and lldb_private::Address
- lldb_private::LineTable can now relink itself using a FileRangeMap to make it easier to re-link line tables in the future
- Added ObjectFile::ClearSymtab() so that we can get rid of the object file symbol tables after we parse them once since they are not needed and kept memory allocated for no reason
- Moved the m_sections_ap (std::auto_ptr to section list) and m_symtab_ap (std::auto_ptr to the lldb_private::Symtab) out of each of the ObjectFile subclasses and put it into lldb_private::ObjectFile.
- Changed how the debug map is parsed and stored to be able to:
    - Lazily parse the debug map for each object file
    - not require the address map for a .o file until debug information is linked for a .o file

llvm-svn: 176454
This commit is contained in:
Greg Clayton 2013-03-04 21:46:16 +00:00
parent 427b404d0a
commit 9422dd64f8
25 changed files with 1486 additions and 999 deletions

View File

@ -393,12 +393,6 @@ public:
bool
ResolveAddressUsingFileSections (lldb::addr_t addr, const SectionList *sections);
bool
IsLinkedAddress () const;
void
ResolveLinkedAddress ();
//------------------------------------------------------------------
/// Set the address to represent \a load_addr.
///

View File

@ -10,6 +10,8 @@
#ifndef liblldb_RangeMap_h_
#define liblldb_RangeMap_h_
#include <vector>
#include "lldb/lldb-private.h"
#include "llvm/ADT/SmallVector.h"
@ -171,7 +173,6 @@ namespace lldb_private {
typedef B BaseType;
typedef S SizeType;
typedef Range<B,S> Entry;
//typedef std::vector<Entry> Collection;
typedef llvm::SmallVector<Entry, N> Collection;
RangeArray () :
@ -445,6 +446,286 @@ namespace lldb_private {
Collection m_entries;
};
template <typename B, typename S>
class RangeVector
{
public:
typedef B BaseType;
typedef S SizeType;
typedef Range<B,S> Entry;
typedef std::vector<Entry> Collection;
RangeVector () :
m_entries ()
{
}
~RangeVector()
{
}
void
Append (const Entry &entry)
{
m_entries.push_back (entry);
}
bool
RemoveEntrtAtIndex (uint32_t idx)
{
if (idx < m_entries.size())
{
m_entries.erase (m_entries.begin() + idx);
return true;
}
return false;
}
void
Sort ()
{
if (m_entries.size() > 1)
std::stable_sort (m_entries.begin(), m_entries.end());
}
#ifdef ASSERT_RANGEMAP_ARE_SORTED
bool
IsSorted () const
{
typename Collection::const_iterator pos, end, prev;
// First we determine if we can combine any of the Entry objects so we
// don't end up allocating and making a new collection for no reason
for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
{
if (prev != end && *pos < *prev)
return false;
}
return true;
}
#endif
void
CombineConsecutiveRanges ()
{
#ifdef ASSERT_RANGEMAP_ARE_SORTED
assert (IsSorted());
#endif
// Can't combine if ranges if we have zero or one range
if (m_entries.size() > 1)
{
// The list should be sorted prior to calling this function
typename Collection::iterator pos;
typename Collection::iterator end;
typename Collection::iterator prev;
bool can_combine = false;
// First we determine if we can combine any of the Entry objects so we
// don't end up allocating and making a new collection for no reason
for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
{
if (prev != end && prev->Overlap(*pos))
{
can_combine = true;
break;
}
}
// We we can combine at least one entry, then we make a new collection
// and populate it accordingly, and then swap it into place.
if (can_combine)
{
Collection minimal_ranges;
for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
{
if (prev != end && prev->Overlap(*pos))
minimal_ranges.back().SetRangeEnd (std::max<BaseType>(prev->GetRangeEnd(), pos->GetRangeEnd()));
else
minimal_ranges.push_back (*pos);
}
// Use the swap technique in case our new vector is much smaller.
// We must swap when using the STL because std::vector objects never
// release or reduce the memory once it has been allocated/reserved.
m_entries.swap (minimal_ranges);
}
}
}
BaseType
GetMinRangeBase (BaseType fail_value) const
{
#ifdef ASSERT_RANGEMAP_ARE_SORTED
assert (IsSorted());
#endif
if (m_entries.empty())
return fail_value;
// m_entries must be sorted, so if we aren't empty, we grab the
// first range's base
return m_entries.front().GetRangeBase();
}
BaseType
GetMaxRangeEnd (BaseType fail_value) const
{
#ifdef ASSERT_RANGEMAP_ARE_SORTED
assert (IsSorted());
#endif
if (m_entries.empty())
return fail_value;
// m_entries must be sorted, so if we aren't empty, we grab the
// last range's end
return m_entries.back().GetRangeEnd();
}
void
Slide (BaseType slide)
{
typename Collection::iterator pos, end;
for (pos = m_entries.begin(), end = m_entries.end(); pos != end; ++pos)
pos->Slide (slide);
}
void
Clear ()
{
m_entries.clear();
}
bool
IsEmpty () const
{
return m_entries.empty();
}
size_t
GetSize () const
{
return m_entries.size();
}
const Entry *
GetEntryAtIndex (size_t i) const
{
if (i<m_entries.size())
return &m_entries[i];
return NULL;
}
// Clients must ensure that "i" is a valid index prior to calling this function
const Entry &
GetEntryRef (size_t i) const
{
return m_entries[i];
}
Entry *
Back()
{
if (m_entries.empty())
return NULL;
return &m_entries.back();
}
const Entry *
Back() const
{
if (m_entries.empty())
return NULL;
return &m_entries.back();
}
static bool
BaseLessThan (const Entry& lhs, const Entry& rhs)
{
return lhs.GetRangeBase() < rhs.GetRangeBase();
}
uint32_t
FindEntryIndexThatContains (B addr) const
{
#ifdef ASSERT_RANGEMAP_ARE_SORTED
assert (IsSorted());
#endif
if (!m_entries.empty())
{
Entry entry (addr, 1);
typename Collection::const_iterator begin = m_entries.begin();
typename Collection::const_iterator end = m_entries.end();
typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
if (pos != end && pos->Contains(addr))
{
return std::distance (begin, pos);
}
else if (pos != begin)
{
--pos;
if (pos->Contains(addr))
return std::distance (begin, pos);
}
}
return UINT32_MAX;
}
const Entry *
FindEntryThatContains (B addr) const
{
#ifdef ASSERT_RANGEMAP_ARE_SORTED
assert (IsSorted());
#endif
if (!m_entries.empty())
{
Entry entry (addr, 1);
typename Collection::const_iterator begin = m_entries.begin();
typename Collection::const_iterator end = m_entries.end();
typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
if (pos != end && pos->Contains(addr))
{
return &(*pos);
}
else if (pos != begin)
{
--pos;
if (pos->Contains(addr))
{
return &(*pos);
}
}
}
return NULL;
}
const Entry *
FindEntryThatContains (const Entry &range) const
{
#ifdef ASSERT_RANGEMAP_ARE_SORTED
assert (IsSorted());
#endif
if (!m_entries.empty())
{
typename Collection::const_iterator begin = m_entries.begin();
typename Collection::const_iterator end = m_entries.end();
typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan);
if (pos != end && pos->Contains(range))
{
return &(*pos);
}
else if (pos != begin)
{
--pos;
if (pos->Contains(range))
{
return &(*pos);
}
}
}
return NULL;
}
protected:
Collection m_entries;
};
//----------------------------------------------------------------------
// A simple range with data class where you get to define the type of
// the range base "B", the type used for the range byte size "S", and
@ -463,6 +744,12 @@ namespace lldb_private {
{
}
RangeData (B base, S size) :
Range<B,S> (base, size),
data ()
{
}
RangeData (B base, S size, DataType d) :
Range<B,S> (base, size),
data (d)
@ -504,7 +791,6 @@ namespace lldb_private {
{
public:
typedef RangeData<B,S,T> Entry;
//typedef std::vector<Entry> Collection;
typedef llvm::SmallVector<Entry, N> Collection;
@ -760,6 +1046,267 @@ namespace lldb_private {
Collection m_entries;
};
// Same as RangeDataArray, but uses std::vector as to not
// require static storage of N items in the class itself
template <typename B, typename S, typename T>
class RangeDataVector
{
public:
typedef RangeData<B,S,T> Entry;
typedef std::vector<Entry> Collection;
RangeDataVector ()
{
}
~RangeDataVector()
{
}
void
Append (const Entry &entry)
{
m_entries.push_back (entry);
}
void
Sort ()
{
if (m_entries.size() > 1)
std::stable_sort (m_entries.begin(), m_entries.end());
}
#ifdef ASSERT_RANGEMAP_ARE_SORTED
bool
IsSorted () const
{
typename Collection::const_iterator pos, end, prev;
// First we determine if we can combine any of the Entry objects so we
// don't end up allocating and making a new collection for no reason
for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
{
if (prev != end && *pos < *prev)
return false;
}
return true;
}
#endif
void
CombineConsecutiveEntriesWithEqualData ()
{
#ifdef ASSERT_RANGEMAP_ARE_SORTED
assert (IsSorted());
#endif
typename Collection::iterator pos;
typename Collection::iterator end;
typename Collection::iterator prev;
bool can_combine = false;
// First we determine if we can combine any of the Entry objects so we
// don't end up allocating and making a new collection for no reason
for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
{
if (prev != end && prev->data == pos->data)
{
can_combine = true;
break;
}
}
// We we can combine at least one entry, then we make a new collection
// and populate it accordingly, and then swap it into place.
if (can_combine)
{
Collection minimal_ranges;
for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
{
if (prev != end && prev->data == pos->data)
minimal_ranges.back().SetRangeEnd (pos->GetRangeEnd());
else
minimal_ranges.push_back (*pos);
}
// Use the swap technique in case our new vector is much smaller.
// We must swap when using the STL because std::vector objects never
// release or reduce the memory once it has been allocated/reserved.
m_entries.swap (minimal_ranges);
}
}
void
Clear ()
{
m_entries.clear();
}
bool
IsEmpty () const
{
return m_entries.empty();
}
size_t
GetSize () const
{
return m_entries.size();
}
const Entry *
GetEntryAtIndex (size_t i) const
{
if (i<m_entries.size())
return &m_entries[i];
return NULL;
}
// Clients must ensure that "i" is a valid index prior to calling this function
const Entry &
GetEntryRef (size_t i) const
{
return m_entries[i];
}
static bool
BaseLessThan (const Entry& lhs, const Entry& rhs)
{
return lhs.GetRangeBase() < rhs.GetRangeBase();
}
uint32_t
FindEntryIndexThatContains (B addr) const
{
#ifdef ASSERT_RANGEMAP_ARE_SORTED
assert (IsSorted());
#endif
if ( !m_entries.empty() )
{
Entry entry (addr, 1);
typename Collection::const_iterator begin = m_entries.begin();
typename Collection::const_iterator end = m_entries.end();
typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
if (pos != end && pos->Contains(addr))
{
return std::distance (begin, pos);
}
else if (pos != begin)
{
--pos;
if (pos->Contains(addr))
return std::distance (begin, pos);
}
}
return UINT32_MAX;
}
Entry *
FindEntryThatContains (B addr)
{
#ifdef ASSERT_RANGEMAP_ARE_SORTED
assert (IsSorted());
#endif
if ( !m_entries.empty() )
{
Entry entry;
entry.SetRangeBase(addr);
entry.SetByteSize(1);
typename Collection::iterator begin = m_entries.begin();
typename Collection::iterator end = m_entries.end();
typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
if (pos != end && pos->Contains(addr))
{
return &(*pos);
}
else if (pos != begin)
{
--pos;
if (pos->Contains(addr))
{
return &(*pos);
}
}
}
return NULL;
}
const Entry *
FindEntryThatContains (B addr) const
{
#ifdef ASSERT_RANGEMAP_ARE_SORTED
assert (IsSorted());
#endif
if ( !m_entries.empty() )
{
Entry entry;
entry.SetRangeBase(addr);
entry.SetByteSize(1);
typename Collection::const_iterator begin = m_entries.begin();
typename Collection::const_iterator end = m_entries.end();
typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
if (pos != end && pos->Contains(addr))
{
return &(*pos);
}
else if (pos != begin)
{
--pos;
if (pos->Contains(addr))
{
return &(*pos);
}
}
}
return NULL;
}
const Entry *
FindEntryThatContains (const Entry &range) const
{
#ifdef ASSERT_RANGEMAP_ARE_SORTED
assert (IsSorted());
#endif
if ( !m_entries.empty() )
{
typename Collection::const_iterator begin = m_entries.begin();
typename Collection::const_iterator end = m_entries.end();
typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan);
if (pos != end && pos->Contains(range))
{
return &(*pos);
}
else if (pos != begin)
{
--pos;
if (pos->Contains(range))
{
return &(*pos);
}
}
}
return NULL;
}
Entry *
Back()
{
if (!m_entries.empty())
return &m_entries.back();
return NULL;
}
const Entry *
Back() const
{
if (!m_entries.empty())
return &m_entries.back();
return NULL;
}
protected:
Collection m_entries;
};
//----------------------------------------------------------------------
// A simple range with data class where you get to define the type of
@ -816,7 +1363,6 @@ namespace lldb_private {
{
public:
typedef AddressData<B,T> Entry;
//typedef std::vector<Entry> Collection;
typedef llvm::SmallVector<Entry, N> Collection;

View File

@ -61,9 +61,6 @@ public:
lldb::SectionSP
FindSectionContainingFileAddress (lldb::addr_t addr, uint32_t depth = UINT32_MAX) const;
lldb::SectionSP
FindSectionContainingLinkedFileAddress (lldb::addr_t vm_addr, uint32_t depth) const;
bool
GetSectionData (const DataExtractor& module_data, DataExtractor& section_data) const;
@ -93,16 +90,6 @@ public:
protected:
collection m_sections;
typedef RangeDataArray<uint64_t, uint64_t, collection::size_type, 1> SectionRangeCache;
mutable SectionRangeCache m_range_cache;
#ifdef LLDB_CONFIGURATION_DEBUG
mutable bool m_finalized;
#endif
void BuildRangeCache() const;
void InvalidateRangeCache() const;
};
@ -120,8 +107,8 @@ public:
lldb::SectionType sect_type,
lldb::addr_t file_vm_addr,
lldb::addr_t vm_size,
uint64_t file_offset,
uint64_t file_size,
lldb::offset_t file_offset,
lldb::offset_t file_size,
uint32_t flags);
// Create a section that is a child of parent_section_sp
@ -132,8 +119,8 @@ public:
lldb::SectionType sect_type,
lldb::addr_t file_vm_addr,
lldb::addr_t vm_size,
uint64_t file_offset,
uint64_t file_size,
lldb::offset_t file_offset,
lldb::offset_t file_size,
uint32_t flags);
~Section ();
@ -168,26 +155,26 @@ public:
bool
ResolveContainedAddress (lldb::addr_t offset, Address &so_addr) const;
uint64_t
lldb::offset_t
GetFileOffset () const
{
return m_file_offset;
}
void
SetFileOffset (uint64_t file_offset)
SetFileOffset (lldb::offset_t file_offset)
{
m_file_offset = file_offset;
}
uint64_t
lldb::offset_t
GetFileSize () const
{
return m_file_size;
}
void
SetFileSize (uint64_t file_size)
SetFileSize (lldb::offset_t file_size)
{
m_file_size = file_size;
}
@ -239,31 +226,14 @@ public:
IsDescendant (const Section *section);
const ConstString&
GetName () const;
GetName () const
{
return m_name;
}
bool
Slide (lldb::addr_t slide_amount, bool slide_children);
void
SetLinkedLocation (const lldb::SectionSP &linked_section_sp, uint64_t linked_offset);
bool
ContainsLinkedFileAddress (lldb::addr_t vm_addr) const;
lldb::SectionSP
GetLinkedSection () const
{
return m_linked_section_wp.lock();
}
uint64_t
GetLinkedOffset () const
{
return m_linked_offset;
}
lldb::addr_t
GetLinkedFileAddress () const;
lldb::SectionType
GetType () const
@ -304,8 +274,8 @@ protected:
lldb::addr_t m_file_addr; // The absolute file virtual address range of this section if m_parent == NULL,
// offset from parent file virtual address if m_parent != NULL
lldb::addr_t m_byte_size; // Size in bytes that this section will occupy in memory at runtime
uint64_t m_file_offset; // Object file offset (if any)
uint64_t m_file_size; // Object file size (can be smaller than m_byte_size for zero filled sections...)
lldb::offset_t m_file_offset; // Object file offset (if any)
lldb::offset_t m_file_size; // Object file size (can be smaller than m_byte_size for zero filled sections...)
SectionList m_children; // Child sections
bool m_fake:1, // If true, then this section only can contain the address if one of its
// children contains an address. This allows for gaps between the children
@ -313,8 +283,6 @@ protected:
// hits unless the children contain the address.
m_encrypted:1, // Set to true if the contents are encrypted
m_thread_specific:1;// This section is thread specific
lldb::SectionWP m_linked_section_wp;
uint64_t m_linked_offset;
private:
DISALLOW_COPY_AND_ASSIGN (Section);
};

View File

@ -139,21 +139,20 @@ public:
/// us detect if a variable is a global or static variable since
/// there is no other indication from DWARF debug info.
///
/// @param[in] file_addr
/// The file address to search for in the location.
/// @param[in] op_addr_idx
/// The DW_OP_addr index to retrieve in case there is more than
/// one DW_OP_addr opcode in the location byte stream.
///
/// @param[out] error
/// If the location stream contains unknown DW_OP opcodes or the
/// data is missing, \a error will be set to \b true.
///
/// @return
/// True if IsLocationList() is false and the \a file_addr was
/// is contained in a DW_OP_addr location opcode or if \a file_addr
/// was invalid and there are any DW_OP_addr opcodes, false
/// otherwise.
/// LLDB_INVALID_ADDRESS if the location doesn't contain a
/// DW_OP_addr for \a op_addr_idx, otherwise a valid file address
//------------------------------------------------------------------
bool
LocationContains_DW_OP_addr (lldb::addr_t file_addr, bool &error) const;
lldb::addr_t
GetLocation_DW_OP_addr (uint32_t op_addr_idx, bool &error) const;
bool
Update_DW_OP_addr (lldb::addr_t file_addr);

View File

@ -75,8 +75,7 @@ public:
// Called when you can't guarantee the addresses are in increasing order
void
InsertLineEntry (const lldb::SectionSP& section_sp,
lldb::addr_t section_offset,
InsertLineEntry (lldb::addr_t file_addr,
uint32_t line,
uint16_t column,
uint16_t file_idx,
@ -94,8 +93,7 @@ public:
// inserted in this line table.
void
AppendLineEntryToSequence (LineSequence* sequence,
const lldb::SectionSP& section_sp,
lldb::addr_t section_offset,
lldb::addr_t file_addr,
uint32_t line,
uint16_t column,
uint16_t file_idx,
@ -253,15 +251,29 @@ public:
size_t
GetContiguousFileAddressRanges (FileAddressRanges &file_ranges, bool append);
//------------------------------------------------------------------
/// Given a file range link map, relink the current line table
/// and return a fixed up line table.
///
/// @param[out] file_range_map
/// A collection of file ranges that maps to new file ranges
/// that will be used when linking the line table.
///
/// @return
/// A new line table if at least one line table entry was able
/// to be mapped.
//------------------------------------------------------------------
typedef RangeDataVector<lldb::addr_t, lldb::addr_t, lldb::addr_t> FileRangeMap;
LineTable *
LinkLineTable (const FileRangeMap &file_range_map);
protected:
struct Entry
{
enum { kInvalidSectIdx = UINT32_MAX };
Entry () :
sect_idx (kInvalidSectIdx),
sect_offset (0),
file_addr (LLDB_INVALID_ADDRESS),
line (0),
column (0),
file_idx (0),
@ -273,8 +285,7 @@ protected:
{
}
Entry ( uint32_t _sect_idx,
lldb::addr_t _sect_offset,
Entry ( lldb::addr_t _file_addr,
uint32_t _line,
uint16_t _column,
uint16_t _file_idx,
@ -283,8 +294,7 @@ protected:
bool _is_prologue_end,
bool _is_epilogue_begin,
bool _is_terminal_entry) :
sect_idx (_sect_idx),
sect_offset (_sect_offset),
file_addr (_file_addr),
line (_line),
column (_column),
file_idx (_file_idx),
@ -294,10 +304,6 @@ protected:
is_epilogue_begin (_is_epilogue_begin),
is_terminal_entry (_is_terminal_entry)
{
// We have reserved 32 bits for the section offset which should
// be enough, but if it isn't then we need to make m_section_offset
// bigger
assert(_sect_offset <= UINT32_MAX);
}
int
@ -306,8 +312,7 @@ protected:
void
Clear ()
{
sect_idx = kInvalidSectIdx;
sect_offset = 0;
file_addr = LLDB_INVALID_ADDRESS;
line = 0;
column = 0;
file_idx = 0;
@ -323,7 +328,7 @@ protected:
{
// Compare the sections before calling
#define SCALAR_COMPARE(a,b) if (a < b) return -1; if (a > b) return +1
SCALAR_COMPARE (lhs.sect_offset, rhs.sect_offset);
SCALAR_COMPARE (lhs.file_addr, rhs.file_addr);
SCALAR_COMPARE (lhs.line, rhs.line);
SCALAR_COMPARE (lhs.column, rhs.column);
SCALAR_COMPARE (lhs.is_start_of_statement, rhs.is_start_of_statement);
@ -350,16 +355,13 @@ protected:
static bool EntryAddressLessThan (const Entry& lhs, const Entry& rhs)
{
if (lhs.sect_idx == rhs.sect_idx)
return lhs.sect_offset < rhs.sect_offset;
return lhs.sect_idx < rhs.sect_idx;
return lhs.file_addr < rhs.file_addr;
}
//------------------------------------------------------------------
// Member variables.
//------------------------------------------------------------------
uint32_t sect_idx; ///< The section index for this line entry.
uint32_t sect_offset; ///< The offset into the section for this line entry.
lldb::addr_t file_addr; ///< The file address for this line entry
uint32_t line; ///< The source line number, or zero if there is no line number information.
uint16_t column; ///< The column number of the source line, or zero if there is no column information.
uint16_t file_idx:11, ///< The file index into CompileUnit's file table, or zero if there is no file information.
@ -386,7 +388,6 @@ protected:
// Member variables.
//------------------------------------------------------------------
CompileUnit* m_comp_unit; ///< The compile unit that this line table belongs to.
SectionList m_section_list; ///< The list of sections that at least one of the line entries exists in.
entry_collection m_entries; ///< The collection of line entries in this line table.
//------------------------------------------------------------------
@ -406,14 +407,12 @@ protected:
virtual void
Clear();
entry_collection m_seq_entries; ///< The collection of line entries in this sequence.
entry_collection m_entries; ///< The collection of line entries in this sequence.
};
bool
ConvertEntryAtIndexToLineEntry (uint32_t idx, LineEntry &line_entry);
lldb_private::Section *
GetSectionForEntryIndex (uint32_t idx);
private:
DISALLOW_COPY_AND_ASSIGN (LineTable);
};

View File

@ -350,6 +350,17 @@ public:
virtual Symtab *
GetSymtab () = 0;
//------------------------------------------------------------------
/// Frees the symbol table.
///
/// This function should only be used when an object file is
///
/// @return
/// The symbol table for this object file.
//------------------------------------------------------------------
virtual void
ClearSymtab ();
//------------------------------------------------------------------
/// Gets the UUID for this object file.
///
@ -610,6 +621,8 @@ protected:
lldb_private::UnwindTable m_unwind_table; /// < Table of FuncUnwinders objects created for this ObjectFile's functions
lldb::ProcessWP m_process_wp;
const lldb::addr_t m_memory_addr;
std::auto_ptr<lldb_private::SectionList> m_sections_ap;
std::auto_ptr<lldb_private::Symtab> m_symtab_ap;
//------------------------------------------------------------------
/// Sets the architecture for a module. At present the architecture

View File

@ -1015,29 +1015,6 @@ lldb_private::operator!= (const Address& a, const Address& rhs)
a.GetOffset() != rhs.GetOffset();
}
bool
Address::IsLinkedAddress () const
{
SectionSP section_sp (GetSection());
return section_sp && section_sp->GetLinkedSection();
}
void
Address::ResolveLinkedAddress ()
{
SectionSP section_sp (GetSection());
if (section_sp)
{
SectionSP linked_section_sp (section_sp->GetLinkedSection());
if (linked_section_sp)
{
m_offset += section_sp->GetLinkedOffset();
m_section_wp = linked_section_sp;
}
}
}
AddressClass
Address::GetAddressClass () const
{

View File

@ -21,8 +21,8 @@ Section::Section (const ModuleSP &module_sp,
SectionType sect_type,
addr_t file_addr,
addr_t byte_size,
uint64_t file_offset,
uint64_t file_size,
lldb::offset_t file_offset,
lldb::offset_t file_size,
uint32_t flags) :
ModuleChild (module_sp),
UserID (sect_id),
@ -37,9 +37,7 @@ Section::Section (const ModuleSP &module_sp,
m_children (),
m_fake (false),
m_encrypted (false),
m_thread_specific (false),
m_linked_section_wp(),
m_linked_offset (0)
m_thread_specific (false)
{
// printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s\n",
// this, module_sp.get(), sect_id, file_addr, file_addr + byte_size, file_offset, file_offset + file_size, flags, name.GetCString());
@ -52,8 +50,8 @@ Section::Section (const lldb::SectionSP &parent_section_sp,
SectionType sect_type,
addr_t file_addr,
addr_t byte_size,
uint64_t file_offset,
uint64_t file_size,
lldb::offset_t file_offset,
lldb::offset_t file_size,
uint32_t flags) :
ModuleChild (module_sp),
UserID (sect_id),
@ -68,9 +66,7 @@ Section::Section (const lldb::SectionSP &parent_section_sp,
m_children (),
m_fake (false),
m_encrypted (false),
m_thread_specific (false),
m_linked_section_wp(),
m_linked_offset (0)
m_thread_specific (false)
{
// printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s.%s\n",
// this, module_sp.get(), sect_id, file_addr, file_addr + byte_size, file_offset, file_offset + file_size, flags, parent_section_sp->GetName().GetCString(), name.GetCString());
@ -83,15 +79,6 @@ Section::~Section()
// printf ("Section::~Section(%p)\n", this);
}
const ConstString&
Section::GetName() const
{
SectionSP linked_section_sp (m_linked_section_wp.lock());
if (linked_section_sp)
return linked_section_sp->GetName();
return m_name;
}
addr_t
Section::GetFileAddress () const
{
@ -119,30 +106,10 @@ Section::GetOffset () const
return 0;
}
addr_t
Section::GetLinkedFileAddress () const
{
SectionSP linked_section_sp (m_linked_section_wp.lock());
if (linked_section_sp)
return linked_section_sp->GetFileAddress() + m_linked_offset;
return LLDB_INVALID_ADDRESS;
}
addr_t
Section::GetLoadBaseAddress (Target *target) const
{
addr_t load_base_addr = LLDB_INVALID_ADDRESS;
SectionSP linked_section_sp (m_linked_section_wp.lock());
if (linked_section_sp)
{
load_base_addr = linked_section_sp->GetLoadBaseAddress(target);
if (load_base_addr != LLDB_INVALID_ADDRESS)
load_base_addr += m_linked_offset;
}
else
{
SectionSP parent_sp (GetParent ());
if (parent_sp)
{
@ -154,8 +121,6 @@ Section::GetLoadBaseAddress (Target *target) const
{
load_base_addr = target->GetSectionLoadList().GetSectionLoadAddress (const_cast<Section *>(this)->shared_from_this());
}
}
return load_base_addr;
}
@ -174,14 +139,6 @@ Section::ResolveContainedAddress (addr_t offset, Address &so_addr) const
return child_section->ResolveContainedAddress (offset - child_offset, so_addr);
}
}
SectionSP linked_section_sp (m_linked_section_wp.lock());
if (linked_section_sp)
{
so_addr.SetOffset(m_linked_offset + offset);
so_addr.SetSection(linked_section_sp);
}
else
{
so_addr.SetOffset(offset);
so_addr.SetSection(const_cast<Section *>(this)->shared_from_this());
@ -189,7 +146,6 @@ Section::ResolveContainedAddress (addr_t offset, Address &so_addr) const
// For debug builds, ensure that there are no orphaned (i.e., moduleless) sections.
assert(GetModule().get());
#endif
}
return true;
}
@ -208,21 +164,6 @@ Section::ContainsFileAddress (addr_t vm_addr) const
return false;
}
bool
Section::ContainsLinkedFileAddress (addr_t vm_addr) const
{
const addr_t linked_file_addr = GetLinkedFileAddress();
if (linked_file_addr != LLDB_INVALID_ADDRESS)
{
if (linked_file_addr <= vm_addr)
{
const addr_t offset = vm_addr - linked_file_addr;
return offset < GetByteSize();
}
}
return false;
}
int
Section::Compare (const Section& a, const Section& b)
{
@ -261,12 +202,11 @@ Section::Dump (Stream *s, Target *target, uint32_t depth) const
bool resolved = true;
addr_t addr = LLDB_INVALID_ADDRESS;
SectionSP linked_section_sp (m_linked_section_wp.lock());
if (GetByteSize() == 0)
s->Printf("%39s", "");
else
{
if (target && linked_section_sp.get() == NULL)
if (target)
addr = GetLoadBaseAddress (target);
if (addr == LLDB_INVALID_ADDRESS)
@ -286,35 +226,6 @@ Section::Dump (Stream *s, Target *target, uint32_t depth) const
s->EOL();
if (linked_section_sp)
{
addr = LLDB_INVALID_ADDRESS;
resolved = true;
if (target)
{
addr = linked_section_sp->GetLoadBaseAddress(target);
if (addr != LLDB_INVALID_ADDRESS)
addr += m_linked_offset;
}
if (addr == LLDB_INVALID_ADDRESS)
{
if (target)
resolved = false;
addr = linked_section_sp->GetFileAddress() + m_linked_offset;
}
int indent = 28 + s->GetIndentLevel();
s->Printf("%*.*s", indent, indent, "");
VMRange linked_range(addr, addr + m_byte_size);
linked_range.Dump (s, 0);
indent = 3 * (sizeof(uint32_t) * 2 + 2 + 1) + 1;
s->Printf("%c%*.*s", resolved ? ' ' : '*', indent, indent, "");
linked_section_sp->DumpName(s);
s->Printf(" + 0x%" PRIx64 "\n", m_linked_offset);
}
if (depth > 0)
m_children.Dump(s, target, false, depth - 1);
}
@ -371,22 +282,10 @@ Section::Slide (addr_t slide_amount, bool slide_children)
return false;
}
void
Section::SetLinkedLocation (const lldb::SectionSP &linked_section_sp, uint64_t linked_offset)
{
if (linked_section_sp)
m_module_wp = linked_section_sp->GetModule();
m_linked_section_wp = linked_section_sp;
m_linked_offset = linked_offset;
}
#pragma mark SectionList
SectionList::SectionList () :
m_sections()
#ifdef LLDB_CONFIGURATION_DEBUG
, m_finalized(false)
#endif
{
}
@ -401,7 +300,6 @@ SectionList::AddSection (const lldb::SectionSP& section_sp)
assert (section_sp.get());
size_t section_index = m_sections.size();
m_sections.push_back(section_sp);
InvalidateRangeCache();
return section_index;
}
@ -441,7 +339,6 @@ SectionList::ReplaceSection (user_id_t sect_id, const lldb::SectionSP& sect_sp,
if ((*sect_iter)->GetID() == sect_id)
{
*sect_iter = sect_sp;
InvalidateRangeCache();
return true;
}
else if (depth > 0)
@ -575,71 +472,6 @@ SectionList::FindSectionContainingFileAddress (addr_t vm_addr, uint32_t depth) c
return sect_sp;
}
void
SectionList::BuildRangeCache() const
{
m_range_cache.Clear();
for (collection::size_type idx = 0, last_idx = m_sections.size();
idx < last_idx;
++idx)
{
Section *sect = m_sections[idx].get();
addr_t linked_file_address = sect->GetLinkedFileAddress();
if (linked_file_address != LLDB_INVALID_ADDRESS)
m_range_cache.Append(SectionRangeCache::Entry(linked_file_address, sect->GetByteSize(), idx));
}
m_range_cache.Sort();
#ifdef LLDB_CONFIGURATION_DEBUG
m_finalized = true;
#endif
}
void
SectionList::InvalidateRangeCache() const
{
#ifdef LLDB_CONFIGURATION_DEBUG
assert(!m_finalized);
#endif
m_range_cache.Clear();
}
SectionSP
SectionList::FindSectionContainingLinkedFileAddress (addr_t vm_addr, uint32_t depth) const
{
//if (m_range_cache.IsEmpty())
// BuildRangeCache();
#ifdef LLDB_CONFIGURATION_DEBUG
assert(m_finalized);
#endif
SectionRangeCache::Entry *entry = m_range_cache.FindEntryThatContains(vm_addr);
if (entry)
return m_sections[entry->data];
if (depth == 0)
return SectionSP();
for (const_iterator si = m_sections.begin(), se = m_sections.end();
si != se;
++si)
{
Section *sect = si->get();
SectionSP sect_sp = sect->GetChildren().FindSectionContainingLinkedFileAddress(vm_addr, depth - 1);
if (sect_sp)
return sect_sp;
}
return SectionSP();
}
bool
SectionList::ContainsSection(user_id_t sect_id) const
{
@ -681,15 +513,12 @@ SectionList::Slide (addr_t slide_amount, bool slide_children)
if ((*pos)->Slide(slide_amount, slide_children))
++count;
}
InvalidateRangeCache();
return count;
}
void
SectionList::Finalize ()
{
BuildRangeCache();
for (const_iterator si = m_sections.begin(), se = m_sections.end();
si != se;
++si)

View File

@ -1009,24 +1009,25 @@ GetOpcodeDataSize (const DataExtractor &data, const lldb::offset_t data_offset,
return LLDB_INVALID_OFFSET;
}
bool
DWARFExpression::LocationContains_DW_OP_addr (lldb::addr_t file_addr, bool &error) const
lldb::addr_t
DWARFExpression::GetLocation_DW_OP_addr (uint32_t op_addr_idx, bool &error) const
{
error = false;
if (IsLocationList())
return false;
return LLDB_INVALID_ADDRESS;
lldb::offset_t offset = 0;
uint32_t curr_op_addr_idx = 0;
while (m_data.ValidOffset(offset))
{
const uint8_t op = m_data.GetU8(&offset);
if (op == DW_OP_addr)
{
if (file_addr == LLDB_INVALID_ADDRESS)
return true;
addr_t op_file_addr = m_data.GetAddress(&offset);
if (op_file_addr == file_addr)
return true;
const lldb::addr_t op_file_addr = m_data.GetAddress(&offset);
if (curr_op_addr_idx == op_addr_idx)
return op_file_addr;
else
++curr_op_addr_idx;
}
else
{
@ -1039,7 +1040,7 @@ DWARFExpression::LocationContains_DW_OP_addr (lldb::addr_t file_addr, bool &erro
offset += op_arg_size;
}
}
return false;
return LLDB_INVALID_ADDRESS;
}
bool

View File

@ -254,8 +254,6 @@ ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp,
m_header(),
m_program_headers(),
m_section_headers(),
m_sections_ap(),
m_symtab_ap(),
m_filespec_ap(),
m_shstr_data()
{

View File

@ -153,12 +153,6 @@ private:
/// Collection of symbols from the dynamic table.
DynamicSymbolColl m_dynamic_symbols;
/// List of sections present in this ELF object file.
mutable std::auto_ptr<lldb_private::SectionList> m_sections_ap;
/// Table of all non-dynamic symbols present in this object file.
mutable std::auto_ptr<lldb_private::Symtab> m_symtab_ap;
/// List of file specifications corresponding to the modules (shared
/// libraries) on which this object file depends.
mutable std::auto_ptr<lldb_private::FileSpecList> m_filespec_ap;

View File

@ -501,8 +501,6 @@ ObjectFileMachO::ObjectFileMachO(const lldb::ModuleSP &module_sp,
lldb::offset_t file_offset,
lldb::offset_t length) :
ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
m_sections_ap(),
m_symtab_ap(),
m_mach_segments(),
m_mach_sections(),
m_entry_point_address(),
@ -518,8 +516,6 @@ ObjectFileMachO::ObjectFileMachO (const lldb::ModuleSP &module_sp,
const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr) :
ObjectFile(module_sp, process_sp, header_addr, header_data_sp),
m_sections_ap(),
m_symtab_ap(),
m_mach_segments(),
m_mach_sections(),
m_entry_point_address(),

View File

@ -146,8 +146,6 @@ public:
protected:
llvm::MachO::mach_header m_header;
mutable std::auto_ptr<lldb_private::SectionList> m_sections_ap;
mutable std::auto_ptr<lldb_private::Symtab> m_symtab_ap;
static const lldb_private::ConstString &GetSegmentNameTEXT();
static const lldb_private::ConstString &GetSegmentNameDATA();
static const lldb_private::ConstString &GetSegmentNameOBJC();
@ -157,7 +155,7 @@ protected:
llvm::MachO::dysymtab_command m_dysymtab;
std::vector<llvm::MachO::segment_command_64> m_mach_segments;
std::vector<llvm::MachO::section_64> m_mach_sections;
typedef lldb_private::RangeArray<uint32_t, uint32_t, 1> FileRangeArray;
typedef lldb_private::RangeVector<uint32_t, uint32_t> FileRangeArray;
lldb_private::Address m_entry_point_address;
FileRangeArray m_thread_context_offsets;
bool m_thread_context_offsets_valid;

View File

@ -229,8 +229,6 @@ protected:
typedef SectionHeaderColl::iterator SectionHeaderCollIter;
typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter;
private:
mutable std::auto_ptr<lldb_private::SectionList> m_sections_ap;
mutable std::auto_ptr<lldb_private::Symtab> m_symtab_ap;
dos_header_t m_dos_header;
coff_header_t m_coff_header;
coff_opt_header_t m_coff_header_opt;

View File

@ -130,7 +130,7 @@ private:
// For ProcessMachCore only
//------------------------------------------------------------------
typedef lldb_private::Range<uint32_t, uint32_t> FileRange;
typedef lldb_private::RangeDataArray<lldb::addr_t, lldb::addr_t, FileRange, 1> VMRangeToFileOffset;
typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, FileRange> VMRangeToFileOffset;
VMRangeToFileOffset m_core_aranges;
lldb::ModuleSP m_core_module_sp;

View File

@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
#ifndef SymbolFileDWARF_DWARFDebugLine_h_
#define SymbolFileDWARF_DWARFDebugLine_h_
#ifndef SymbolFileDWARF_DWARFDebugMacinfo_h_
#define SymbolFileDWARF_DWARFDebugMacinfo_h_
#include "SymbolFileDWARF.h"
@ -26,4 +26,4 @@ public:
};
#endif // SymbolFileDWARF_DWARFDebugLine_h_
#endif // SymbolFileDWARF_DWARFDebugMacinfo_h_

View File

@ -182,9 +182,9 @@ LogChannelDWARF::ListCategories (Stream *strm)
" line - log the parsing if .debug_line\n"
" pubnames - log the parsing if .debug_pubnames\n"
" pubtypes - log the parsing if .debug_pubtypes\n"
" lookups - log any lookups that happen by name, regex, or address\n\n"
" completion - log struct/unions/class type completions\n\n"
" map - log insertions of object files into DWARF debug maps\n\n",
" lookups - log any lookups that happen by name, regex, or address\n"
" completion - log struct/unions/class type completions\n"
" map - log insertions of object files into DWARF debug maps\n",
SymbolFileDWARF::GetPluginNameStatic());
}

View File

@ -891,12 +891,12 @@ SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, DWARFCompile
assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED);
func_range.GetBaseAddress().ResolveLinkedAddress();
if (FixupAddress (func_range.GetBaseAddress()))
{
const user_id_t func_user_id = MakeUserID(die->GetOffset());
func_sp.reset(new Function (sc.comp_unit,
func_user_id, // UserID is the DIE offset
func_user_id,
MakeUserID(func_user_id), // UserID is the DIE offset
MakeUserID(func_user_id),
func_name,
func_type,
func_range)); // first address range
@ -910,9 +910,21 @@ SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, DWARFCompile
}
}
}
}
return NULL;
}
bool
SymbolFileDWARF::FixupAddress (Address &addr)
{
SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile ();
if (debug_map_symfile)
{
return debug_map_symfile->LinkOSOAddress(addr);
}
// This is a normal DWARF file, no address fixups need to happen
return true;
}
lldb::LanguageType
SymbolFileDWARF::ParseCompileUnitLanguage (const SymbolContext& sc)
{
@ -983,15 +995,7 @@ SymbolFileDWARF::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpec
struct ParseDWARFLineTableCallbackInfo
{
LineTable* line_table;
const SectionList *section_list;
lldb::addr_t prev_sect_file_base_addr;
lldb::addr_t curr_sect_file_base_addr;
bool is_oso_for_debug_map;
bool prev_in_final_executable;
DWARFDebugLine::Row prev_row;
SectionSP prev_section_sp;
SectionSP curr_section_sp;
llvm::OwningPtr<LineSequence> curr_sequence_ap;
std::auto_ptr<LineSequence> sequence_ap;
};
//----------------------------------------------------------------------
@ -1000,7 +1004,6 @@ struct ParseDWARFLineTableCallbackInfo
static void
ParseDWARFLineTableCallback(dw_offset_t offset, const DWARFDebugLine::State& state, void* userData)
{
LineTable* line_table = ((ParseDWARFLineTableCallbackInfo*)userData)->line_table;
if (state.row == DWARFDebugLine::State::StartParsingLineTable)
{
// Just started parsing the line table
@ -1012,147 +1015,17 @@ ParseDWARFLineTableCallback(dw_offset_t offset, const DWARFDebugLine::State& sta
else
{
ParseDWARFLineTableCallbackInfo* info = (ParseDWARFLineTableCallbackInfo*)userData;
// We have a new row, lets append it
if (info->curr_section_sp.get() == NULL || info->curr_section_sp->ContainsFileAddress(state.address) == false)
{
info->prev_section_sp = info->curr_section_sp;
info->prev_sect_file_base_addr = info->curr_sect_file_base_addr;
// If this is an end sequence entry, then we subtract one from the
// address to make sure we get an address that is not the end of
// a section.
if (state.end_sequence && state.address != 0)
info->curr_section_sp = info->section_list->FindSectionContainingFileAddress (state.address - 1);
else
info->curr_section_sp = info->section_list->FindSectionContainingFileAddress (state.address);
if (info->curr_section_sp.get())
info->curr_sect_file_base_addr = info->curr_section_sp->GetFileAddress ();
else
info->curr_sect_file_base_addr = 0;
}
if (info->curr_section_sp.get())
{
lldb::addr_t curr_line_section_offset = state.address - info->curr_sect_file_base_addr;
// Check for the fancy section magic to determine if we
if (info->is_oso_for_debug_map)
{
// When this is a debug map object file that contains DWARF
// (referenced from an N_OSO debug map nlist entry) we will have
// a file address in the file range for our section from the
// original .o file, and a load address in the executable that
// contains the debug map.
//
// If the sections for the file range and load range are
// different, we have a remapped section for the function and
// this address is resolved. If they are the same, then the
// function for this address didn't make it into the final
// executable.
bool curr_in_final_executable = (bool) info->curr_section_sp->GetLinkedSection ();
// If we are doing DWARF with debug map, then we need to carefully
// add each line table entry as there may be gaps as functions
// get moved around or removed.
if (!info->prev_row.end_sequence && info->prev_section_sp.get())
{
if (info->prev_in_final_executable)
{
bool terminate_previous_entry = false;
if (!curr_in_final_executable)
{
// Check for the case where the previous line entry
// in a function made it into the final executable,
// yet the current line entry falls in a function
// that didn't. The line table used to be contiguous
// through this address range but now it isn't. We
// need to terminate the previous line entry so
// that we can reconstruct the line range correctly
// for it and to keep the line table correct.
terminate_previous_entry = true;
}
else if (info->curr_section_sp.get() != info->prev_section_sp.get())
{
// Check for cases where the line entries used to be
// contiguous address ranges, but now they aren't.
// This can happen when order files specify the
// ordering of the functions.
lldb::addr_t prev_line_section_offset = info->prev_row.address - info->prev_sect_file_base_addr;
Section *curr_sect = info->curr_section_sp.get();
Section *prev_sect = info->prev_section_sp.get();
assert (curr_sect->GetLinkedSection());
assert (prev_sect->GetLinkedSection());
lldb::addr_t object_file_addr_delta = state.address - info->prev_row.address;
lldb::addr_t curr_linked_file_addr = curr_sect->GetLinkedFileAddress() + curr_line_section_offset;
lldb::addr_t prev_linked_file_addr = prev_sect->GetLinkedFileAddress() + prev_line_section_offset;
lldb::addr_t linked_file_addr_delta = curr_linked_file_addr - prev_linked_file_addr;
if (object_file_addr_delta != linked_file_addr_delta)
terminate_previous_entry = true;
}
if (terminate_previous_entry)
{
line_table->InsertLineEntry (info->prev_section_sp,
state.address - info->prev_sect_file_base_addr,
info->prev_row.line,
info->prev_row.column,
info->prev_row.file,
false, // is_stmt
false, // basic_block
false, // state.prologue_end
false, // state.epilogue_begin
true); // end_sequence);
}
}
}
if (curr_in_final_executable)
{
line_table->InsertLineEntry (info->curr_section_sp,
curr_line_section_offset,
state.line,
state.column,
state.file,
state.is_stmt,
state.basic_block,
state.prologue_end,
state.epilogue_begin,
state.end_sequence);
info->prev_section_sp = info->curr_section_sp;
}
else
{
// If the current address didn't make it into the final
// executable, the current section will be the __text
// segment in the .o file, so we need to clear this so
// we can catch the next function that did make it into
// the final executable.
info->prev_section_sp.reset();
info->curr_section_sp.reset();
}
info->prev_in_final_executable = curr_in_final_executable;
}
else
{
// We are not in an object file that contains DWARF for an
// N_OSO, this is just a normal DWARF file. The DWARF spec
// guarantees that the addresses will be in increasing order
// for a sequence, but the line table for a single compile unit
// may contain multiple sequences so we append entries to the
// current sequence until we find its end, then we merge the
// sequence into the main line table collection.
LineTable* line_table = info->line_table;
// If this is our first time here, we need to create a
// sequence container.
if (!info->curr_sequence_ap)
if (!info->sequence_ap.get())
{
info->curr_sequence_ap.reset(line_table->CreateLineSequenceContainer());
assert(info->curr_sequence_ap);
info->sequence_ap.reset(line_table->CreateLineSequenceContainer());
assert(info->sequence_ap.get());
}
line_table->AppendLineEntryToSequence(info->curr_sequence_ap.get(),
info->curr_section_sp,
curr_line_section_offset,
line_table->AppendLineEntryToSequence (info->sequence_ap.get(),
state.address,
state.line,
state.column,
state.file,
@ -1164,17 +1037,13 @@ ParseDWARFLineTableCallback(dw_offset_t offset, const DWARFDebugLine::State& sta
if (state.end_sequence)
{
// First, put the current sequence into the line table.
line_table->InsertSequence(info->curr_sequence_ap.get());
line_table->InsertSequence(info->sequence_ap.get());
// Then, empty it to prepare for the next sequence.
info->curr_sequence_ap->Clear();
info->sequence_ap->Clear();
}
}
}
info->prev_row = state;
}
}
bool
SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc)
{
@ -1194,26 +1063,27 @@ SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc)
std::auto_ptr<LineTable> line_table_ap(new LineTable(sc.comp_unit));
if (line_table_ap.get())
{
ParseDWARFLineTableCallbackInfo info = {
line_table_ap.get(),
m_obj_file->GetSectionList(),
0,
0,
GetDebugMapSymfile () != NULL,
false,
DWARFDebugLine::Row(),
SectionSP(),
SectionSP(),
llvm::OwningPtr<LineSequence>()
};
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;
}
@ -2672,19 +2542,19 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_
LineTable *line_table = sc.comp_unit->GetLineTable();
if (line_table != NULL)
{
if (so_addr.IsLinkedAddress())
// 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))
{
Address linked_addr (so_addr);
linked_addr.ResolveLinkedAddress();
if (line_table->FindLineEntryByAddress (linked_addr, sc.line_entry))
if (line_table->FindLineEntryByAddress (exe_so_addr, sc.line_entry))
{
resolved |= eSymbolContextLineEntry;
}
}
else if (line_table->FindLineEntryByAddress (so_addr, sc.line_entry))
{
resolved |= eSymbolContextLineEntry;
}
}
}
@ -6976,14 +6846,13 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
if (info == NULL)
return 0;
uint32_t cu_idx = UINT32_MAX;
DWARFCompileUnit* dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID(), &cu_idx).get();
if (sc.function)
{
DWARFCompileUnit* dwarf_cu = info->GetCompileUnitContainingDIE(sc.function->GetID()).get();
if (dwarf_cu == NULL)
return 0;
if (sc.function)
{
const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(sc.function->GetID());
dw_addr_t func_lo_pc = function_die->GetAttributeValueAsUnsigned (this, dwarf_cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
@ -6998,6 +6867,11 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
}
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));
@ -7232,10 +7106,10 @@ SymbolFileDWARF::ParseVariableDIE
{
bool op_error = false;
// Check if the location has a DW_OP_addr with any address value...
addr_t location_has_op_addr = false;
lldb::addr_t location_DW_OP_addr = LLDB_INVALID_ADDRESS;
if (!location_is_const_value_data)
{
location_has_op_addr = location.LocationContains_DW_OP_addr (LLDB_INVALID_ADDRESS, op_error);
location_DW_OP_addr = location.GetLocation_DW_OP_addr (0, op_error);
if (op_error)
{
StreamString strm;
@ -7244,13 +7118,17 @@ SymbolFileDWARF::ParseVariableDIE
}
}
if (location_has_op_addr)
if (location_DW_OP_addr != LLDB_INVALID_ADDRESS)
{
if (is_external)
{
scope = eValueTypeVariableGlobal;
else
scope = eValueTypeVariableStatic;
if (GetDebugMapSymfile ())
SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile ();
if (debug_map_symfile)
{
// When leaving the DWARF in the .o files on darwin,
// when we have a global variable that wasn't initialized,
@ -7270,41 +7148,33 @@ SymbolFileDWARF::ParseVariableDIE
// 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.
if (location.LocationContains_DW_OP_addr (0, op_error))
bool linked_oso_file_addr = false;
if (is_external && location_DW_OP_addr == 0)
{
// we have a possible uninitialized extern global
Symtab *symtab = m_obj_file->GetSymtab();
if (symtab)
{
ConstString const_name(mangled ? mangled : name);
Symbol *o_symbol = symtab->FindFirstSymbolWithNameAndType (const_name,
eSymbolTypeAny,
Symtab::eDebugNo,
Symtab::eVisibilityExtern);
if (o_symbol)
{
ObjectFile *debug_map_objfile = m_debug_map_symfile->GetObjectFile();
ObjectFile *debug_map_objfile = debug_map_symfile->GetObjectFile();
if (debug_map_objfile)
{
Symtab *debug_map_symtab = debug_map_objfile->GetSymtab();
Symbol *defined_symbol = debug_map_symtab->FindFirstSymbolWithNameAndType (const_name,
if (debug_map_symtab)
{
Symbol *exe_symbol = debug_map_symtab->FindFirstSymbolWithNameAndType (const_name,
eSymbolTypeData,
Symtab::eDebugYes,
Symtab::eVisibilityExtern);
if (defined_symbol)
if (exe_symbol)
{
if (defined_symbol->ValueIsAddress())
if (exe_symbol->ValueIsAddress())
{
const addr_t defined_addr = defined_symbol->GetAddress().GetFileAddress();
if (defined_addr != LLDB_INVALID_ADDRESS)
const addr_t exe_file_addr = exe_symbol->GetAddress().GetFileAddress();
if (exe_file_addr != LLDB_INVALID_ADDRESS)
{
if (location.Update_DW_OP_addr (defined_addr))
if (location.Update_DW_OP_addr (exe_file_addr))
{
symbol_context_scope = defined_symbol;
}
}
linked_oso_file_addr = true;
symbol_context_scope = exe_symbol;
}
}
}
@ -7312,10 +7182,23 @@ SymbolFileDWARF::ParseVariableDIE
}
}
}
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
{
scope = eValueTypeVariableStatic;
// Variable didn't make it into the final executable
return var_sp;
}
}
}
}
else

View File

@ -541,6 +541,9 @@ protected:
const DWARFDebugInfoEntry *dst_class_die,
llvm::SmallVectorImpl <const DWARFDebugInfoEntry *> &failures);
bool
FixupAddress (lldb_private::Address &addr);
lldb::ModuleWP m_debug_map_module_wp;
SymbolFileDWARFDebugMap * m_debug_map_symfile;
clang::TranslationUnitDecl * m_clang_tu_decl;

View File

@ -14,6 +14,8 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/Section.h"
//#define DEBUG_OSO_DMAP // DO NOT CHECKIN WITH THIS NOT COMMENTED OUT
#if defined(DEBUG_OSO_DMAP)
#include "lldb/Core/StreamFile.h"
#endif
@ -21,6 +23,7 @@
#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"
@ -35,76 +38,48 @@ using namespace lldb_private;
// (so we can fixup the object file sections) and also for "Module::GetSymbolVendor()"
// (so we can fixup the symbol file id.
class DebugMapModule : public Module
{
public:
DebugMapModule (const ModuleSP &exe_module_sp,
uint32_t cu_idx,
const FileSpec& file_spec,
const ArchSpec& arch,
const ConstString *object_name,
off_t object_offset) :
Module (file_spec, arch, object_name, object_offset),
m_exe_module_wp (exe_module_sp),
m_cu_idx (cu_idx)
const SymbolFileDWARFDebugMap::FileRangeMap &
SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMap *exe_symfile)
{
if (file_range_map_valid)
return file_range_map;
file_range_map_valid = true;
Module *oso_module = exe_symfile->GetModuleByCompUnitInfo (this);
ObjectFile *oso_objfile = oso_module->GetObjectFile();
LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP));
if (log)
log->Printf("%p: DebugMapModule::DebugMapModule (exe_module=%p, cu_idx=%u, oso_path='%s/%s', object_name='%s')",
{
ConstString object_name (oso_module->GetObjectName());
log->Printf("%p: SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap ('%s/%s%s%s%s')",
this,
exe_module_sp.get(),
cu_idx,
file_spec.GetDirectory().GetCString(),
file_spec.GetFilename().GetCString(),
object_name ? object_name->GetCString() : "");
oso_module->GetFileSpec().GetDirectory().GetCString(),
oso_module->GetFileSpec().GetFilename().GetCString(),
object_name ? "(" : "",
object_name ? object_name.GetCString() : "",
object_name ? ")" : "");
}
virtual
~DebugMapModule ()
{
LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP));
if (log)
log->Printf("%p: DebugMapModule::~DebugMapModule ()", this);
}
virtual ObjectFile *
GetObjectFile ()
{
Mutex::Locker locker (m_mutex);
if (m_did_load_objfile == false)
{
ModuleSP exe_module_sp (m_exe_module_wp.lock());
if (exe_module_sp)
{
ObjectFile *exe_objfile = exe_module_sp->GetObjectFile();
ObjectFile *oso_objfile = Module::GetObjectFile();
SymbolVendor *exe_sym_vendor = exe_module_sp->GetSymbolVendor();
if (exe_objfile && oso_objfile && exe_sym_vendor)
{
SymbolFileDWARFDebugMap *exe_symfile = (SymbolFileDWARFDebugMap *)exe_sym_vendor->GetSymbolFile();
if (exe_symfile)
{
std::vector<SymbolFileDWARFDebugMap::CompileUnitInfo *> cu_infos;
if (exe_symfile->GetCompUnitInfosForModule(this, cu_infos))
if (exe_symfile->GetCompUnitInfosForModule(oso_module, cu_infos))
{
for (auto comp_unit_info : cu_infos)
{
// Set the ID of the symbol file DWARF to the index of the OSO
// shifted left by 32 bits to provide a unique prefix for any
// UserID's that get created in the symbol file.
//comp_unit_info->exe_sections_sp.reset(new SectionList);
Symtab *exe_symtab = exe_objfile->GetSymtab();
Symtab *exe_symtab = exe_symfile->GetObjectFile()->GetSymtab();
ModuleSP oso_module_sp (oso_objfile->GetModule());
Symtab *oso_symtab = oso_objfile->GetSymtab();
//#define DEBUG_OSO_DMAP // Do not check in with this defined...
#if defined(DEBUG_OSO_DMAP)
StreamFile s(stdout);
StreamFile s(stdout, false);
s << "OSO symtab:\n";
oso_symtab->Dump(&s, NULL);
oso_symtab->Dump(&s, NULL, eSortOrderNone);
s << "OSO sections before:\n";
oso_objfile->GetSectionList()->Dump(&s, NULL, true);
oso_objfile->GetSectionList()->Dump(&s, NULL, true, UINT32_MAX);
#endif
///const uint32_t fun_resolve_flags = SymbolContext::Module | eSymbolContextCompUnit | eSymbolContextFunction;
@ -115,7 +90,6 @@ public:
assert (comp_unit_info->first_symbol_index != UINT32_MAX);
// End index is one past the last valid symbol index
const uint32_t oso_end_idx = comp_unit_info->last_symbol_index + 1;
uint32_t sect_id = 0x10000;
for (uint32_t idx = comp_unit_info->first_symbol_index + 2; // Skip the N_SO and N_OSO
idx < oso_end_idx;
++idx)
@ -143,35 +117,18 @@ public:
// correctly to the new addresses in the main executable.
// First we find the original symbol in the .o file's symbol table
Symbol *oso_fun_symbol = oso_symtab->FindFirstSymbolWithNameAndType(exe_symbol->GetMangled().GetName(Mangled::ePreferMangled), eSymbolTypeCode, Symtab::eDebugNo, Symtab::eVisibilityAny);
Symbol *oso_fun_symbol = oso_symtab->FindFirstSymbolWithNameAndType (exe_symbol->GetMangled().GetName(Mangled::ePreferMangled),
eSymbolTypeCode,
Symtab::eDebugNo,
Symtab::eVisibilityAny);
if (oso_fun_symbol)
{
// If we found the symbol, then we
SectionSP exe_fun_section (exe_symbol->GetAddress().GetSection());
SectionSP oso_fun_section (oso_fun_symbol->GetAddress().GetSection());
if (oso_fun_section)
{
// Now we create a section that we will add as a child of the
// section in which the .o symbol (the N_FUN) exists.
// Add the inverse OSO file address to debug map entry mapping
exe_symfile->AddOSOFileRange (this,
exe_symbol->GetAddress().GetFileAddress(),
oso_fun_symbol->GetAddress().GetFileAddress(),
std::min<addr_t>(exe_symbol->GetByteSize(), oso_fun_symbol->GetByteSize()));
// We use the exe_symbol size because the one in the .o file
// will just be a symbol with no size, and the exe_symbol
// size will reflect any size changes (ppc has been known to
// shrink function sizes when it gets rid of jump islands that
// aren't needed anymore).
SectionSP oso_fun_section_sp (new Section (oso_fun_symbol->GetAddress().GetSection(),
oso_module_sp, // Module (the .o file)
sect_id++, // Section ID starts at 0x10000 and increments so the section IDs don't overlap with the standard mach IDs
exe_symbol->GetMangled().GetName(Mangled::ePreferMangled), // Name the section the same as the symbol for which is was generated!
eSectionTypeDebug,
oso_fun_symbol->GetAddress().GetOffset(), // File VM address offset in the current section
exe_symbol->GetByteSize(), // File size (we need the size from the executable)
0, 0, 0));
oso_fun_section_sp->SetLinkedLocation (exe_fun_section,
exe_symbol->GetAddress().GetFileAddress() - exe_fun_section->GetFileAddress());
oso_fun_section->GetChildren().AddSection(oso_fun_section_sp);
}
}
}
break;
@ -192,50 +149,60 @@ public:
// sizes from the DWARF info as we are parsing.
// Next we find the non-stab entry that corresponds to the N_GSYM in the .o file
Symbol *oso_gsym_symbol = oso_symtab->FindFirstSymbolWithNameAndType (exe_symbol->GetMangled().GetName(),
Symbol *oso_gsym_symbol = oso_symtab->FindFirstSymbolWithNameAndType (exe_symbol->GetMangled().GetName(Mangled::ePreferMangled),
eSymbolTypeData,
Symtab::eDebugNo,
Symtab::eVisibilityAny);
if (exe_symbol && oso_gsym_symbol && exe_symbol->ValueIsAddress() && oso_gsym_symbol->ValueIsAddress())
if (exe_symbol && oso_gsym_symbol &&
exe_symbol->ValueIsAddress() &&
oso_gsym_symbol->ValueIsAddress())
{
// If we found the symbol, then we
SectionSP exe_gsym_section (exe_symbol->GetAddress().GetSection());
SectionSP oso_gsym_section (oso_gsym_symbol->GetAddress().GetSection());
if (oso_gsym_section)
{
SectionSP oso_gsym_section_sp (new Section (oso_gsym_symbol->GetAddress().GetSection(),
oso_module_sp, // Module (the .o file)
sect_id++, // Section ID starts at 0x10000 and increments so the section IDs don't overlap with the standard mach IDs
exe_symbol->GetMangled().GetName(Mangled::ePreferMangled), // Name the section the same as the symbol for which is was generated!
eSectionTypeDebug,
oso_gsym_symbol->GetAddress().GetOffset(), // File VM address offset in the current section
1, // We don't know the size of the global, just do the main address for now.
0, 0, 0));
oso_gsym_section_sp->SetLinkedLocation (exe_gsym_section,
exe_symbol->GetAddress().GetFileAddress() - exe_gsym_section->GetFileAddress());
oso_gsym_section->GetChildren().AddSection(oso_gsym_section_sp);
}
// Add the inverse OSO file address to debug map entry mapping
exe_symfile->AddOSOFileRange (this,
exe_symbol->GetAddress().GetFileAddress(),
oso_gsym_symbol->GetAddress().GetFileAddress(),
std::min<addr_t>(exe_symbol->GetByteSize(), oso_gsym_symbol->GetByteSize()));
}
}
break;
}
}
}
oso_objfile->GetSectionList()->Finalize(); // Now that we're done adding sections, finalize to build fast-lookup caches
exe_symfile->FinalizeOSOFileRanges (this);
#if defined(DEBUG_OSO_DMAP)
s << "OSO sections after:\n";
oso_objfile->GetSectionList()->Dump(&s, NULL, true);
oso_objfile->GetSectionList()->Dump(&s, NULL, true, UINT32_MAX);
#endif
// We don't need the symbols anymore for the .o files
oso_objfile->ClearSymtab();
}
}
return file_range_map;
}
class DebugMapModule : public Module
{
public:
DebugMapModule (const ModuleSP &exe_module_sp,
uint32_t cu_idx,
const FileSpec& file_spec,
const ArchSpec& arch,
const ConstString *object_name,
off_t object_offset) :
Module (file_spec, arch, object_name, object_offset),
m_exe_module_wp (exe_module_sp),
m_cu_idx (cu_idx)
{
}
virtual
~DebugMapModule ()
{
}
}
return m_objfile_sp.get();
}
virtual SymbolVendor*
GetSymbolVendor(bool can_create = true, lldb_private::Stream *feedback_strm = NULL)
@ -356,8 +323,6 @@ SymbolFileDWARFDebugMap::InitializeObject()
GetClangASTContext().SetExternalSource (ast_source_ap);
}
void
SymbolFileDWARFDebugMap::InitOSO()
{
@ -376,10 +341,6 @@ SymbolFileDWARFDebugMap::InitOSO()
LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP));
std::vector<uint32_t> oso_indexes;
#if defined(DEBUG_OSO_DMAP)
// StreamFile s(stdout);
// symtab->Dump(&s, NULL, eSortOrderNone);
#endif
// When a mach-o symbol is encoded, the n_type field is encoded in bits
// 23:16, and the n_desc field is encoded in bits 15:0.
//
@ -399,7 +360,31 @@ SymbolFileDWARFDebugMap::InitOSO()
symtab->SortSymbolIndexesByValue(m_func_indexes, true);
symtab->SortSymbolIndexesByValue(m_glob_indexes, true);
for (uint32_t sym_idx : m_func_indexes)
{
const Symbol *symbol = symtab->SymbolAtIndex(sym_idx);
lldb::addr_t file_addr = symbol->GetAddress().GetFileAddress();
lldb::addr_t byte_size = symbol->GetByteSize();
DebugMap::Entry debug_map_entry(file_addr, byte_size, OSOEntry(sym_idx, LLDB_INVALID_ADDRESS));
m_debug_map.Append(debug_map_entry);
}
for (uint32_t sym_idx : m_glob_indexes)
{
const Symbol *symbol = symtab->SymbolAtIndex(sym_idx);
lldb::addr_t file_addr = symbol->GetAddress().GetFileAddress();
lldb::addr_t byte_size = symbol->GetByteSize();
DebugMap::Entry debug_map_entry(file_addr, byte_size, OSOEntry(sym_idx, LLDB_INVALID_ADDRESS));
m_debug_map.Append(debug_map_entry);
}
m_debug_map.Sort();
#if defined(DEBUG_OSO_DMAP)
StreamFile s(stdout, false);
symtab->Dump(&s, NULL, m_func_indexes);
symtab->Dump(&s, NULL, m_glob_indexes);
#endif
m_compile_unit_infos.resize(oso_index_count);
// s.Printf("%s N_OSO symbols:\n", __PRETTY_FUNCTION__);
// symtab->Dump(&s, oso_indexes);
@ -642,35 +627,21 @@ SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx)
{
FileSpec so_file_spec;
if (GetFileSpecForSO (cu_idx, so_file_spec))
{
Module *oso_module = GetModuleByOSOIndex (cu_idx);
if (oso_module)
{
// User zero as the ID to match the compile unit at offset
// zero in each .o file since each .o file can only have
// one compile unit for now.
lldb::user_id_t cu_id = 0;
m_compile_unit_infos[cu_idx].compile_unit_sp.reset (new CompileUnit (oso_module->shared_from_this(),
m_compile_unit_infos[cu_idx].compile_unit_sp.reset(new CompileUnit (m_obj_file->GetModule(),
NULL,
so_file_spec,
cu_id,
eLanguageTypeUnknown));
}
if (!m_compile_unit_infos[cu_idx].compile_unit_sp)
{
m_compile_unit_infos[cu_idx].compile_unit_sp.reset(new CompileUnit (m_obj_file->GetModule(),
NULL,
so_file_spec,
cu_idx,
eLanguageTypeUnknown));
}
if (m_compile_unit_infos[cu_idx].compile_unit_sp)
{
// Let our symbol vendor know about this compile unit
m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex (cu_idx,
m_compile_unit_infos[cu_idx].compile_unit_sp);
m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex (cu_idx, m_compile_unit_infos[cu_idx].compile_unit_sp);
}
}
}
@ -779,7 +750,7 @@ SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid)
const uint64_t oso_idx = GetOSOIndexFromUserID (type_uid);
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);
if (oso_dwarf)
oso_dwarf->ResolveTypeUID (type_uid);
return oso_dwarf->ResolveTypeUID (type_uid);
return NULL;
}
@ -798,7 +769,12 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext (const Address& exe_so_addr, uint3
if (symtab)
{
const addr_t exe_file_addr = exe_so_addr.GetFileAddress();
sc.symbol = symtab->FindSymbolContainingFileAddress (exe_file_addr, &m_func_indexes[0], m_func_indexes.size());
const DebugMap::Entry *debug_map_entry = m_debug_map.FindEntryThatContains (exe_file_addr);
if (debug_map_entry)
{
sc.symbol = symtab->SymbolAtIndex(debug_map_entry->data.GetExeSymbolIndex());
if (sc.symbol != NULL)
{
@ -808,20 +784,15 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext (const Address& exe_so_addr, uint3
CompileUnitInfo* comp_unit_info = GetCompileUnitInfoForSymbolWithID (sc.symbol->GetID(), &oso_idx);
if (comp_unit_info)
{
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);
ObjectFile *oso_objfile = GetObjectFileByOSOIndex (oso_idx);
if (oso_dwarf && oso_objfile)
Module *oso_module = GetModuleByCompUnitInfo (comp_unit_info);
if (oso_module)
{
SectionList *oso_section_list = oso_objfile->GetSectionList();
SectionSP oso_symbol_section_sp (oso_section_list->FindSectionContainingLinkedFileAddress (exe_file_addr, UINT32_MAX));
if (oso_symbol_section_sp)
lldb::addr_t oso_file_addr = exe_file_addr - debug_map_entry->GetRangeBase() + debug_map_entry->data.GetOSOFileAddress();
Address oso_so_addr;
if (oso_module->ResolveFileAddress(oso_file_addr, oso_so_addr))
{
const addr_t linked_file_addr = oso_symbol_section_sp->GetLinkedFileAddress();
Address oso_so_addr (oso_symbol_section_sp, exe_file_addr - linked_file_addr);
if (oso_so_addr.IsSectionOffset())
resolved_flags |= oso_dwarf->ResolveSymbolContext (oso_so_addr, resolve_scope, sc);
resolved_flags |= oso_module->GetSymbolVendor()->ResolveSymbolContext (oso_so_addr, resolve_scope, sc);
}
}
}
}
@ -1307,6 +1278,24 @@ SymbolFileDWARFDebugMap::GetCompileUnit (SymbolFileDWARF *oso_dwarf)
return lldb::CompUnitSP();
}
SymbolFileDWARFDebugMap::CompileUnitInfo *
SymbolFileDWARFDebugMap::GetCompileUnitInfo (SymbolFileDWARF *oso_dwarf)
{
if (oso_dwarf)
{
const uint32_t cu_count = GetNumCompileUnits();
for (uint32_t cu_idx=0; cu_idx<cu_count; ++cu_idx)
{
SymbolFileDWARF *oso_symfile = GetSymbolFileByCompUnitInfo (&m_compile_unit_infos[cu_idx]);
if (oso_symfile == oso_dwarf)
{
return &m_compile_unit_infos[cu_idx];
}
}
}
return NULL;
}
void
SymbolFileDWARFDebugMap::SetCompileUnit (SymbolFileDWARF *oso_dwarf, const CompUnitSP &cu_sp)
@ -1415,4 +1404,99 @@ SymbolFileDWARFDebugMap::GetClangDeclContextForTypeUID (const lldb_private::Symb
return NULL;
}
bool
SymbolFileDWARFDebugMap::AddOSOFileRange (CompileUnitInfo *cu_info,
lldb::addr_t exe_file_addr,
lldb::addr_t oso_file_addr,
lldb::addr_t oso_byte_size)
{
assert (cu_info);// REMOVE THIS PRIOR TO CHECKIN
const uint32_t debug_map_idx = m_debug_map.FindEntryIndexThatContains(exe_file_addr);
if (debug_map_idx != UINT32_MAX)
{
DebugMap::Entry *debug_map_entry = m_debug_map.FindEntryThatContains(exe_file_addr);
assert (debug_map_entry);// REMOVE THIS PRIOR TO CHECKIN
debug_map_entry->data.SetOSOFileAddress(oso_file_addr);
cu_info->file_range_map.Append(FileRangeMap::Entry(oso_file_addr, oso_byte_size, exe_file_addr));
return true;
}
return false;
}
void
SymbolFileDWARFDebugMap::FinalizeOSOFileRanges (CompileUnitInfo *cu_info)
{
cu_info->file_range_map.Sort();
#if defined(DEBUG_OSO_DMAP)
const FileRangeMap &oso_file_range_map = cu_info->GetFileRangeMap(this);
const size_t n = oso_file_range_map.GetSize();
printf ("SymbolFileDWARFDebugMap::FinalizeOSOFileRanges (cu_info = %p)\n", cu_info);
for (size_t i=0; i<n; ++i)
{
const FileRangeMap::Entry &entry = oso_file_range_map.GetEntryRef(i);
printf ("oso [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ") ==> exe [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n",
entry.GetRangeBase(), entry.GetRangeEnd(),
entry.data, entry.data + entry.GetByteSize());
}
#endif
}
lldb::addr_t
SymbolFileDWARFDebugMap::LinkOSOFileAddress (SymbolFileDWARF *oso_symfile, lldb::addr_t oso_file_addr)
{
CompileUnitInfo *cu_info = GetCompileUnitInfo (oso_symfile);
if (cu_info)
{
const FileRangeMap::Entry *oso_range_entry = cu_info->GetFileRangeMap(this).FindEntryThatContains(oso_file_addr);
if (oso_range_entry)
{
const DebugMap::Entry *debug_map_entry = m_debug_map.FindEntryThatContains(oso_range_entry->data);
if (debug_map_entry)
{
const lldb::addr_t offset = oso_file_addr - oso_range_entry->GetRangeBase();
const lldb::addr_t exe_file_addr = debug_map_entry->GetRangeBase() + offset;
return exe_file_addr;
}
}
}
return LLDB_INVALID_ADDRESS;
}
bool
SymbolFileDWARFDebugMap::LinkOSOAddress (Address &addr)
{
// Make sure this address hasn't been fixed already
Module *exe_module = GetObjectFile()->GetModule().get();
Module *addr_module = addr.GetModule().get();
if (addr_module == exe_module)
return true; // Address is already in terms of the main executable module
CompileUnitInfo *cu_info = GetCompileUnitInfo ((SymbolFileDWARF *)addr_module->GetSymbolVendor()->GetSymbolFile());
if (cu_info)
{
const lldb::addr_t oso_file_addr = addr.GetFileAddress();
const FileRangeMap::Entry *oso_range_entry = cu_info->GetFileRangeMap(this).FindEntryThatContains(oso_file_addr);
if (oso_range_entry)
{
const DebugMap::Entry *debug_map_entry = m_debug_map.FindEntryThatContains(oso_range_entry->data);
if (debug_map_entry)
{
const lldb::addr_t offset = oso_file_addr - oso_range_entry->GetRangeBase();
const lldb::addr_t exe_file_addr = debug_map_entry->GetRangeBase() + offset;
return exe_module->ResolveFileAddress(exe_file_addr, addr);
}
}
}
return true;
}
LineTable *
SymbolFileDWARFDebugMap::LinkOSOLineTable (SymbolFileDWARF *oso_dwarf, LineTable *line_table)
{
CompileUnitInfo *cu_info = GetCompileUnitInfo (oso_dwarf);
if (cu_info)
return line_table->LinkLineTable(cu_info->GetFileRangeMap(this));
return NULL;
}

View File

@ -16,6 +16,7 @@
#include "clang/AST/CharUnits.h"
#include "lldb/Core/RangeMap.h"
#include "lldb/Symbol/SymbolFile.h"
#include "UniqueDWARFASTType.h"
@ -143,6 +144,8 @@ protected:
typedef STD_SHARED_PTR(OSOInfo) OSOInfoSP;
typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, lldb::addr_t> FileRangeMap;
//------------------------------------------------------------------
// Class specific types
//------------------------------------------------------------------
@ -156,6 +159,9 @@ protected:
uint32_t last_symbol_index;
uint32_t first_symbol_id;
uint32_t last_symbol_id;
FileRangeMap file_range_map;
bool file_range_map_valid;
CompileUnitInfo() :
so_file (),
@ -165,9 +171,14 @@ protected:
first_symbol_index (UINT32_MAX),
last_symbol_index (UINT32_MAX),
first_symbol_id (UINT32_MAX),
last_symbol_id (UINT32_MAX)
last_symbol_id (UINT32_MAX),
file_range_map (),
file_range_map_valid (false)
{
}
const FileRangeMap &
GetFileRangeMap(SymbolFileDWARFDebugMap *exe_symfile);
};
//------------------------------------------------------------------
@ -241,6 +252,9 @@ protected:
lldb::CompUnitSP
GetCompileUnit (SymbolFileDWARF *oso_dwarf);
CompileUnitInfo *
GetCompileUnitInfo (SymbolFileDWARF *oso_dwarf);
lldb::TypeSP
FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx);
@ -258,6 +272,58 @@ protected:
{
return m_unique_ast_type_map;
}
//------------------------------------------------------------------
// OSOEntry
//------------------------------------------------------------------
class OSOEntry
{
public:
OSOEntry () :
m_exe_sym_idx (UINT32_MAX),
m_oso_file_addr (LLDB_INVALID_ADDRESS)
{
}
OSOEntry (uint32_t exe_sym_idx,
lldb::addr_t oso_file_addr) :
m_exe_sym_idx (exe_sym_idx),
m_oso_file_addr (oso_file_addr)
{
}
uint32_t
GetExeSymbolIndex () const
{
return m_exe_sym_idx;
}
bool
operator < (const OSOEntry &rhs) const
{
return m_exe_sym_idx < rhs.m_exe_sym_idx;
}
lldb::addr_t
GetOSOFileAddress () const
{
return m_oso_file_addr;
}
void
SetOSOFileAddress (lldb::addr_t oso_file_addr)
{
m_oso_file_addr = oso_file_addr;
}
protected:
uint32_t m_exe_sym_idx;
lldb::addr_t m_oso_file_addr;
};
typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, OSOEntry> DebugMap;
//------------------------------------------------------------------
// Member Variables
//------------------------------------------------------------------
@ -268,6 +334,77 @@ protected:
std::map<lldb_private::ConstString, OSOInfoSP> m_oso_map;
UniqueDWARFASTTypeMap m_unique_ast_type_map;
lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type;
DebugMap m_debug_map;
//------------------------------------------------------------------
// When an object file from the debug map gets parsed in
// SymbolFileDWARF, it needs to tell the debug map about the object
// files addresses by calling this function once for each N_FUN,
// N_GSYM and N_STSYM and after all entries in the debug map have
// been matched up, FinalizeOSOFileRanges() should be called.
//------------------------------------------------------------------
bool
AddOSOFileRange (CompileUnitInfo *cu_info,
lldb::addr_t exe_file_addr,
lldb::addr_t oso_file_addr,
lldb::addr_t oso_byte_size);
//------------------------------------------------------------------
// Called after calling AddOSOFileRange() for each object file debug
// map entry to finalize the info for the unlinked compile unit.
//------------------------------------------------------------------
void
FinalizeOSOFileRanges (CompileUnitInfo *cu_info);
//------------------------------------------------------------------
/// Convert \a addr from a .o file address, to an executable address.
///
/// @param[in] addr
/// A section offset address from a .o file
///
/// @return
/// Returns true if \a addr was converted to be an executable
/// section/offset address, false otherwise.
//------------------------------------------------------------------
bool
LinkOSOAddress (lldb_private::Address &addr);
//------------------------------------------------------------------
/// Convert a .o file "file address" to an executable "file address".
///
/// @param[in] oso_symfile
/// The DWARF symbol file that contains \a oso_file_addr
///
/// @param[in] oso_file_addr
/// A .o file "file address" to convert.
///
/// @return
/// LLDB_INVALID_ADDRESS if \a oso_file_addr is not in the
/// linked executable, otherwise a valid "file address" from the
/// linked executable that contains the debug map.
//------------------------------------------------------------------
lldb::addr_t
LinkOSOFileAddress (SymbolFileDWARF *oso_symfile, lldb::addr_t oso_file_addr);
//------------------------------------------------------------------
/// Given a line table full of lines with "file adresses" that are
/// for a .o file represented by \a oso_symfile, link a new line table
/// and return it.
///
/// @param[in] oso_symfile
/// The DWARF symbol file that produced the \a line_table
///
/// @param[in] addr
/// A section offset address from a .o file
///
/// @return
/// Returns a valid line table full of linked addresses, or NULL
/// if none of the line table adresses exist in the main
/// executable.
//------------------------------------------------------------------
lldb_private::LineTable *
LinkOSOLineTable (SymbolFileDWARF *oso_symfile,
lldb_private::LineTable *line_table);
};
#endif // #ifndef SymbolFileDWARF_SymbolFileDWARFDebugMap_h_

View File

@ -392,13 +392,7 @@ Function::CalculateSymbolContextModule ()
{
SectionSP section_sp (m_range.GetBaseAddress().GetSection());
if (section_sp)
{
SectionSP linked_section_sp (section_sp->GetLinkedSection());
if (linked_section_sp)
return linked_section_sp->GetModule();
else
return section_sp->GetModule();
}
return this->GetCompileUnit()->GetModule();
}

View File

@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/Core/Address.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/CompileUnit.h"
@ -22,7 +23,6 @@ using namespace lldb_private;
//----------------------------------------------------------------------
LineTable::LineTable(CompileUnit* comp_unit) :
m_comp_unit(comp_unit),
m_section_list(),
m_entries()
{
}
@ -37,8 +37,7 @@ LineTable::~LineTable()
void
LineTable::InsertLineEntry
(
const SectionSP& section_sp,
lldb::addr_t section_offset,
lldb::addr_t file_addr,
uint32_t line,
uint16_t column,
uint16_t file_idx,
@ -49,21 +48,7 @@ LineTable::InsertLineEntry
bool is_terminal_entry
)
{
SectionSP line_section_sp;
SectionSP linked_section_sp (section_sp->GetLinkedSection());
if (linked_section_sp)
{
section_offset += section_sp->GetLinkedOffset();
line_section_sp = linked_section_sp;
}
else
{
line_section_sp = section_sp;
}
assert(line_section_sp.get());
uint32_t sect_idx = m_section_list.AddUniqueSection (line_section_sp);
Entry entry(sect_idx, section_offset, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry);
Entry entry(file_addr, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry);
entry_collection::iterator begin_pos = m_entries.begin();
entry_collection::iterator end_pos = m_entries.end();
@ -85,7 +70,7 @@ LineSequence::LineSequence()
void
LineTable::LineSequenceImpl::Clear()
{
m_seq_entries.clear();
m_entries.clear();
}
LineSequence* LineTable::CreateLineSequenceContainer ()
@ -97,8 +82,7 @@ void
LineTable::AppendLineEntryToSequence
(
LineSequence* sequence,
const SectionSP& section_sp,
lldb::addr_t section_offset,
lldb::addr_t file_addr,
uint32_t line,
uint16_t column,
uint16_t file_idx,
@ -111,9 +95,8 @@ LineTable::AppendLineEntryToSequence
{
assert(sequence != NULL);
LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence);
uint32_t sect_idx = m_section_list.AddUniqueSection (section_sp);
Entry entry(sect_idx, section_offset, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry);
seq->m_seq_entries.push_back (entry);
Entry entry(file_addr, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry);
seq->m_entries.push_back (entry);
}
void
@ -121,17 +104,17 @@ LineTable::InsertSequence (LineSequence* sequence)
{
assert(sequence != NULL);
LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence);
if (seq->m_seq_entries.empty())
if (seq->m_entries.empty())
return;
Entry& entry = seq->m_seq_entries.front();
Entry& entry = seq->m_entries.front();
// If the first entry address in this sequence is greater than or equal to
// the address of the last item in our entry collection, just append.
if (m_entries.empty() || !Entry::EntryAddressLessThan(entry, m_entries.back()))
{
m_entries.insert(m_entries.end(),
seq->m_seq_entries.begin(),
seq->m_seq_entries.end());
seq->m_entries.begin(),
seq->m_entries.end());
return;
}
@ -149,7 +132,7 @@ LineTable::InsertSequence (LineSequence* sequence)
assert(prev_pos->is_terminal_entry);
}
#endif
m_entries.insert(pos, seq->m_seq_entries.begin(), seq->m_seq_entries.end());
m_entries.insert(pos, seq->m_entries.begin(), seq->m_entries.end());
}
//----------------------------------------------------------------------
@ -160,11 +143,9 @@ LineTable::Entry::LessThanBinaryPredicate::LessThanBinaryPredicate(LineTable *li
bool
LineTable::Entry::LessThanBinaryPredicate::operator() (const LineTable::Entry& a, const LineTable::Entry& b) const
{
if (a.sect_idx == b.sect_idx)
{
#define LT_COMPARE(a,b) if (a != b) return a < b
LT_COMPARE (a.sect_offset, b.sect_offset);
LT_COMPARE (a.file_addr, b.file_addr);
// b and a reversed on purpose below.
LT_COMPARE (b.is_terminal_entry, a.is_terminal_entry);
LT_COMPARE (a.line, b.line);
@ -179,20 +160,8 @@ LineTable::Entry::LessThanBinaryPredicate::operator() (const LineTable::Entry& a
#undef LT_COMPARE
}
const Section *a_section = m_line_table->GetSectionForEntryIndex (a.sect_idx);
const Section *b_section = m_line_table->GetSectionForEntryIndex (b.sect_idx);
return Section::Compare(*a_section, *b_section) < 0;
}
Section *
LineTable::GetSectionForEntryIndex (uint32_t idx)
{
if (idx < m_section_list.GetSize())
return m_section_list.GetSectionAtIndex(idx).get();
return NULL;
}
uint32_t
LineTable::GetSize() const
{
@ -218,13 +187,13 @@ LineTable::FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry
*index_ptr = UINT32_MAX;
bool success = false;
uint32_t sect_idx = m_section_list.FindSectionIndex (so_addr.GetSection().get());
if (sect_idx != UINT32_MAX)
if (so_addr.GetModule().get() == m_comp_unit->GetModule().get())
{
Entry search_entry;
search_entry.sect_idx = sect_idx;
search_entry.sect_offset = so_addr.GetOffset();
search_entry.file_addr = so_addr.GetFileAddress();
if (search_entry.file_addr != LLDB_INVALID_ADDRESS)
{
entry_collection::const_iterator begin_pos = m_entries.begin();
entry_collection::const_iterator end_pos = m_entries.end();
entry_collection::const_iterator pos = lower_bound(begin_pos, end_pos, search_entry, Entry::EntryAddressLessThan);
@ -232,9 +201,9 @@ LineTable::FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry
{
if (pos != begin_pos)
{
if (pos->sect_offset != search_entry.sect_offset)
if (pos->file_addr != search_entry.file_addr)
--pos;
else if (pos->sect_offset == search_entry.sect_offset)
else if (pos->file_addr == search_entry.file_addr)
{
// If this is a termination entry, it should't match since
// entries with the "is_terminal_entry" member set to true
@ -248,7 +217,7 @@ LineTable::FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry
++pos;
if (pos != end_pos)
{
if (pos->sect_offset != search_entry.sect_offset)
if (pos->file_addr != search_entry.file_addr)
pos = end_pos;
}
}
@ -261,8 +230,7 @@ LineTable::FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry
while (pos != begin_pos)
{
entry_collection::const_iterator prev_pos = pos - 1;
if (prev_pos->sect_idx == search_entry.sect_idx &&
prev_pos->sect_offset == search_entry.sect_offset &&
if (prev_pos->file_addr == search_entry.file_addr &&
prev_pos->is_terminal_entry == false)
--pos;
else
@ -284,6 +252,7 @@ LineTable::FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry
}
}
}
}
return success;
}
@ -294,23 +263,14 @@ LineTable::ConvertEntryAtIndexToLineEntry (uint32_t idx, LineEntry &line_entry)
if (idx < m_entries.size())
{
const Entry& entry = m_entries[idx];
line_entry.range.GetBaseAddress().SetSection(m_section_list.GetSectionAtIndex (entry.sect_idx));
line_entry.range.GetBaseAddress().SetOffset(entry.sect_offset);
ModuleSP module_sp (m_comp_unit->GetModule());
if (module_sp && module_sp->ResolveFileAddress(entry.file_addr, line_entry.range.GetBaseAddress()))
{
if (!entry.is_terminal_entry && idx + 1 < m_entries.size())
{
const Entry& next_entry = m_entries[idx+1];
if (next_entry.sect_idx == entry.sect_idx)
{
line_entry.range.SetByteSize(next_entry.sect_offset - entry.sect_offset);
}
else
{
Address next_line_addr(m_section_list.GetSectionAtIndex (next_entry.sect_idx), next_entry.sect_offset);
line_entry.range.SetByteSize(next_line_addr.GetFileAddress() - line_entry.range.GetBaseAddress().GetFileAddress());
}
}
line_entry.range.SetByteSize(m_entries[idx+1].file_addr - entry.file_addr);
else
line_entry.range.SetByteSize(0);
line_entry.file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex (entry.file_idx);
line_entry.line = entry.line;
line_entry.column = entry.column;
@ -321,6 +281,7 @@ LineTable::ConvertEntryAtIndexToLineEntry (uint32_t idx, LineEntry &line_entry)
line_entry.is_terminal_entry = entry.is_terminal_entry;
return true;
}
}
return false;
}
@ -503,7 +464,6 @@ LineTable::GetContiguousFileAddressRanges (FileAddressRanges &file_ranges, bool
const size_t count = m_entries.size();
LineEntry line_entry;
std::vector<addr_t> section_base_file_addrs (m_section_list.GetSize(), LLDB_INVALID_ADDRESS);
FileAddressRanges::Entry range (LLDB_INVALID_ADDRESS, 0);
for (size_t idx = 0; idx < count; ++idx)
{
@ -513,23 +473,89 @@ LineTable::GetContiguousFileAddressRanges (FileAddressRanges &file_ranges, bool
{
if (range.GetRangeBase() != LLDB_INVALID_ADDRESS)
{
if (section_base_file_addrs[entry.sect_idx] == LLDB_INVALID_ADDRESS)
section_base_file_addrs[entry.sect_idx] = m_section_list.GetSectionAtIndex (entry.sect_idx)->GetFileAddress();
range.SetRangeEnd(section_base_file_addrs[entry.sect_idx] + entry.sect_offset);
range.SetRangeEnd(entry.file_addr);
file_ranges.Append(range);
range.Clear(LLDB_INVALID_ADDRESS);
}
}
else if (range.GetRangeBase() == LLDB_INVALID_ADDRESS)
{
if (section_base_file_addrs[entry.sect_idx] == LLDB_INVALID_ADDRESS)
section_base_file_addrs[entry.sect_idx] = m_section_list.GetSectionAtIndex (entry.sect_idx)->GetFileAddress();
range.SetRangeBase(section_base_file_addrs[entry.sect_idx] + entry.sect_offset);
range.SetRangeBase(entry.file_addr);
}
}
return file_ranges.GetSize() - initial_count;
}
LineTable *
LineTable::LinkLineTable (const FileRangeMap &file_range_map)
{
std::auto_ptr<LineTable> line_table_ap (new LineTable (m_comp_unit));
LineSequenceImpl sequence;
const size_t count = m_entries.size();
LineEntry line_entry;
const FileRangeMap::Entry *file_range_entry = NULL;
const FileRangeMap::Entry *prev_file_range_entry = NULL;
lldb::addr_t prev_file_addr = LLDB_INVALID_ADDRESS;
bool prev_entry_was_linked = false;
for (size_t idx = 0; idx < count; ++idx)
{
const Entry& entry = m_entries[idx];
const bool end_sequence = entry.is_terminal_entry;
const lldb::addr_t lookup_file_addr = entry.file_addr - (end_sequence ? 1 : 0);
if (file_range_entry == NULL || !file_range_entry->Contains(lookup_file_addr))
{
prev_file_range_entry = file_range_entry;
file_range_entry = file_range_map.FindEntryThatContains(lookup_file_addr);
}
if (file_range_entry)
{
// This entry has an address remapping and it needs to have its address relinked
sequence.m_entries.push_back(entry);
// Fix tha addresss
const lldb::addr_t linked_file_addr = entry.file_addr - file_range_entry->GetRangeBase() + file_range_entry->data;
// if (linked_file_addr == 0x000000000128b7d5)
// puts("remove this");
sequence.m_entries.back().file_addr = linked_file_addr;
}
else if (prev_entry_was_linked)
{
// This entry doesn't have a remapping and it needs to be removed.
// Watch out in case we need to terminate a previous entry needs to
// be terminated now that one line entry in a sequence is not longer valid.
if (!entry.is_terminal_entry &&
!sequence.m_entries.empty() &&
!sequence.m_entries.back().is_terminal_entry)
{
assert (prev_file_addr != LLDB_INVALID_ADDRESS);
sequence.m_entries.push_back(sequence.m_entries.back());
const lldb::addr_t linked_file_addr = std::min<lldb::addr_t>(entry.file_addr,prev_file_range_entry->GetRangeEnd()) - prev_file_range_entry->GetRangeBase() + prev_file_range_entry->data;
sequence.m_entries.back().file_addr = linked_file_addr;
sequence.m_entries.back().is_terminal_entry = true;
}
}
// If we have items in the sequence and the last entry is a terminal entry,
// insert this sequence into our new line table.
if (!sequence.m_entries.empty() && sequence.m_entries.back().is_terminal_entry)
{
line_table_ap->InsertSequence (&sequence);
sequence.Clear();
prev_entry_was_linked = false;
prev_file_addr = LLDB_INVALID_ADDRESS;
}
else
{
prev_entry_was_linked = file_range_entry != NULL;
prev_file_addr = entry.file_addr;
}
}
if (line_table_ap->m_entries.empty())
return NULL;
return line_table_ap.release();
}

View File

@ -200,7 +200,9 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp,
m_data (),
m_unwind_table (*this),
m_process_wp(),
m_memory_addr (LLDB_INVALID_ADDRESS)
m_memory_addr (LLDB_INVALID_ADDRESS),
m_sections_ap (),
m_symtab_ap ()
{
if (file_spec_ptr)
m_file = *file_spec_ptr;
@ -209,12 +211,16 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp,
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
{
const ConstString object_name (module_sp->GetObjectName());
if (m_file)
{
log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, file = %s/%s, file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64 "\n",
log->Printf ("%p ObjectFile::ObjectFile() module = %p (%s%s%s%s), file = %s/%s, file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64,
this,
module_sp->GetFileSpec().GetDirectory().AsCString(),
module_sp.get(),
module_sp->GetFileSpec().GetFilename().AsCString(),
object_name ? "(" : "",
object_name ? object_name.GetCString() : "",
object_name ? ")" : "",
m_file.GetDirectory().AsCString(),
m_file.GetFilename().AsCString(),
m_file_offset,
@ -222,10 +228,13 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp,
}
else
{
log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, file = <NULL>, file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64 "\n",
log->Printf ("%p ObjectFile::ObjectFile() module = %p (%s%s%s%s), file = <NULL>, file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64,
this,
module_sp->GetFileSpec().GetDirectory().AsCString(),
module_sp.get(),
module_sp->GetFileSpec().GetFilename().AsCString(),
object_name ? "(" : "",
object_name ? object_name.GetCString() : "",
object_name ? ")" : "",
m_file_offset,
m_length);
}
@ -246,17 +255,23 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp,
m_data (),
m_unwind_table (*this),
m_process_wp (process_sp),
m_memory_addr (header_addr)
m_memory_addr (header_addr),
m_sections_ap (),
m_symtab_ap ()
{
if (header_data_sp)
m_data.SetData (header_data_sp, 0, header_data_sp->GetByteSize());
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
{
log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, process = %p, header_addr = 0x%" PRIx64 "\n",
const ConstString object_name (module_sp->GetObjectName());
log->Printf ("%p ObjectFile::ObjectFile() module = %p (%s%s%s%s), process = %p, header_addr = 0x%" PRIx64,
this,
module_sp->GetFileSpec().GetDirectory().AsCString(),
module_sp.get(),
module_sp->GetFileSpec().GetFilename().AsCString(),
object_name ? "(" : "",
object_name ? object_name.GetCString() : "",
object_name ? ")" : "",
process_sp.get(),
m_memory_addr);
}
@ -519,3 +534,20 @@ ObjectFile::SplitArchivePathWithObject (const char *path_with_object, FileSpec &
return false;
}
void
ObjectFile::ClearSymtab ()
{
ModuleSP module_sp(GetModule());
if (module_sp)
{
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
{
log->Printf ("%p ObjectFile::ClearSymtab () symtab = %p",
this,
m_symtab_ap.get());
}
m_symtab_ap.reset();
}
}

View File

@ -11,6 +11,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Timer.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
@ -882,13 +883,13 @@ Symtab::CalculateSymbolSize (Symbol *symbol)
if (!m_addr_indexes_computed)
InitAddressIndexes();
const size_t num_addr_indexes = m_addr_indexes.size();
const lldb::addr_t symbol_file_addr = symbol->GetAddress().GetFileAddress();
SymbolSearchInfo info = FindIndexPtrForSymbolContainingAddress (this,
symbol->GetAddress().GetFileAddress(),
symbol_file_addr,
&m_addr_indexes.front(),
num_addr_indexes);
if (info.match_index_ptr != NULL)
{
const lldb::addr_t curr_file_addr = symbol->GetAddress().GetFileAddress();
// We can figure out the address range of all symbols except the
// last one by taking the delta between the current symbol and
// the next symbol
@ -899,18 +900,35 @@ Symtab::CalculateSymbolSize (Symbol *symbol)
{
Symbol *next_symbol = SymbolAtIndex(m_addr_indexes[addr_index]);
if (next_symbol == NULL)
break;
const lldb::addr_t next_file_addr = next_symbol->GetAddress().GetFileAddress();
if (next_file_addr > curr_file_addr)
{
byte_size = next_file_addr - curr_file_addr;
// No next symbol take the size to be the remaining bytes in the section
// in which the symbol resides
SectionSP section_sp (m_objfile->GetSectionList()->FindSectionContainingFileAddress (symbol_file_addr));
if (section_sp)
{
const lldb::addr_t end_section_file_addr = section_sp->GetFileAddress() + section_sp->GetByteSize();
if (end_section_file_addr > symbol_file_addr)
{
byte_size = end_section_file_addr - symbol_file_addr;
symbol->SetByteSize(byte_size);
symbol->SetSizeIsSynthesized(true);
break;
}
}
}
else
{
const lldb::addr_t next_file_addr = next_symbol->GetAddress().GetFileAddress();
if (next_file_addr > symbol_file_addr)
{
byte_size = next_file_addr - symbol_file_addr;
symbol->SetByteSize(byte_size);
symbol->SetSizeIsSynthesized(true);
break;
}
}
}
}
}
return byte_size;
}