llvm.org GIT mirror llvm / eceb5b9
Add basic support for .debug_ranges section to LLVM's DebugInfo library. This section (introduced in DWARF-3) is used to define instruction address ranges for functions that are not contiguous and can't be described by low_pc/high_pc attributes (this is the usual case for inlined subroutines). The patch is the first step to support fetching complete inlining info from DWARF. Reviewed by Benjamin Kramer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162657 91177308-0d34-0410-b5e6-96231b3b80d8 Alexey Samsonov 7 years ago
8 changed file(s) with 153 addition(s) and 7 deletion(s). Raw diff Collapse all Expand all
8080 StringRef abbrevSection,
8181 StringRef aRangeSection = StringRef(),
8282 StringRef lineSection = StringRef(),
83 StringRef stringSection = StringRef());
83 StringRef stringSection = StringRef(),
84 StringRef rangeSection = StringRef());
8485
8586 virtual void dump(raw_ostream &OS) = 0;
8687
1717 StringRef abbrevSection,
1818 StringRef aRangeSection,
1919 StringRef lineSection,
20 StringRef stringSection) {
20 StringRef stringSection,
21 StringRef rangeSection) {
2122 return new DWARFContextInMemory(isLittleEndian, infoSection, abbrevSection,
22 aRangeSection, lineSection, stringSection);
23 aRangeSection, lineSection, stringSection,
24 rangeSection);
2325 }
3131 while (set.extract(arangesData, &offset))
3232 set.dump(OS);
3333
34 uint8_t savedAddressByteSize = 0;
3435 OS << "\n.debug_lines contents:\n";
3536 for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) {
3637 DWARFCompileUnit *cu = getCompileUnitAtIndex(i);
38 savedAddressByteSize = cu->getAddressByteSize();
3739 unsigned stmtOffset =
3840 cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
3941 -1U);
4042 if (stmtOffset != -1U) {
4143 DataExtractor lineData(getLineSection(), isLittleEndian(),
42 cu->getAddressByteSize());
44 savedAddressByteSize);
4345 DWARFDebugLine::DumpingState state(OS);
4446 DWARFDebugLine::parseStatementTable(lineData, &stmtOffset, state);
4547 }
5355 OS << format("0x%8.8x: \"%s\"\n", lastOffset, s);
5456 lastOffset = offset;
5557 }
58
59 OS << "\n.debug_ranges contents:\n";
60 // In fact, different compile units may have different address byte
61 // sizes, but for simplicity we just use the address byte size of the last
62 // compile unit (there is no easy and fast way to associate address range
63 // list and the compile unit it describes).
64 DataExtractor rangesData(getRangeSection(), isLittleEndian(),
65 savedAddressByteSize);
66 offset = 0;
67 DWARFDebugRangeList rangeList;
68 while (rangeList.extract(rangesData, &offset))
69 rangeList.dump(OS);
5670 }
5771
5872 const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
1212 #include "DWARFCompileUnit.h"
1313 #include "DWARFDebugAranges.h"
1414 #include "DWARFDebugLine.h"
15 #include "DWARFDebugRangeList.h"
1516 #include "llvm/DebugInfo/DIContext.h"
1617 #include "llvm/ADT/OwningPtr.h"
1718 #include "llvm/ADT/SmallVector.h"
7576 virtual StringRef getARangeSection() = 0;
7677 virtual StringRef getLineSection() = 0;
7778 virtual StringRef getStringSection() = 0;
79 virtual StringRef getRangeSection() = 0;
7880
7981 static bool isSupportedVersion(unsigned version) {
8082 return version == 2 || version == 3;
9294 StringRef ARangeSection;
9395 StringRef LineSection;
9496 StringRef StringSection;
97 StringRef RangeSection;
9598 public:
9699 DWARFContextInMemory(bool isLittleEndian,
97100 StringRef infoSection,
98101 StringRef abbrevSection,
99102 StringRef aRangeSection,
100103 StringRef lineSection,
101 StringRef stringSection)
104 StringRef stringSection,
105 StringRef rangeSection)
102106 : DWARFContext(isLittleEndian),
103107 InfoSection(infoSection),
104108 AbbrevSection(abbrevSection),
105109 ARangeSection(aRangeSection),
106110 LineSection(lineSection),
107 StringSection(stringSection)
111 StringSection(stringSection),
112 RangeSection(rangeSection)
108113 {}
109114
110115 virtual StringRef getInfoSection() { return InfoSection; }
112117 virtual StringRef getARangeSection() { return ARangeSection; }
113118 virtual StringRef getLineSection() { return LineSection; }
114119 virtual StringRef getStringSection() { return StringSection; }
120 virtual StringRef getRangeSection() { return RangeSection; }
115121 };
116122
117123 }
0 //===-- DWARFDebugRangesList.cpp ------------------------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "DWARFDebugRangeList.h"
10 #include "llvm/Support/Format.h"
11 #include "llvm/Support/raw_ostream.h"
12
13 using namespace llvm;
14
15 void DWARFDebugRangeList::clear() {
16 Offset = -1U;
17 AddressSize = 0;
18 Entries.clear();
19 }
20
21 bool DWARFDebugRangeList::extract(DataExtractor data, uint32_t *offset_ptr) {
22 clear();
23 if (!data.isValidOffset(*offset_ptr))
24 return false;
25 AddressSize = data.getAddressSize();
26 if (AddressSize != 4 && AddressSize != 8)
27 return false;
28 Offset = *offset_ptr;
29 while (true) {
30 RangeListEntry entry;
31 uint32_t prev_offset = *offset_ptr;
32 entry.StartAddress = data.getAddress(offset_ptr);
33 entry.EndAddress = data.getAddress(offset_ptr);
34 // Check that both values were extracted correctly.
35 if (*offset_ptr != prev_offset + 2 * AddressSize) {
36 clear();
37 return false;
38 }
39 // The end of any given range list is marked by an end of list entry,
40 // which consists of a 0 for the beginning address offset
41 // and a 0 for the ending address offset.
42 if (entry.StartAddress == 0 && entry.EndAddress == 0)
43 break;
44 Entries.push_back(entry);
45 }
46 return true;
47 }
48
49 void DWARFDebugRangeList::dump(raw_ostream &OS) const {
50 for (int i = 0, n = Entries.size(); i != n; ++i) {
51 const char *format_str = (AddressSize == 4) ? "%08x %08x %08x\n"
52 : "%08x %016x %016x\n";
53 OS << format(format_str, Offset, Entries[i].StartAddress,
54 Entries[i].EndAddress);
55 }
56 OS << format("%08x \n", Offset);
57 }
0 //===-- DWARFDebugRangeList.h -----------------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_DEBUGINFO_DWARFDEBUGRANGELIST_H
10 #define LLVM_DEBUGINFO_DWARFDEBUGRANGELIST_H
11
12 #include "llvm/Support/DataExtractor.h"
13 #include
14
15 namespace llvm {
16
17 class raw_ostream;
18
19 class DWARFDebugRangeList {
20 public:
21 struct RangeListEntry {
22 // A beginning address offset. This address offset has the size of an
23 // address and is relative to the applicable base address of the
24 // compilation unit referencing this range list. It marks the beginning
25 // of an address range.
26 uint64_t StartAddress;
27 // An ending address offset. This address offset again has the size of
28 // an address and is relative to the applicable base address of the
29 // compilation unit referencing this range list. It marks the first
30 // address past the end of the address range. The ending address must
31 // be greater than or equal to the beginning address.
32 uint64_t EndAddress;
33 };
34
35 private:
36 // Offset in .debug_ranges section.
37 uint32_t Offset;
38 uint8_t AddressSize;
39 std::vector Entries;
40
41 public:
42 DWARFDebugRangeList() { clear(); }
43 void clear();
44 void dump(raw_ostream &OS) const;
45 bool extract(DataExtractor data, uint32_t *offset_ptr);
46 };
47
48 } // namespace llvm
49
50 #endif // LLVM_DEBUGINFO_DWARFDEBUGRANGELIST_H
1616 RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test4.elf-x86-64 \
1717 RUN: --address=0x55c --functions \
1818 RUN: | FileCheck %s -check-prefix MANY_SEQ_IN_LINE_TABLE
19 RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test4.elf-x86-64 \
20 RUN: | FileCheck %s -check-prefix DEBUG_RANGES
1921
2022 MAIN: main
2123 MAIN-NEXT: /tmp/dbginfo{{[/\\]}}dwarfdump-test.cc:16:10
4345
4446 MANY_SEQ_IN_LINE_TABLE: _Z1cv
4547 MANY_SEQ_IN_LINE_TABLE-NEXT: /tmp/dbginfo/sequences{{[/\\]}}c.cc:2:0
48
49 DEBUG_RANGES: .debug_ranges contents:
50 DEBUG_RANGES-NEXT: 00000000 000000000000055c 0000000000000567
51 DEBUG_RANGES-NEXT: 00000000 0000000000000567 000000000000056d
52 DEBUG_RANGES-NEXT: 00000000
53 DEBUG_RANGES-NEXT: 00000030 0000000000000570 000000000000057b
54 DEBUG_RANGES-NEXT: 00000030 0000000000000567 000000000000056d
55 DEBUG_RANGES-NEXT: 00000030
5858 StringRef DebugLineSection;
5959 StringRef DebugArangesSection;
6060 StringRef DebugStringSection;
61 StringRef DebugRangesSection;
6162
6263 error_code ec;
6364 for (section_iterator i = Obj->begin_sections(),
8182 DebugArangesSection = data;
8283 else if (name == "debug_str")
8384 DebugStringSection = data;
85 else if (name == "debug_ranges")
86 DebugRangesSection = data;
8487 }
8588
8689 OwningPtr dictx(DIContext::getDWARFContext(/*FIXME*/true,
8891 DebugAbbrevSection,
8992 DebugArangesSection,
9093 DebugLineSection,
91 DebugStringSection));
94 DebugStringSection,
95 DebugRangesSection));
9296 if (Address == -1ULL) {
9397 outs() << Filename
9498 << ":\tfile format " << Obj->getFileFormatName() << "\n\n";