DWARFDebugRanges.cpp revision 341825
1254721Semaste//===-- DWARFDebugRanges.cpp ------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "DWARFDebugRanges.h"
11254721Semaste#include "SymbolFileDWARF.h"
12321369Sdim#include "lldb/Utility/Stream.h"
13254721Semaste#include <assert.h>
14254721Semaste
15254721Semasteusing namespace lldb_private;
16254721Semasteusing namespace std;
17254721Semaste
18327952Sdimstatic dw_addr_t GetBaseAddressMarker(uint32_t addr_size) {
19327952Sdim  switch(addr_size) {
20327952Sdim    case 2:
21327952Sdim      return 0xffff;
22327952Sdim    case 4:
23327952Sdim      return 0xffffffff;
24327952Sdim    case 8:
25327952Sdim      return 0xffffffffffffffff;
26327952Sdim  }
27327952Sdim  llvm_unreachable("GetBaseAddressMarker unsupported address size.");
28327952Sdim}
29327952Sdim
30314564SdimDWARFDebugRanges::DWARFDebugRanges() : m_range_map() {}
31254721Semaste
32314564SdimDWARFDebugRanges::~DWARFDebugRanges() {}
33254721Semaste
34314564Sdimvoid DWARFDebugRanges::Extract(SymbolFileDWARF *dwarf2Data) {
35314564Sdim  DWARFRangeList range_list;
36314564Sdim  lldb::offset_t offset = 0;
37314564Sdim  dw_offset_t debug_ranges_offset = offset;
38314564Sdim  while (Extract(dwarf2Data, &offset, range_list)) {
39314564Sdim    range_list.Sort();
40314564Sdim    m_range_map[debug_ranges_offset] = range_list;
41314564Sdim    debug_ranges_offset = offset;
42314564Sdim  }
43254721Semaste}
44254721Semaste
45314564Sdimbool DWARFDebugRanges::Extract(SymbolFileDWARF *dwarf2Data,
46314564Sdim                               lldb::offset_t *offset_ptr,
47314564Sdim                               DWARFRangeList &range_list) {
48314564Sdim  range_list.Clear();
49254721Semaste
50314564Sdim  lldb::offset_t range_offset = *offset_ptr;
51314564Sdim  const DWARFDataExtractor &debug_ranges_data =
52314564Sdim      dwarf2Data->get_debug_ranges_data();
53314564Sdim  uint32_t addr_size = debug_ranges_data.GetAddressByteSize();
54327952Sdim  dw_addr_t base_addr = 0;
55327952Sdim  dw_addr_t base_addr_marker = GetBaseAddressMarker(addr_size);
56254721Semaste
57314564Sdim  while (
58314564Sdim      debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) {
59314564Sdim    dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
60314564Sdim    dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
61327952Sdim
62314564Sdim    if (!begin && !end) {
63314564Sdim      // End of range list
64314564Sdim      break;
65314564Sdim    }
66254721Semaste
67327952Sdim    if (begin == base_addr_marker) {
68327952Sdim      base_addr = end;
69327952Sdim      continue;
70254721Semaste    }
71254721Semaste
72314564Sdim    // Filter out empty ranges
73314564Sdim    if (begin < end)
74327952Sdim      range_list.Append(DWARFRangeList::Entry(begin + base_addr, end - begin));
75314564Sdim  }
76314564Sdim
77314564Sdim  // Make sure we consumed at least something
78314564Sdim  return range_offset != *offset_ptr;
79254721Semaste}
80254721Semaste
81314564Sdimvoid DWARFDebugRanges::Dump(Stream &s,
82314564Sdim                            const DWARFDataExtractor &debug_ranges_data,
83314564Sdim                            lldb::offset_t *offset_ptr,
84314564Sdim                            dw_addr_t cu_base_addr) {
85314564Sdim  uint32_t addr_size = s.GetAddressByteSize();
86254721Semaste
87314564Sdim  dw_addr_t base_addr = cu_base_addr;
88314564Sdim  while (
89314564Sdim      debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) {
90314564Sdim    dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
91314564Sdim    dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
92341825Sdim    // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits of
93341825Sdim    // ones
94314564Sdim    if (begin == 0xFFFFFFFFull && addr_size == 4)
95314564Sdim      begin = LLDB_INVALID_ADDRESS;
96254721Semaste
97314564Sdim    s.Indent();
98314564Sdim    if (begin == 0 && end == 0) {
99314564Sdim      s.PutCString(" End");
100314564Sdim      break;
101314564Sdim    } else if (begin == LLDB_INVALID_ADDRESS) {
102314564Sdim      // A base address selection entry
103314564Sdim      base_addr = end;
104314564Sdim      s.Address(base_addr, sizeof(dw_addr_t), " Base address = ");
105314564Sdim    } else {
106314564Sdim      // Convert from offset to an address
107314564Sdim      dw_addr_t begin_addr = begin + base_addr;
108314564Sdim      dw_addr_t end_addr = end + base_addr;
109254721Semaste
110321369Sdim      s.AddressRange(begin_addr, end_addr, sizeof(dw_addr_t), NULL);
111254721Semaste    }
112314564Sdim  }
113254721Semaste}
114254721Semaste
115314564Sdimbool DWARFDebugRanges::FindRanges(dw_addr_t debug_ranges_base,
116314564Sdim                                  dw_offset_t debug_ranges_offset,
117314564Sdim                                  DWARFRangeList &range_list) const {
118314564Sdim  dw_addr_t debug_ranges_address = debug_ranges_base + debug_ranges_offset;
119314564Sdim  range_map_const_iterator pos = m_range_map.find(debug_ranges_address);
120314564Sdim  if (pos != m_range_map.end()) {
121314564Sdim    range_list = pos->second;
122314564Sdim    return true;
123314564Sdim  }
124314564Sdim  return false;
125254721Semaste}
126