DWARFDebugArangeSet.cpp revision 258054
14374Slars//===-- DWARFDebugArangeSet.cpp ---------------------------------*- C++ -*-===// 24374Slars// 350477Speter// The LLVM Compiler Infrastructure 44374Slars// 54374Slars// This file is distributed under the University of Illinois Open Source 64374Slars// License. See LICENSE.TXT for details. 74374Slars// 84374Slars//===----------------------------------------------------------------------===// 934766Speter 104374Slars#include "DWARFDebugArangeSet.h" 114374Slars 124374Slars#include <assert.h> 134374Slars#include "lldb/Core/Stream.h" 144374Slars#include "SymbolFileDWARF.h" 154374Slars 164374Slarsusing namespace lldb_private; 174374Slars 184374SlarsDWARFDebugArangeSet::DWARFDebugArangeSet() : 194374Slars m_offset(DW_INVALID_OFFSET), 204374Slars m_header(), 2157670Ssheldonh m_arange_descriptors() 2257670Ssheldonh{ 234374Slars m_header.length = 0; 244374Slars m_header.version = 0; 254374Slars m_header.cu_offset = 0; 264374Slars m_header.addr_size = 0; 274374Slars m_header.seg_size = 0; 2857670Ssheldonh} 2957670Ssheldonh 3057670Ssheldonhvoid 3157670SsheldonhDWARFDebugArangeSet::Clear() 3257670Ssheldonh{ 3357670Ssheldonh m_offset = DW_INVALID_OFFSET; 3457670Ssheldonh m_header.length = 0; 3557670Ssheldonh m_header.version = 0; 364374Slars m_header.cu_offset = 0; 374374Slars m_header.addr_size = 0; 384374Slars m_header.seg_size = 0; 3957670Ssheldonh m_arange_descriptors.clear(); 4057670Ssheldonh} 414374Slars 4257670Ssheldonhvoid 4357670SsheldonhDWARFDebugArangeSet::SetHeader 4457670Ssheldonh( 4557670Ssheldonh uint16_t version, 464374Slars uint32_t cu_offset, 474374Slars uint8_t addr_size, 4811990Speter uint8_t seg_size 4957670Ssheldonh) 5057670Ssheldonh{ 5157670Ssheldonh m_header.version = version; 5257670Ssheldonh m_header.cu_offset = cu_offset; 5311990Speter m_header.addr_size = addr_size; 5411990Speter m_header.seg_size = seg_size; 5511990Speter} 5628597Speter 5757670Ssheldonhvoid 5857670SsheldonhDWARFDebugArangeSet::Compact() 5928597Speter{ 6057670Ssheldonh if (m_arange_descriptors.empty()) 6157670Ssheldonh return; 6228597Speter 6328597Speter // Iterate through all arange descriptors and combine any ranges that 644374Slars // overlap or have matching boundaries. The m_arange_descriptors are assumed 6557670Ssheldonh // to be in ascending order after being built by adding descriptors 6657670Ssheldonh // using the AddDescriptor method. 6734766Speter uint32_t i = 0; 6834766Speter while (i + 1 < m_arange_descriptors.size()) 6934766Speter { 7034766Speter if (m_arange_descriptors[i].end_address() >= m_arange_descriptors[i+1].address) 7134766Speter { 7216935Smpp // The current range ends at or exceeds the start of the next address range. 7316935Smpp // Compute the max end address between the two and use that to make the new 7416935Smpp // length. 754374Slars const dw_addr_t max_end_addr = std::max(m_arange_descriptors[i].end_address(), m_arange_descriptors[i+1].end_address()); 7628597Speter m_arange_descriptors[i].length = max_end_addr - m_arange_descriptors[i].address; 7728597Speter // Now remove the next entry as it was just combined with the previous one. 7857670Ssheldonh m_arange_descriptors.erase(m_arange_descriptors.begin()+i+1); 7957670Ssheldonh } 8057670Ssheldonh else 8157670Ssheldonh { 8228597Speter // Discontiguous address range, just proceed to the next one. 8337126Speter ++i; 8428597Speter } 8534766Speter } 8634766Speter} 8734766Speter//---------------------------------------------------------------------- 8834766Speter// Compare function DWARFDebugArangeSet::Descriptor structures 8934766Speter//---------------------------------------------------------------------- 9034766Speterstatic bool DescriptorLessThan (const DWARFDebugArangeSet::Descriptor& range1, const DWARFDebugArangeSet::Descriptor& range2) 9134766Speter{ 9234766Speter return range1.address < range2.address; 9334766Speter} 9434766Speter 9534766Speter//---------------------------------------------------------------------- 9634766Speter// Add a range descriptor and keep things sorted so we can easily 9734766Speter// compact the ranges before being saved or used. 9834766Speter//---------------------------------------------------------------------- 9936601Sjkoshyvoid 10034766SpeterDWARFDebugArangeSet::AddDescriptor(const DWARFDebugArangeSet::Descriptor& range) 10134766Speter{ 10234766Speter if (m_arange_descriptors.empty()) 10334766Speter { 10434766Speter m_arange_descriptors.push_back(range); 10579755Sdd return; 10634766Speter } 10734766Speter 1084374Slars DescriptorIter end = m_arange_descriptors.end(); 1094374Slars DescriptorIter pos = lower_bound(m_arange_descriptors.begin(), end, range, DescriptorLessThan); 1104374Slars const dw_addr_t range_end_addr = range.end_address(); 1114374Slars if (pos != end) 1124374Slars { 1134374Slars const dw_addr_t found_end_addr = pos->end_address(); 1144374Slars if (range.address < pos->address) 1154374Slars { 1164374Slars if (range_end_addr < pos->address) 1174374Slars { 1184374Slars // Non-contiguous entries, add this one before the found entry 1194374Slars m_arange_descriptors.insert(pos, range); 1204374Slars } 1214374Slars else if (range_end_addr == pos->address) 1224374Slars { 1234374Slars // The top end of 'range' is the lower end of the entry 1244374Slars // pointed to by 'pos'. We can combine range with the 1254374Slars // entry we found by setting the starting address and 1264374Slars // increasing the length since they don't overlap. 12711990Speter pos->address = range.address; 12811990Speter pos->length += range.length; 12911990Speter } 1304374Slars else 13157670Ssheldonh { 13257670Ssheldonh // We can combine these two and make sure the largest end 1334374Slars // address is used to make end address. 1344374Slars pos->address = range.address; 1354374Slars pos->length = std::max(found_end_addr, range_end_addr) - pos->address; 1364374Slars } 13757670Ssheldonh } 13857670Ssheldonh else if (range.address == pos->address) 13957670Ssheldonh { 14057670Ssheldonh pos->length = std::max(pos->length, range.length); 1414374Slars } 1424374Slars } 1434374Slars else 1444374Slars { 1454374Slars // NOTE: 'pos' points to entry past the end which is ok for insert, 1464374Slars // don't use otherwise!!! 14757670Ssheldonh const dw_addr_t max_addr = m_arange_descriptors.back().end_address(); 14857670Ssheldonh if (max_addr < range.address) 1494374Slars { 1504374Slars // Non-contiguous entries, add this one before the found entry 1514374Slars m_arange_descriptors.insert(pos, range); 1524374Slars } 1534374Slars else if (max_addr == range.address) 1544374Slars { 1554374Slars m_arange_descriptors.back().length += range.length; 1564374Slars } 1574374Slars else 15857670Ssheldonh { 15957670Ssheldonh m_arange_descriptors.back().length = std::max(max_addr, range_end_addr) - m_arange_descriptors.back().address; 1604374Slars } 16157670Ssheldonh } 16257670Ssheldonh} 1634374Slars 16420510Salexbool 1654374SlarsDWARFDebugArangeSet::Extract(const DWARFDataExtractor &data, lldb::offset_t *offset_ptr) 16657670Ssheldonh{ 16757670Ssheldonh if (data.ValidOffset(*offset_ptr)) 1684374Slars { 16957670Ssheldonh m_arange_descriptors.clear(); 17057670Ssheldonh m_offset = *offset_ptr; 1714374Slars 1724374Slars // 7.20 Address Range Table 17328597Speter // 17457670Ssheldonh // Each set of entries in the table of address ranges contained in 17557670Ssheldonh // the .debug_aranges section begins with a header consisting of: a 17628597Speter // 4-byte length containing the length of the set of entries for this 17757670Ssheldonh // compilation unit, not including the length field itself; a 2-byte 17857670Ssheldonh // version identifier containing the value 2 for DWARF Version 2; a 17928597Speter // 4-byte offset into the.debug_infosection; a 1-byte unsigned integer 18028597Speter // containing the size in bytes of an address (or the offset portion of 18128597Speter // an address for segmented addressing) on the target system; and a 18228597Speter // 1-byte unsigned integer containing the size in bytes of a segment 18328597Speter // descriptor on the target system. This header is followed by a series 18428597Speter // of tuples. Each tuple consists of an address and a length, each in 18528597Speter // the size appropriate for an address on the target architecture. 186100532Strhodes m_header.length = data.GetDWARFInitialLength(offset_ptr); 18728597Speter m_header.version = data.GetU16(offset_ptr); 18828597Speter m_header.cu_offset = data.GetDWARFOffset(offset_ptr); 1894374Slars m_header.addr_size = data.GetU8(offset_ptr); 19057670Ssheldonh m_header.seg_size = data.GetU8(offset_ptr); 19157670Ssheldonh 19257670Ssheldonh 19357670Ssheldonh // The first tuple following the header in each set begins at an offset 1944374Slars // that is a multiple of the size of a single tuple (that is, twice the 19557670Ssheldonh // size of an address). The header is padded, if necessary, to the 19657670Ssheldonh // appropriate boundary. 19757670Ssheldonh const uint32_t header_size = *offset_ptr - m_offset; 19857670Ssheldonh const uint32_t tuple_size = m_header.addr_size << 1; 1994374Slars uint32_t first_tuple_offset = 0; 2004374Slars while (first_tuple_offset < header_size) 2014374Slars first_tuple_offset += tuple_size; 20257670Ssheldonh 20357670Ssheldonh *offset_ptr = m_offset + first_tuple_offset; 2044374Slars 2054374Slars Descriptor arangeDescriptor; 2064374Slars 20757670Ssheldonh assert(sizeof(arangeDescriptor.address) == sizeof(arangeDescriptor.length)); 20857670Ssheldonh assert(sizeof(arangeDescriptor.address) >= m_header.addr_size); 20957670Ssheldonh 21057670Ssheldonh while (data.ValidOffset(*offset_ptr)) 21157670Ssheldonh { 21257670Ssheldonh arangeDescriptor.address = data.GetMaxU64(offset_ptr, m_header.addr_size); 21357670Ssheldonh arangeDescriptor.length = data.GetMaxU64(offset_ptr, m_header.addr_size); 21457670Ssheldonh 21557670Ssheldonh // Each set of tuples is terminated by a 0 for the address and 0 21657670Ssheldonh // for the length. 21757670Ssheldonh if (arangeDescriptor.address || arangeDescriptor.length) 21857670Ssheldonh m_arange_descriptors.push_back(arangeDescriptor); 21957670Ssheldonh else 22057670Ssheldonh break; // We are done if we get a zero address and length 22157670Ssheldonh } 22257670Ssheldonh 22357695Ssheldonh return !m_arange_descriptors.empty(); 22457695Ssheldonh } 22557670Ssheldonh return false; 2264374Slars} 22728597Speter 22828597Speter 22928597Speterdw_offset_t 23028597SpeterDWARFDebugArangeSet::GetOffsetOfNextEntry() const 23128597Speter{ 23228597Speter return m_offset + m_header.length + 4; 23328597Speter} 23428597Speter 23528597Speter 23628597Spetervoid 23728597SpeterDWARFDebugArangeSet::Dump(Stream *s) const 23828597Speter{ 23957670Ssheldonh 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", 24057670Ssheldonh m_header.length ,m_header.version, m_header.cu_offset, m_header.addr_size, m_header.seg_size); 24128597Speter 24236601Sjkoshy const uint32_t hex_width = m_header.addr_size * 2; 24328597Speter DescriptorConstIter pos; 24428597Speter DescriptorConstIter end = m_arange_descriptors.end(); 24528597Speter for (pos = m_arange_descriptors.begin(); pos != end; ++pos) 24628597Speter s->Printf("[0x%*.*" PRIx64 " - 0x%*.*" PRIx64 ")\n", 24728597Speter hex_width, hex_width, pos->address, 24879755Sdd hex_width, hex_width, pos->end_address()); 24928597Speter} 25079755Sdd 25128597Speter 25279755Sddclass DescriptorContainsAddress 25328597Speter{ 254100532Strhodespublic: 25528597Speter DescriptorContainsAddress (dw_addr_t address) : m_address(address) {} 25628597Speter bool operator() (const DWARFDebugArangeSet::Descriptor& desc) const 25728597Speter { 25828597Speter return (m_address >= desc.address) && (m_address < (desc.address + desc.length)); 25928597Speter } 26079755Sdd private: 26128597Speter const dw_addr_t m_address; 262100532Strhodes}; 26328597Speter 26428597Speterdw_offset_t 26528597SpeterDWARFDebugArangeSet::FindAddress(dw_addr_t address) const 26628597Speter{ 26728597Speter DescriptorConstIter end = m_arange_descriptors.end(); 26828597Speter DescriptorConstIter pos = std::find_if( m_arange_descriptors.begin(), end, // Range 269100532Strhodes DescriptorContainsAddress(address));// Predicate 27028597Speter if (pos != end) 27128597Speter return m_header.cu_offset; 27228597Speter 27357670Ssheldonh return DW_INVALID_OFFSET; 27457670Ssheldonh} 27528597Speter