forked from OSchip/llvm-project
<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:
parent
427b404d0a
commit
9422dd64f8
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
@ -759,7 +1045,268 @@ namespace lldb_private {
|
|||
protected:
|
||||
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;
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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,43 +106,21 @@ 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)
|
||||
SectionSP parent_sp (GetParent ());
|
||||
if (parent_sp)
|
||||
{
|
||||
load_base_addr = linked_section_sp->GetLoadBaseAddress(target);
|
||||
load_base_addr = parent_sp->GetLoadBaseAddress (target);
|
||||
if (load_base_addr != LLDB_INVALID_ADDRESS)
|
||||
load_base_addr += m_linked_offset;
|
||||
load_base_addr += GetOffset();
|
||||
}
|
||||
else
|
||||
{
|
||||
SectionSP parent_sp (GetParent ());
|
||||
if (parent_sp)
|
||||
{
|
||||
load_base_addr = parent_sp->GetLoadBaseAddress (target);
|
||||
if (load_base_addr != LLDB_INVALID_ADDRESS)
|
||||
load_base_addr += GetOffset();
|
||||
}
|
||||
else
|
||||
{
|
||||
load_base_addr = target->GetSectionLoadList().GetSectionLoadAddress (const_cast<Section *>(this)->shared_from_this());
|
||||
}
|
||||
load_base_addr = target->GetSectionLoadList().GetSectionLoadAddress (const_cast<Section *>(this)->shared_from_this());
|
||||
}
|
||||
|
||||
return load_base_addr;
|
||||
}
|
||||
|
||||
|
@ -174,22 +139,13 @@ 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());
|
||||
|
||||
so_addr.SetOffset(offset);
|
||||
so_addr.SetSection(const_cast<Section *>(this)->shared_from_this());
|
||||
|
||||
#ifdef LLDB_CONFIGURATION_DEBUG
|
||||
// For debug builds, ensure that there are no orphaned (i.e., moduleless) sections.
|
||||
assert(GetModule().get());
|
||||
// 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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -891,28 +891,40 @@ SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, DWARFCompile
|
|||
|
||||
assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED);
|
||||
|
||||
func_range.GetBaseAddress().ResolveLinkedAddress();
|
||||
|
||||
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,
|
||||
func_name,
|
||||
func_type,
|
||||
func_range)); // first address range
|
||||
|
||||
if (func_sp.get() != NULL)
|
||||
if (FixupAddress (func_range.GetBaseAddress()))
|
||||
{
|
||||
if (frame_base.IsValid())
|
||||
func_sp->GetFrameBaseExpression() = frame_base;
|
||||
sc.comp_unit->AddFunction(func_sp);
|
||||
return func_sp.get();
|
||||
const user_id_t func_user_id = MakeUserID(die->GetOffset());
|
||||
func_sp.reset(new Function (sc.comp_unit,
|
||||
MakeUserID(func_user_id), // UserID is the DIE offset
|
||||
MakeUserID(func_user_id),
|
||||
func_name,
|
||||
func_type,
|
||||
func_range)); // first address range
|
||||
|
||||
if (func_sp.get() != NULL)
|
||||
{
|
||||
if (frame_base.IsValid())
|
||||
func_sp->GetFrameBaseExpression() = frame_base;
|
||||
sc.comp_unit->AddFunction(func_sp);
|
||||
return func_sp.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
SymbolFileDWARF::FixupAddress (Address &addr)
|
||||
{
|
||||
SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile ();
|
||||
if (debug_map_symfile)
|
||||
{
|
||||
return debug_map_symfile->LinkOSOAddress(addr);
|
||||
}
|
||||
// This is a normal DWARF file, no address fixups need to happen
|
||||
return true;
|
||||
}
|
||||
lldb::LanguageType
|
||||
SymbolFileDWARF::ParseCompileUnitLanguage (const SymbolContext& sc)
|
||||
{
|
||||
|
@ -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,166 +1015,32 @@ ParseDWARFLineTableCallback(dw_offset_t offset, const DWARFDebugLine::State& sta
|
|||
else
|
||||
{
|
||||
ParseDWARFLineTableCallbackInfo* info = (ParseDWARFLineTableCallbackInfo*)userData;
|
||||
// We have a new row, lets append it
|
||||
LineTable* line_table = info->line_table;
|
||||
|
||||
if (info->curr_section_sp.get() == NULL || info->curr_section_sp->ContainsFileAddress(state.address) == false)
|
||||
// If this is our first time here, we need to create a
|
||||
// sequence container.
|
||||
if (!info->sequence_ap.get())
|
||||
{
|
||||
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;
|
||||
info->sequence_ap.reset(line_table->CreateLineSequenceContainer());
|
||||
assert(info->sequence_ap.get());
|
||||
}
|
||||
if (info->curr_section_sp.get())
|
||||
line_table->AppendLineEntryToSequence (info->sequence_ap.get(),
|
||||
state.address,
|
||||
state.line,
|
||||
state.column,
|
||||
state.file,
|
||||
state.is_stmt,
|
||||
state.basic_block,
|
||||
state.prologue_end,
|
||||
state.epilogue_begin,
|
||||
state.end_sequence);
|
||||
if (state.end_sequence)
|
||||
{
|
||||
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.
|
||||
|
||||
// If this is our first time here, we need to create a
|
||||
// sequence container.
|
||||
if (!info->curr_sequence_ap)
|
||||
{
|
||||
info->curr_sequence_ap.reset(line_table->CreateLineSequenceContainer());
|
||||
assert(info->curr_sequence_ap);
|
||||
}
|
||||
line_table->AppendLineEntryToSequence(info->curr_sequence_ap.get(),
|
||||
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);
|
||||
if (state.end_sequence)
|
||||
{
|
||||
// First, put the current sequence into the line table.
|
||||
line_table->InsertSequence(info->curr_sequence_ap.get());
|
||||
// Then, empty it to prepare for the next sequence.
|
||||
info->curr_sequence_ap->Clear();
|
||||
}
|
||||
}
|
||||
// First, put the current sequence into the line table.
|
||||
line_table->InsertSequence(info->sequence_ap.get());
|
||||
// Then, empty it to prepare for the next sequence.
|
||||
info->sequence_ap->Clear();
|
||||
}
|
||||
|
||||
info->prev_row = state;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1194,22 +1063,23 @@ 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);
|
||||
sc.comp_unit->SetLineTable(line_table_ap.release());
|
||||
return true;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 (dwarf_cu == NULL)
|
||||
return 0;
|
||||
|
||||
if (sc.function)
|
||||
{
|
||||
DWARFCompileUnit* dwarf_cu = info->GetCompileUnitContainingDIE(sc.function->GetID()).get();
|
||||
|
||||
if (dwarf_cu == NULL)
|
||||
return 0;
|
||||
|
||||
const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(sc.function->GetID());
|
||||
|
||||
dw_addr_t func_lo_pc = function_die->GetAttributeValueAsUnsigned (this, dwarf_cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
|
||||
|
@ -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,67 +7118,63 @@ SymbolFileDWARF::ParseVariableDIE
|
|||
}
|
||||
}
|
||||
|
||||
if (location_has_op_addr)
|
||||
if (location_DW_OP_addr != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
if (is_external)
|
||||
{
|
||||
scope = eValueTypeVariableGlobal;
|
||||
|
||||
if (GetDebugMapSymfile ())
|
||||
else
|
||||
scope = eValueTypeVariableStatic;
|
||||
|
||||
|
||||
SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile ();
|
||||
|
||||
if (debug_map_symfile)
|
||||
{
|
||||
// When leaving the DWARF in the .o files on darwin,
|
||||
// when we have a global variable that wasn't initialized,
|
||||
// the .o file might not have allocated a virtual
|
||||
// address for the global variable. In this case it will
|
||||
// have created a symbol for the global variable
|
||||
// that is undefined/data and external and the value will
|
||||
// be the byte size of the variable. When we do the
|
||||
// address map in SymbolFileDWARFDebugMap we rely on
|
||||
// having an address, we need to do some magic here
|
||||
// so we can get the correct address for our global
|
||||
// variable. The address for all of these entries
|
||||
// will be zero, and there will be an undefined symbol
|
||||
// in this object file, and the executable will have
|
||||
// a matching symbol with a good address. So here we
|
||||
// dig up the correct address and replace it in the
|
||||
// location for the variable, and set the variable's
|
||||
// symbol context scope to be that of the main executable
|
||||
// so the file address will resolve correctly.
|
||||
bool linked_oso_file_addr = false;
|
||||
if (is_external && location_DW_OP_addr == 0)
|
||||
{
|
||||
// When leaving the DWARF in the .o files on darwin,
|
||||
// when we have a global variable that wasn't initialized,
|
||||
// the .o file might not have allocated a virtual
|
||||
// address for the global variable. In this case it will
|
||||
// have created a symbol for the global variable
|
||||
// that is undefined/data and external and the value will
|
||||
// be the byte size of the variable. When we do the
|
||||
// address map in SymbolFileDWARFDebugMap we rely on
|
||||
// having an address, we need to do some magic here
|
||||
// so we can get the correct address for our global
|
||||
// variable. The address for all of these entries
|
||||
// will be zero, and there will be an undefined symbol
|
||||
// in this object file, and the executable will have
|
||||
// a matching symbol with a good address. So here we
|
||||
// dig up the correct address and replace it in the
|
||||
// location for the variable, and set the variable's
|
||||
// symbol context scope to be that of the main executable
|
||||
// so the file address will resolve correctly.
|
||||
if (location.LocationContains_DW_OP_addr (0, op_error))
|
||||
|
||||
// we have a possible uninitialized extern global
|
||||
ConstString const_name(mangled ? mangled : name);
|
||||
ObjectFile *debug_map_objfile = debug_map_symfile->GetObjectFile();
|
||||
if (debug_map_objfile)
|
||||
{
|
||||
|
||||
// we have a possible uninitialized extern global
|
||||
Symtab *symtab = m_obj_file->GetSymtab();
|
||||
if (symtab)
|
||||
Symtab *debug_map_symtab = debug_map_objfile->GetSymtab();
|
||||
if (debug_map_symtab)
|
||||
{
|
||||
ConstString const_name(mangled ? mangled : name);
|
||||
Symbol *o_symbol = symtab->FindFirstSymbolWithNameAndType (const_name,
|
||||
eSymbolTypeAny,
|
||||
Symtab::eDebugNo,
|
||||
Symtab::eVisibilityExtern);
|
||||
|
||||
if (o_symbol)
|
||||
Symbol *exe_symbol = debug_map_symtab->FindFirstSymbolWithNameAndType (const_name,
|
||||
eSymbolTypeData,
|
||||
Symtab::eDebugYes,
|
||||
Symtab::eVisibilityExtern);
|
||||
if (exe_symbol)
|
||||
{
|
||||
ObjectFile *debug_map_objfile = m_debug_map_symfile->GetObjectFile();
|
||||
if (debug_map_objfile)
|
||||
if (exe_symbol->ValueIsAddress())
|
||||
{
|
||||
Symtab *debug_map_symtab = debug_map_objfile->GetSymtab();
|
||||
Symbol *defined_symbol = debug_map_symtab->FindFirstSymbolWithNameAndType (const_name,
|
||||
eSymbolTypeData,
|
||||
Symtab::eDebugYes,
|
||||
Symtab::eVisibilityExtern);
|
||||
if (defined_symbol)
|
||||
const addr_t exe_file_addr = exe_symbol->GetAddress().GetFileAddress();
|
||||
if (exe_file_addr != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
if (defined_symbol->ValueIsAddress())
|
||||
if (location.Update_DW_OP_addr (exe_file_addr))
|
||||
{
|
||||
const addr_t defined_addr = defined_symbol->GetAddress().GetFileAddress();
|
||||
if (defined_addr != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
if (location.Update_DW_OP_addr (defined_addr))
|
||||
{
|
||||
symbol_context_scope = defined_symbol;
|
||||
}
|
||||
}
|
||||
linked_oso_file_addr = true;
|
||||
symbol_context_scope = exe_symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7312,10 +7182,23 @@ SymbolFileDWARF::ParseVariableDIE
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
scope = eValueTypeVariableStatic;
|
||||
|
||||
if (!linked_oso_file_addr)
|
||||
{
|
||||
// The DW_OP_addr is not zero, but it contains a .o file address which
|
||||
// needs to be linked up correctly.
|
||||
const lldb::addr_t exe_file_addr = debug_map_symfile->LinkOSOFileAddress(this, location_DW_OP_addr);
|
||||
if (exe_file_addr != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
// Update the file address for this variable
|
||||
location.Update_DW_OP_addr (exe_file_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Variable didn't make it into the final executable
|
||||
return var_sp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,6 +38,151 @@ 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.
|
||||
|
||||
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
ConstString object_name (oso_module->GetObjectName());
|
||||
log->Printf("%p: SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap ('%s/%s%s%s%s')",
|
||||
this,
|
||||
oso_module->GetFileSpec().GetDirectory().GetCString(),
|
||||
oso_module->GetFileSpec().GetFilename().GetCString(),
|
||||
object_name ? "(" : "",
|
||||
object_name ? object_name.GetCString() : "",
|
||||
object_name ? ")" : "");
|
||||
}
|
||||
|
||||
|
||||
std::vector<SymbolFileDWARFDebugMap::CompileUnitInfo *> cu_infos;
|
||||
if (exe_symfile->GetCompUnitInfosForModule(oso_module, cu_infos))
|
||||
{
|
||||
for (auto comp_unit_info : cu_infos)
|
||||
{
|
||||
Symtab *exe_symtab = exe_symfile->GetObjectFile()->GetSymtab();
|
||||
ModuleSP oso_module_sp (oso_objfile->GetModule());
|
||||
Symtab *oso_symtab = oso_objfile->GetSymtab();
|
||||
#if defined(DEBUG_OSO_DMAP)
|
||||
StreamFile s(stdout, false);
|
||||
s << "OSO symtab:\n";
|
||||
oso_symtab->Dump(&s, NULL, eSortOrderNone);
|
||||
s << "OSO sections before:\n";
|
||||
oso_objfile->GetSectionList()->Dump(&s, NULL, true, UINT32_MAX);
|
||||
#endif
|
||||
|
||||
///const uint32_t fun_resolve_flags = SymbolContext::Module | eSymbolContextCompUnit | eSymbolContextFunction;
|
||||
//SectionList *oso_sections = oso_objfile->Sections();
|
||||
// Now we need to make sections that map from zero based object
|
||||
// file addresses to where things eneded up in the main executable.
|
||||
|
||||
assert (comp_unit_info->first_symbol_index != UINT32_MAX);
|
||||
// End index is one past the last valid symbol index
|
||||
const uint32_t oso_end_idx = comp_unit_info->last_symbol_index + 1;
|
||||
for (uint32_t idx = comp_unit_info->first_symbol_index + 2; // Skip the N_SO and N_OSO
|
||||
idx < oso_end_idx;
|
||||
++idx)
|
||||
{
|
||||
Symbol *exe_symbol = exe_symtab->SymbolAtIndex(idx);
|
||||
if (exe_symbol)
|
||||
{
|
||||
if (exe_symbol->IsDebug() == false)
|
||||
continue;
|
||||
|
||||
switch (exe_symbol->GetType())
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case eSymbolTypeCode:
|
||||
{
|
||||
// For each N_FUN, or function that we run into in the debug map
|
||||
// we make a new section that we add to the sections found in the
|
||||
// .o file. This new section has the file address set to what the
|
||||
// addresses are in the .o file, and the load address is adjusted
|
||||
// to match where it ended up in the final executable! We do this
|
||||
// before we parse any dwarf info so that when it goes get parsed
|
||||
// all section/offset addresses that get registered will resolve
|
||||
// correctly to the new addresses in the main executable.
|
||||
|
||||
// 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);
|
||||
if (oso_fun_symbol)
|
||||
{
|
||||
// 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()));
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case eSymbolTypeData:
|
||||
{
|
||||
// For each N_GSYM we remap the address for the global by making
|
||||
// a new section that we add to the sections found in the .o file.
|
||||
// This new section has the file address set to what the
|
||||
// addresses are in the .o file, and the load address is adjusted
|
||||
// to match where it ended up in the final executable! We do this
|
||||
// before we parse any dwarf info so that when it goes get parsed
|
||||
// all section/offset addresses that get registered will resolve
|
||||
// correctly to the new addresses in the main executable. We
|
||||
// initially set the section size to be 1 byte, but will need to
|
||||
// fix up these addresses further after all globals have been
|
||||
// parsed to span the gaps, or we can find the global variable
|
||||
// sizes from the DWARF info as we are parsing.
|
||||
|
||||
// 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(Mangled::ePreferMangled),
|
||||
eSymbolTypeData,
|
||||
Symtab::eDebugNo,
|
||||
Symtab::eVisibilityAny);
|
||||
|
||||
if (exe_symbol && oso_gsym_symbol &&
|
||||
exe_symbol->ValueIsAddress() &&
|
||||
oso_gsym_symbol->ValueIsAddress())
|
||||
{
|
||||
// Add the inverse OSO file address to debug map entry mapping
|
||||
exe_symfile->AddOSOFileRange (this,
|
||||
exe_symbol->GetAddress().GetFileAddress(),
|
||||
oso_gsym_symbol->GetAddress().GetFileAddress(),
|
||||
std::min<addr_t>(exe_symbol->GetByteSize(), oso_gsym_symbol->GetByteSize()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exe_symfile->FinalizeOSOFileRanges (this);
|
||||
#if defined(DEBUG_OSO_DMAP)
|
||||
s << "OSO sections after:\n";
|
||||
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:
|
||||
|
@ -48,194 +196,13 @@ public:
|
|||
m_exe_module_wp (exe_module_sp),
|
||||
m_cu_idx (cu_idx)
|
||||
{
|
||||
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')",
|
||||
this,
|
||||
exe_module_sp.get(),
|
||||
cu_idx,
|
||||
file_spec.GetDirectory().GetCString(),
|
||||
file_spec.GetFilename().GetCString(),
|
||||
object_name ? object_name->GetCString() : "");
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
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();
|
||||
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);
|
||||
s << "OSO symtab:\n";
|
||||
oso_symtab->Dump(&s, NULL);
|
||||
s << "OSO sections before:\n";
|
||||
oso_objfile->GetSectionList()->Dump(&s, NULL, true);
|
||||
#endif
|
||||
|
||||
///const uint32_t fun_resolve_flags = SymbolContext::Module | eSymbolContextCompUnit | eSymbolContextFunction;
|
||||
//SectionList *oso_sections = oso_objfile->Sections();
|
||||
// Now we need to make sections that map from zero based object
|
||||
// file addresses to where things eneded up in the main executable.
|
||||
|
||||
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)
|
||||
{
|
||||
Symbol *exe_symbol = exe_symtab->SymbolAtIndex(idx);
|
||||
if (exe_symbol)
|
||||
{
|
||||
if (exe_symbol->IsDebug() == false)
|
||||
continue;
|
||||
|
||||
switch (exe_symbol->GetType())
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case eSymbolTypeCode:
|
||||
{
|
||||
// For each N_FUN, or function that we run into in the debug map
|
||||
// we make a new section that we add to the sections found in the
|
||||
// .o file. This new section has the file address set to what the
|
||||
// addresses are in the .o file, and the load address is adjusted
|
||||
// to match where it ended up in the final executable! We do this
|
||||
// before we parse any dwarf info so that when it goes get parsed
|
||||
// all section/offset addresses that get registered will resolve
|
||||
// correctly to the new addresses in the main executable.
|
||||
|
||||
// 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);
|
||||
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.
|
||||
|
||||
// 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;
|
||||
|
||||
case eSymbolTypeData:
|
||||
{
|
||||
// For each N_GSYM we remap the address for the global by making
|
||||
// a new section that we add to the sections found in the .o file.
|
||||
// This new section has the file address set to what the
|
||||
// addresses are in the .o file, and the load address is adjusted
|
||||
// to match where it ended up in the final executable! We do this
|
||||
// before we parse any dwarf info so that when it goes get parsed
|
||||
// all section/offset addresses that get registered will resolve
|
||||
// correctly to the new addresses in the main executable. We
|
||||
// initially set the section size to be 1 byte, but will need to
|
||||
// fix up these addresses further after all globals have been
|
||||
// parsed to span the gaps, or we can find the global variable
|
||||
// sizes from the DWARF info as we are parsing.
|
||||
|
||||
// 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(),
|
||||
eSymbolTypeData,
|
||||
Symtab::eDebugNo,
|
||||
Symtab::eVisibilityAny);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
oso_objfile->GetSectionList()->Finalize(); // Now that we're done adding sections, finalize to build fast-lookup caches
|
||||
#if defined(DEBUG_OSO_DMAP)
|
||||
s << "OSO sections after:\n";
|
||||
oso_objfile->GetSectionList()->Dump(&s, NULL, true);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return m_objfile_sp.get();
|
||||
}
|
||||
|
||||
virtual SymbolVendor*
|
||||
GetSymbolVendor(bool can_create = true, lldb_private::Stream *feedback_strm = NULL)
|
||||
|
@ -356,14 +323,12 @@ SymbolFileDWARFDebugMap::InitializeObject()
|
|||
GetClangASTContext().SetExternalSource (ast_source_ap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
SymbolFileDWARFDebugMap::InitOSO()
|
||||
{
|
||||
if (m_flags.test(kHaveInitializedOSOs))
|
||||
return;
|
||||
|
||||
|
||||
m_flags.set(kHaveInitializedOSOs);
|
||||
// In order to get the abilities of this plug-in, we look at the list of
|
||||
// N_OSO entries (object files) from the symbol table and make sure that
|
||||
|
@ -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);
|
||||
|
||||
|
@ -643,34 +628,20 @@ 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(),
|
||||
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));
|
||||
}
|
||||
// User zero as the ID to match the compile unit at offset
|
||||
// zero in each .o file since each .o file can only have
|
||||
// one compile unit for now.
|
||||
lldb::user_id_t cu_id = 0;
|
||||
m_compile_unit_infos[cu_idx].compile_unit_sp.reset(new CompileUnit (m_obj_file->GetModule(),
|
||||
NULL,
|
||||
so_file_spec,
|
||||
cu_id,
|
||||
eLanguageTypeUnknown));
|
||||
|
||||
if (m_compile_unit_infos[cu_idx].compile_unit_sp)
|
||||
{
|
||||
// Let our symbol vendor know about this compile unit
|
||||
m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex (cu_idx,
|
||||
m_compile_unit_infos[cu_idx].compile_unit_sp);
|
||||
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,30 +769,30 @@ 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());
|
||||
|
||||
if (sc.symbol != NULL)
|
||||
const DebugMap::Entry *debug_map_entry = m_debug_map.FindEntryThatContains (exe_file_addr);
|
||||
if (debug_map_entry)
|
||||
{
|
||||
resolved_flags |= eSymbolContextSymbol;
|
||||
|
||||
uint32_t oso_idx = 0;
|
||||
CompileUnitInfo* comp_unit_info = GetCompileUnitInfoForSymbolWithID (sc.symbol->GetID(), &oso_idx);
|
||||
if (comp_unit_info)
|
||||
sc.symbol = symtab->SymbolAtIndex(debug_map_entry->data.GetExeSymbolIndex());
|
||||
|
||||
if (sc.symbol != NULL)
|
||||
{
|
||||
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);
|
||||
ObjectFile *oso_objfile = GetObjectFileByOSOIndex (oso_idx);
|
||||
if (oso_dwarf && oso_objfile)
|
||||
resolved_flags |= eSymbolContextSymbol;
|
||||
|
||||
uint32_t oso_idx = 0;
|
||||
CompileUnitInfo* comp_unit_info = GetCompileUnitInfoForSymbolWithID (sc.symbol->GetID(), &oso_idx);
|
||||
if (comp_unit_info)
|
||||
{
|
||||
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)
|
||||
Module *oso_module = GetModuleByCompUnitInfo (comp_unit_info);
|
||||
if (oso_module)
|
||||
{
|
||||
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);
|
||||
lldb::addr_t oso_file_addr = exe_file_addr - debug_map_entry->GetRangeBase() + debug_map_entry->data.GetOSOFileAddress();
|
||||
Address oso_so_addr;
|
||||
if (oso_module->ResolveFileAddress(oso_file_addr, oso_so_addr))
|
||||
{
|
||||
resolved_flags |= oso_module->GetSymbolVendor()->ResolveSymbolContext (oso_so_addr, resolve_scope, sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -240,6 +251,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_
|
||||
|
|
|
@ -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 section_sp->GetModule();
|
||||
|
||||
return this->GetCompileUnit()->GetModule();
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -161,37 +144,23 @@ 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);
|
||||
// b and a reversed on purpose below.
|
||||
LT_COMPARE (b.is_terminal_entry, a.is_terminal_entry);
|
||||
LT_COMPARE (a.line, b.line);
|
||||
LT_COMPARE (a.column, b.column);
|
||||
LT_COMPARE (a.is_start_of_statement, b.is_start_of_statement);
|
||||
LT_COMPARE (a.is_start_of_basic_block, b.is_start_of_basic_block);
|
||||
// b and a reversed on purpose below.
|
||||
LT_COMPARE (b.is_prologue_end, a.is_prologue_end);
|
||||
LT_COMPARE (a.is_epilogue_begin, b.is_epilogue_begin);
|
||||
LT_COMPARE (a.file_idx, b.file_idx);
|
||||
return false;
|
||||
#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;
|
||||
#define LT_COMPARE(a,b) if (a != b) return a < b
|
||||
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);
|
||||
LT_COMPARE (a.column, b.column);
|
||||
LT_COMPARE (a.is_start_of_statement, b.is_start_of_statement);
|
||||
LT_COMPARE (a.is_start_of_basic_block, b.is_start_of_basic_block);
|
||||
// b and a reversed on purpose below.
|
||||
LT_COMPARE (b.is_prologue_end, a.is_prologue_end);
|
||||
LT_COMPARE (a.is_epilogue_begin, b.is_epilogue_begin);
|
||||
LT_COMPARE (a.file_idx, b.file_idx);
|
||||
return false;
|
||||
#undef LT_COMPARE
|
||||
}
|
||||
|
||||
|
||||
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,69 +187,69 @@ 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();
|
||||
|
||||
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);
|
||||
if (pos != end_pos)
|
||||
search_entry.file_addr = so_addr.GetFileAddress();
|
||||
if (search_entry.file_addr != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
if (pos != begin_pos)
|
||||
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);
|
||||
if (pos != end_pos)
|
||||
{
|
||||
if (pos->sect_offset != search_entry.sect_offset)
|
||||
--pos;
|
||||
else if (pos->sect_offset == search_entry.sect_offset)
|
||||
if (pos != begin_pos)
|
||||
{
|
||||
// If this is a termination entry, it should't match since
|
||||
// entries with the "is_terminal_entry" member set to true
|
||||
// are termination entries that define the range for the
|
||||
// previous entry.
|
||||
if (pos->is_terminal_entry)
|
||||
if (pos->file_addr != search_entry.file_addr)
|
||||
--pos;
|
||||
else if (pos->file_addr == search_entry.file_addr)
|
||||
{
|
||||
// The matching entry is a terminal entry, so we skip
|
||||
// ahead to the next entry to see if there is another
|
||||
// entry following this one whose section/offset matches.
|
||||
++pos;
|
||||
// If this is a termination entry, it should't match since
|
||||
// entries with the "is_terminal_entry" member set to true
|
||||
// are termination entries that define the range for the
|
||||
// previous entry.
|
||||
if (pos->is_terminal_entry)
|
||||
{
|
||||
// The matching entry is a terminal entry, so we skip
|
||||
// ahead to the next entry to see if there is another
|
||||
// entry following this one whose section/offset matches.
|
||||
++pos;
|
||||
if (pos != end_pos)
|
||||
{
|
||||
if (pos->file_addr != search_entry.file_addr)
|
||||
pos = end_pos;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos != end_pos)
|
||||
{
|
||||
if (pos->sect_offset != search_entry.sect_offset)
|
||||
pos = end_pos;
|
||||
// While in the same section/offset backup to find the first
|
||||
// line entry that matches the address in case there are
|
||||
// multiple
|
||||
while (pos != begin_pos)
|
||||
{
|
||||
entry_collection::const_iterator prev_pos = pos - 1;
|
||||
if (prev_pos->file_addr == search_entry.file_addr &&
|
||||
prev_pos->is_terminal_entry == false)
|
||||
--pos;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pos != end_pos)
|
||||
{
|
||||
// While in the same section/offset backup to find the first
|
||||
// line entry that matches the address in case there are
|
||||
// multiple
|
||||
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 &&
|
||||
prev_pos->is_terminal_entry == false)
|
||||
--pos;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Make sure we have a valid match and that the match isn't a terminating
|
||||
// entry for a previous line...
|
||||
if (pos != end_pos && pos->is_terminal_entry == false)
|
||||
{
|
||||
uint32_t match_idx = std::distance (begin_pos, pos);
|
||||
success = ConvertEntryAtIndexToLineEntry(match_idx, line_entry);
|
||||
if (index_ptr != NULL && success)
|
||||
*index_ptr = match_idx;
|
||||
}
|
||||
|
||||
// Make sure we have a valid match and that the match isn't a terminating
|
||||
// entry for a previous line...
|
||||
if (pos != end_pos && pos->is_terminal_entry == false)
|
||||
{
|
||||
uint32_t match_idx = std::distance (begin_pos, pos);
|
||||
success = ConvertEntryAtIndexToLineEntry(match_idx, line_entry);
|
||||
if (index_ptr != NULL && success)
|
||||
*index_ptr = match_idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -294,32 +263,24 @@ 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);
|
||||
if (!entry.is_terminal_entry && idx + 1 < m_entries.size())
|
||||
ModuleSP module_sp (m_comp_unit->GetModule());
|
||||
if (module_sp && module_sp->ResolveFileAddress(entry.file_addr, line_entry.range.GetBaseAddress()))
|
||||
{
|
||||
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);
|
||||
}
|
||||
if (!entry.is_terminal_entry && idx + 1 < m_entries.size())
|
||||
line_entry.range.SetByteSize(m_entries[idx+1].file_addr - entry.file_addr);
|
||||
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(0);
|
||||
|
||||
line_entry.file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex (entry.file_idx);
|
||||
line_entry.line = entry.line;
|
||||
line_entry.column = entry.column;
|
||||
line_entry.is_start_of_statement = entry.is_start_of_statement;
|
||||
line_entry.is_start_of_basic_block = entry.is_start_of_basic_block;
|
||||
line_entry.is_prologue_end = entry.is_prologue_end;
|
||||
line_entry.is_epilogue_begin = entry.is_epilogue_begin;
|
||||
line_entry.is_terminal_entry = entry.is_terminal_entry;
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
line_entry.is_start_of_statement = entry.is_start_of_statement;
|
||||
line_entry.is_start_of_basic_block = entry.is_start_of_basic_block;
|
||||
line_entry.is_prologue_end = entry.is_prologue_end;
|
||||
line_entry.is_epilogue_begin = entry.is_epilogue_begin;
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -200,8 +200,10 @@ 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;
|
||||
if (data_sp)
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,15 +900,32 @@ 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;
|
||||
symbol->SetByteSize(byte_size);
|
||||
symbol->SetSizeIsSynthesized(true);
|
||||
break;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue