DWARFDebugArangeSet.cpp revision 254729
10Sduke//===-- DWARFDebugArangeSet.cpp ---------------------------------*- C++ -*-===//
211352Scoleenp//
30Sduke//                     The LLVM Compiler Infrastructure
40Sduke//
50Sduke// This file is distributed under the University of Illinois Open Source
60Sduke// License. See LICENSE.TXT for details.
70Sduke//
80Sduke//===----------------------------------------------------------------------===//
90Sduke
100Sduke#include "DWARFDebugArangeSet.h"
110Sduke
120Sduke#include <assert.h>
130Sduke#include "lldb/Core/Stream.h"
140Sduke#include "SymbolFileDWARF.h"
150Sduke
160Sdukeusing namespace lldb_private;
170Sduke
180SdukeDWARFDebugArangeSet::DWARFDebugArangeSet() :
191472Strims    m_offset(DW_INVALID_OFFSET),
201472Strims    m_header(),
211472Strims    m_arange_descriptors()
220Sduke{
230Sduke    m_header.length     = 0;
240Sduke    m_header.version    = 0;
251879Sstefank    m_header.cu_offset  = 0;
261879Sstefank    m_header.addr_size  = 0;
271879Sstefank    m_header.seg_size   = 0;
281879Sstefank}
291879Sstefank
301879Sstefankvoid
311879SstefankDWARFDebugArangeSet::Clear()
321879Sstefank{
331879Sstefank    m_offset = DW_INVALID_OFFSET;
341879Sstefank    m_header.length     = 0;
351879Sstefank    m_header.version    = 0;
361879Sstefank    m_header.cu_offset  = 0;
370Sduke    m_header.addr_size  = 0;
380Sduke    m_header.seg_size   = 0;
390Sduke    m_arange_descriptors.clear();
400Sduke}
410Sduke
420Sdukevoid
430SdukeDWARFDebugArangeSet::SetHeader
440Sduke(
450Sduke    uint16_t version,
460Sduke    uint32_t cu_offset,
470Sduke    uint8_t addr_size,
480Sduke    uint8_t seg_size
490Sduke)
500Sduke{
510Sduke    m_header.version    = version;
520Sduke    m_header.cu_offset  = cu_offset;
530Sduke    m_header.addr_size  = addr_size;
540Sduke    m_header.seg_size   = seg_size;
550Sduke}
560Sduke
570Sdukevoid
5812600SvlivanovDWARFDebugArangeSet::Compact()
590Sduke{
600Sduke    if (m_arange_descriptors.empty())
610Sduke        return;
620Sduke
630Sduke    // Iterate through all arange descriptors and combine any ranges that
640Sduke    // overlap or have matching boundaries. The m_arange_descriptors are assumed
650Sduke    // to be in ascending order after being built by adding descriptors
660Sduke    // using the AddDescriptor method.
670Sduke    uint32_t i = 0;
680Sduke    while (i + 1 < m_arange_descriptors.size())
69780Skvn    {
70780Skvn        if (m_arange_descriptors[i].end_address() >= m_arange_descriptors[i+1].address)
71780Skvn        {
721213Sdcubed            // The current range ends at or exceeds the start of the next address range.
736031Smgronlun            // Compute the max end address between the two and use that to make the new
74780Skvn            // length.
75780Skvn            const dw_addr_t max_end_addr = std::max(m_arange_descriptors[i].end_address(), m_arange_descriptors[i+1].end_address());
76780Skvn            m_arange_descriptors[i].length = max_end_addr - m_arange_descriptors[i].address;
77780Skvn            // Now remove the next entry as it was just combined with the previous one.
78780Skvn            m_arange_descriptors.erase(m_arange_descriptors.begin()+i+1);
79780Skvn        }
80780Skvn        else
810Sduke        {
820Sduke            // Discontiguous address range, just proceed to the next one.
830Sduke            ++i;
841142Snever        }
851142Snever    }
861142Snever}
870Sduke//----------------------------------------------------------------------
880Sduke// Compare function DWARFDebugArangeSet::Descriptor structures
890Sduke//----------------------------------------------------------------------
900Sdukestatic bool DescriptorLessThan (const DWARFDebugArangeSet::Descriptor& range1, const DWARFDebugArangeSet::Descriptor& range2)
910Sduke{
920Sduke    return range1.address < range2.address;
930Sduke}
940Sduke
950Sduke//----------------------------------------------------------------------
960Sduke// Add a range descriptor and keep things sorted so we can easily
970Sduke// compact the ranges before being saved or used.
980Sduke//----------------------------------------------------------------------
990Sdukevoid
1000SdukeDWARFDebugArangeSet::AddDescriptor(const DWARFDebugArangeSet::Descriptor& range)
1010Sduke{
1021080Snever    if (m_arange_descriptors.empty())
1031080Snever    {
1041080Snever        m_arange_descriptors.push_back(range);
1050Sduke        return;
1060Sduke    }
1070Sduke
1080Sduke    DescriptorIter end = m_arange_descriptors.end();
1090Sduke    DescriptorIter pos = lower_bound(m_arange_descriptors.begin(), end, range, DescriptorLessThan);
1100Sduke    const dw_addr_t range_end_addr = range.end_address();
1110Sduke    if (pos != end)
1120Sduke    {
1130Sduke        const dw_addr_t found_end_addr = pos->end_address();
1140Sduke        if (range.address < pos->address)
1150Sduke        {
1160Sduke            if (range_end_addr < pos->address)
1170Sduke            {
1180Sduke                // Non-contiguous entries, add this one before the found entry
1190Sduke                m_arange_descriptors.insert(pos, range);
1200Sduke            }
1210Sduke            else if (range_end_addr == pos->address)
1229248Scoleenp            {
1230Sduke                // The top end of 'range' is the lower end of the entry
1241138Stwisti                // pointed to by 'pos'. We can combine range with the
1251138Stwisti                // entry we found by setting the starting address and
1269248Scoleenp                // increasing the length since they don't overlap.
1271522Sjrose                pos->address = range.address;
1281138Stwisti                pos->length += range.length;
1290Sduke            }
1300Sduke            else
1319248Scoleenp            {
1321138Stwisti                // We can combine these two and make sure the largest end
1331138Stwisti                // address is used to make end address.
1340Sduke                pos->address = range.address;
1350Sduke                pos->length = std::max(found_end_addr, range_end_addr) - pos->address;
1360Sduke            }
1379248Scoleenp        }
1380Sduke        else if (range.address == pos->address)
1390Sduke        {
1409248Scoleenp            pos->length = std::max(pos->length, range.length);
1410Sduke        }
1421138Stwisti    }
1431138Stwisti    else
1449248Scoleenp    {
1451522Sjrose        // NOTE: 'pos' points to entry past the end which is ok for insert,
1461138Stwisti        // don't use otherwise!!!
1470Sduke        const dw_addr_t max_addr = m_arange_descriptors.back().end_address();
1480Sduke        if (max_addr < range.address)
1499248Scoleenp        {
1501138Stwisti            // Non-contiguous entries, add this one before the found entry
1511138Stwisti            m_arange_descriptors.insert(pos, range);
1520Sduke        }
1530Sduke        else if (max_addr == range.address)
1540Sduke        {
1553602Scoleenp            m_arange_descriptors.back().length += range.length;
15612623Sjcm        }
15712623Sjcm        else
15812623Sjcm        {
15912623Sjcm            m_arange_descriptors.back().length = std::max(max_addr, range_end_addr) - m_arange_descriptors.back().address;
16012623Sjcm        }
16112623Sjcm    }
1620Sduke}
1630Sduke
1640Sdukebool
1650SdukeDWARFDebugArangeSet::Extract(const DataExtractor &data, lldb::offset_t *offset_ptr)
1660Sduke{
1670Sduke    if (data.ValidOffset(*offset_ptr))
1680Sduke    {
1690Sduke        m_arange_descriptors.clear();
1700Sduke        m_offset = *offset_ptr;
1710Sduke
1720Sduke        // 7.20 Address Range Table
1732062Scoleenp        //
1742062Scoleenp        // Each set of entries in the table of address ranges contained in
1752062Scoleenp        // the .debug_aranges section begins with a header consisting of: a
1762062Scoleenp        // 4-byte length containing the length of the set of entries for this
1772062Scoleenp        // compilation unit, not including the length field itself; a 2-byte
1782062Scoleenp        // version identifier containing the value 2 for DWARF Version 2; a
1792062Scoleenp        // 4-byte offset into the.debug_infosection; a 1-byte unsigned integer
1802062Scoleenp        // containing the size in bytes of an address (or the offset portion of
1812062Scoleenp        // an address for segmented addressing) on the target system; and a
1823602Scoleenp        // 1-byte unsigned integer containing the size in bytes of a segment
1833602Scoleenp        // descriptor on the target system. This header is followed by a series
1843602Scoleenp        // of tuples. Each tuple consists of an address and a length, each in
1853602Scoleenp        // the size appropriate for an address on the target architecture.
1863602Scoleenp        m_header.length     = data.GetU32(offset_ptr);
1873602Scoleenp        m_header.version    = data.GetU16(offset_ptr);
1883602Scoleenp        m_header.cu_offset  = data.GetU32(offset_ptr);
1893602Scoleenp        m_header.addr_size  = data.GetU8(offset_ptr);
1906707Sstefank        m_header.seg_size   = data.GetU8(offset_ptr);
1916707Sstefank
1926707Sstefank
1936707Sstefank        // The first tuple following the header in each set begins at an offset
1943602Scoleenp        // that is a multiple of the size of a single tuple (that is, twice the
1953602Scoleenp        // size of an address). The header is padded, if necessary, to the
1963602Scoleenp        // appropriate boundary.
1973602Scoleenp        const uint32_t header_size = *offset_ptr - m_offset;
1983602Scoleenp        const uint32_t tuple_size = m_header.addr_size << 1;
1993602Scoleenp        uint32_t first_tuple_offset = 0;
2003602Scoleenp        while (first_tuple_offset < header_size)
2013602Scoleenp            first_tuple_offset += tuple_size;
2023602Scoleenp
2033602Scoleenp        *offset_ptr = m_offset + first_tuple_offset;
2043602Scoleenp
2053602Scoleenp        Descriptor arangeDescriptor;
2063602Scoleenp
2073602Scoleenp        assert(sizeof(arangeDescriptor.address) == sizeof(arangeDescriptor.length));
2083602Scoleenp        assert(sizeof(arangeDescriptor.address) >= m_header.addr_size);
2093602Scoleenp
2103602Scoleenp        while (data.ValidOffset(*offset_ptr))
2113602Scoleenp        {
2123602Scoleenp            arangeDescriptor.address    = data.GetMaxU64(offset_ptr, m_header.addr_size);
2133602Scoleenp            arangeDescriptor.length     = data.GetMaxU64(offset_ptr, m_header.addr_size);
2143602Scoleenp
2153602Scoleenp            // Each set of tuples is terminated by a 0 for the address and 0
2163602Scoleenp            // for the length.
2173602Scoleenp            if (arangeDescriptor.address || arangeDescriptor.length)
2183602Scoleenp                m_arange_descriptors.push_back(arangeDescriptor);
2193602Scoleenp            else
2203602Scoleenp                break;  // We are done if we get a zero address and length
2213602Scoleenp        }
2223602Scoleenp
2233602Scoleenp        return !m_arange_descriptors.empty();
2240Sduke    }
2252062Scoleenp    return false;
2260Sduke}
2270Sduke
2280Sduke
2290Sdukedw_offset_t
23012623SjcmDWARFDebugArangeSet::GetOffsetOfNextEntry() const
2310Sduke{
2322762Stwisti    return m_offset + m_header.length + 4;
2332762Stwisti}
23412623Sjcm
23512623Sjcm
2360Sdukevoid
2370SdukeDWARFDebugArangeSet::Dump(Stream *s) const
2380Sduke{
2390Sduke    s->Printf("Address Range Header: length = 0x%8.8x, version = 0x%4.4x, cu_offset = 0x%8.8x, addr_size = 0x%2.2x, seg_size = 0x%2.2x\n",
2402762Stwisti        m_header.length ,m_header.version, m_header.cu_offset, m_header.addr_size, m_header.seg_size);
2410Sduke
2420Sduke    const uint32_t hex_width = m_header.addr_size * 2;
2430Sduke    DescriptorConstIter pos;
2440Sduke    DescriptorConstIter end = m_arange_descriptors.end();
2451522Sjrose    for (pos = m_arange_descriptors.begin(); pos != end; ++pos)
2461522Sjrose        s->Printf("[0x%*.*" PRIx64 " - 0x%*.*" PRIx64 ")\n",
2471522Sjrose            hex_width, hex_width, pos->address,
2481522Sjrose            hex_width, hex_width, pos->end_address());
2491522Sjrose}
2501522Sjrose
2511522Sjrose
2521522Sjroseclass DescriptorContainsAddress
2531522Sjrose{
2541522Sjrosepublic:
2551522Sjrose    DescriptorContainsAddress (dw_addr_t address) : m_address(address) {}
2561522Sjrose    bool operator() (const DWARFDebugArangeSet::Descriptor& desc) const
2571522Sjrose    {
2581522Sjrose        return (m_address >= desc.address) && (m_address < (desc.address + desc.length));
2591522Sjrose    }
2601522Sjrose private:
2611522Sjrose   const dw_addr_t m_address;
2621522Sjrose};
2631522Sjrose
2640Sdukedw_offset_t
2650SdukeDWARFDebugArangeSet::FindAddress(dw_addr_t address) const
2662762Stwisti{
2670Sduke    DescriptorConstIter end = m_arange_descriptors.end();
2680Sduke    DescriptorConstIter pos = std::find_if( m_arange_descriptors.begin(), end,  // Range
2690Sduke                                            DescriptorContainsAddress(address));// Predicate
2700Sduke    if (pos != end)
2710Sduke        return m_header.cu_offset;
2720Sduke
2730Sduke    return DW_INVALID_OFFSET;
2740Sduke}
2750Sduke