llvm.org GIT mirror llvm / 72c0d7f
Sketch out a DWARF parser. This introduces a new library to LLVM: libDebugInfo. It will provide debug information parsing to LLVM. Much of the design and some of the code is taken from the LLDB project. It also contains an llvm-dwarfdump tool that can dump the abbrevs and DIEs from an object file. It can be used to write tests for DWARF input and output easily. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139627 91177308-0d34-0410-b5e6-96231b3b80d8 Benjamin Kramer 8 years ago
24 changed file(s) with 2046 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
0 //===-- DIContext.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 // This file defines DIContext, and abstract data structure that holds
10 // debug information data.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_DEBUGINFO_DICONTEXT_H
15 #define LLVM_DEBUGINFO_DICONTEXT_H
16
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/DebugInfo/DILineInfo.h"
19
20 namespace llvm {
21
22 class raw_ostream;
23
24 class DIContext {
25 public:
26 virtual ~DIContext();
27
28 /// getDWARFContext - get a context for binary DWARF data.
29 static DIContext *getDWARFContext(bool isLittleEndian,
30 StringRef infoSection,
31 StringRef abbrevSection,
32 StringRef aRangeSection = StringRef(),
33 StringRef lineSection = StringRef(),
34 StringRef stringSection = StringRef());
35
36 virtual void dump(raw_ostream &OS) = 0;
37 };
38
39 }
40
41 #endif
88 add_subdirectory(MC)
99 add_subdirectory(CompilerDriver)
1010 add_subdirectory(Object)
11 add_subdirectory(DebugInfo)
1112 add_subdirectory(ExecutionEngine)
1213 add_subdirectory(Target)
1314 add_subdirectory(AsmParser)
0 add_llvm_library(LLVMMC
1 DIContext.cpp
2 DWARFAbbreviationDeclaration.cpp
3 DWARFCompileUnit.cpp
4 DWARFContext.cpp
5 DWARFDebugAbbrev.cpp
6 DWARFDebugInfoEntry.cpp
7 DWARFFormValue.cpp
8 )
9
10 add_llvm_library_dependencies(LLVMDebugInfo
11 LLVMSupport
12 )
0 //===-- DIContext.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 "llvm/DebugInfo/DIContext.h"
10 #include "DWARFContext.h"
11 using namespace llvm;
12
13 DIContext::~DIContext() {}
14
15 DIContext *DIContext::getDWARFContext(bool isLittleEndian,
16 StringRef infoSection,
17 StringRef abbrevSection,
18 StringRef aRangeSection,
19 StringRef lineSection,
20 StringRef stringSection) {
21 return new DWARFContextInMemory(isLittleEndian, infoSection, abbrevSection,
22 aRangeSection, lineSection, stringSection);
23 }
0 //===-- DWARFAbbreviationDeclaration.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 "DWARFAbbreviationDeclaration.h"
10 #include "llvm/Support/Dwarf.h"
11 #include "llvm/Support/raw_ostream.h"
12 using namespace llvm;
13 using namespace dwarf;
14
15 bool
16 DWARFAbbreviationDeclaration::extract(DataExtractor data, uint32_t* offset_ptr){
17 return extract(data, offset_ptr, data.getULEB128(offset_ptr));
18 }
19
20 bool
21 DWARFAbbreviationDeclaration::extract(DataExtractor data, uint32_t* offset_ptr,
22 uint32_t code) {
23 Code = code;
24 Attributes.clear();
25 if (Code) {
26 Tag = data.getULEB128(offset_ptr);
27 HasChildren = data.getU8(offset_ptr);
28
29 while (data.isValidOffset(*offset_ptr)) {
30 uint16_t attr = data.getULEB128(offset_ptr);
31 uint16_t form = data.getULEB128(offset_ptr);
32
33 if (attr && form)
34 Attributes.push_back(DWARFAttribute(attr, form));
35 else
36 break;
37 }
38
39 return Tag != 0;
40 }
41 else {
42 Tag = 0;
43 HasChildren = false;
44 }
45
46 return false;
47 }
48
49 void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const {
50 OS << '[' << getCode() << "] " << TagString(getTag()) << "\tDW_CHILDREN_"
51 << (hasChildren() ? "yes" : "no") << '\n';
52 for (unsigned i = 0, e = Attributes.size(); i != e; ++i)
53 OS << '\t' << AttributeString(Attributes[i].getAttribute())
54 << '\t' << FormEncodingString(Attributes[i].getForm()) << '\n';
55 OS << '\n';
56 }
57
58 uint32_t
59 DWARFAbbreviationDeclaration::findAttributeIndex(uint16_t attr) const {
60 for (uint32_t i = 0, e = Attributes.size(); i != e; ++i) {
61 if (Attributes[i].getAttribute() == attr)
62 return i;
63 }
64 return -1U;
65 }
0 //===-- DWARFAbbreviationDeclaration.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_DWARFABBREVIATIONDECLARATION_H
10 #define LLVM_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H
11
12 #include "DWARFAttribute.h"
13 #include "llvm/ADT/SmallVector.h"
14 #include "llvm/Support/DataExtractor.h"
15
16 namespace llvm {
17
18 class raw_ostream;
19
20 class DWARFAbbreviationDeclaration {
21 uint32_t Code;
22 uint32_t Tag;
23 bool HasChildren;
24 SmallVector Attributes;
25 public:
26 enum { InvalidCode = 0 };
27 DWARFAbbreviationDeclaration()
28 : Code(InvalidCode), Tag(0), HasChildren(0) {}
29
30 uint32_t getCode() const { return Code; }
31 uint32_t getTag() const { return Tag; }
32 bool hasChildren() const { return HasChildren; }
33 uint32_t getNumAttributes() const { return Attributes.size(); }
34 uint16_t getAttrByIndex(uint32_t idx) const {
35 return Attributes.size() > idx ? Attributes[idx].getAttribute() : 0;
36 }
37 uint16_t getFormByIndex(uint32_t idx) const {
38 return Attributes.size() > idx ? Attributes[idx].getForm() : 0;
39 }
40
41 uint32_t findAttributeIndex(uint16_t attr) const;
42 bool extract(DataExtractor data, uint32_t* offset_ptr);
43 bool extract(DataExtractor data, uint32_t* offset_ptr, uint32_t code);
44 bool isValid() const { return Code != 0 && Tag != 0; }
45 void dump(raw_ostream &OS) const;
46 const SmallVectorImpl &getAttributes() const {
47 return Attributes;
48 }
49 };
50
51 }
52
53 #endif
0 //===-- DWARFAttribute.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_DWARFATTRIBUTE_H
10 #define LLVM_DEBUGINFO_DWARFATTRIBUTE_H
11
12 #include "llvm/Support/DataTypes.h"
13
14 namespace llvm {
15
16 class DWARFAttribute {
17 uint16_t Attribute;
18 uint16_t Form;
19 public:
20 DWARFAttribute(uint16_t attr, uint16_t form)
21 : Attribute(attr), Form(form) {}
22
23 uint16_t getAttribute() const { return Attribute; }
24 uint16_t getForm() const { return Form; }
25 };
26
27 }
28
29 #endif
0 //===-- DWARFCompileUnit.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 "DWARFCompileUnit.h"
10 #include "DWARFContext.h"
11 #include "DWARFFormValue.h"
12 #include "llvm/Support/Dwarf.h"
13 #include "llvm/Support/Format.h"
14 #include "llvm/Support/raw_ostream.h"
15 using namespace llvm;
16 using namespace dwarf;
17
18 DataExtractor DWARFCompileUnit::getDebugInfoExtractor() const {
19 return DataExtractor(Context.getInfoSection(),
20 Context.isLittleEndian(), getAddressByteSize());
21 }
22
23 bool DWARFCompileUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) {
24 clear();
25
26 Offset = *offset_ptr;
27
28 if (debug_info.isValidOffset(*offset_ptr)) {
29 uint64_t abbrOffset;
30 const DWARFDebugAbbrev *abbr = Context.getDebugAbbrev();
31 Length = debug_info.getU32(offset_ptr);
32 Version = debug_info.getU16(offset_ptr);
33 abbrOffset = debug_info.getU32(offset_ptr);
34 AddrSize = debug_info.getU8(offset_ptr);
35
36 bool lengthOK = debug_info.isValidOffset(getNextCompileUnitOffset()-1);
37 bool versionOK = DWARFContext::isSupportedVersion(Version);
38 bool abbrOffsetOK = Context.getAbbrevSection().size() > abbrOffset;
39 bool addrSizeOK = AddrSize == 4 || AddrSize == 8;
40
41 if (lengthOK && versionOK && addrSizeOK && abbrOffsetOK && abbr != NULL) {
42 Abbrevs = abbr->getAbbreviationDeclarationSet(abbrOffset);
43 return true;
44 }
45
46 // reset the offset to where we tried to parse from if anything went wrong
47 *offset_ptr = Offset;
48 }
49
50 return false;
51 }
52
53 uint32_t
54 DWARFCompileUnit::extract(uint32_t offset, DataExtractor debug_info_data,
55 const DWARFAbbreviationDeclarationSet *abbrevs) {
56 clear();
57
58 Offset = offset;
59
60 if (debug_info_data.isValidOffset(offset)) {
61 Length = debug_info_data.getU32(&offset);
62 Version = debug_info_data.getU16(&offset);
63 bool abbrevsOK = debug_info_data.getU32(&offset) == abbrevs->getOffset();
64 Abbrevs = abbrevs;
65 AddrSize = debug_info_data.getU8 (&offset);
66
67 bool versionOK = DWARFContext::isSupportedVersion(Version);
68 bool addrSizeOK = AddrSize == 4 || AddrSize == 8;
69
70 if (versionOK && addrSizeOK && abbrevsOK &&
71 debug_info_data.isValidOffset(offset))
72 return offset;
73 }
74 return 0;
75 }
76
77 void DWARFCompileUnit::clear() {
78 Offset = 0;
79 Length = 0;
80 Version = 0;
81 Abbrevs = 0;
82 AddrSize = 0;
83 BaseAddr = 0;
84 DieArray.clear();
85 }
86
87 void DWARFCompileUnit::dump(raw_ostream &OS) {
88 OS << format("0x%08x", Offset) << ": Compile Unit:"
89 << " length = " << format("0x%08x", Length)
90 << " version = " << format("0x%04x", Version)
91 << " abbr_offset = " << format("0x%04x", Abbrevs->getOffset())
92 << " addr_size = " << format("0x%02x", AddrSize)
93 << " (next CU at " << format("0x%08x", getNextCompileUnitOffset())
94 << ")\n";
95
96 extractDIEsIfNeeded(false);
97 for (unsigned i = 0, e = DieArray.size(); i != e; ++i)
98 DieArray[i].dump(OS, this, 10);
99 }
100
101 void DWARFCompileUnit::setDIERelations() {
102 if (DieArray.empty())
103 return;
104 DWARFDebugInfoEntryMinimal *die_array_begin = &DieArray.front();
105 DWARFDebugInfoEntryMinimal *die_array_end = &DieArray.back();
106 DWARFDebugInfoEntryMinimal *curr_die;
107 // We purposely are skipping the last element in the array in the loop below
108 // so that we can always have a valid next item
109 for (curr_die = die_array_begin; curr_die < die_array_end; ++curr_die) {
110 // Since our loop doesn't include the last element, we can always
111 // safely access the next die in the array.
112 DWARFDebugInfoEntryMinimal *next_die = curr_die + 1;
113
114 const DWARFAbbreviationDeclaration *curr_die_abbrev =
115 curr_die->getAbbreviationDeclarationPtr();
116
117 if (curr_die_abbrev) {
118 // Normal DIE
119 if (curr_die_abbrev->hasChildren())
120 next_die->setParent(curr_die);
121 else
122 curr_die->setSibling(next_die);
123 } else {
124 // NULL DIE that terminates a sibling chain
125 DWARFDebugInfoEntryMinimal *parent = curr_die->getParent();
126 if (parent)
127 parent->setSibling(next_die);
128 }
129 }
130
131 // Since we skipped the last element, we need to fix it up!
132 if (die_array_begin < die_array_end)
133 curr_die->setParent(die_array_begin);
134 }
135
136 size_t DWARFCompileUnit::extractDIEsIfNeeded(bool cu_die_only) {
137 const size_t initial_die_array_size = DieArray.size();
138 if ((cu_die_only && initial_die_array_size > 0) ||
139 initial_die_array_size > 1)
140 return 0; // Already parsed
141
142 // Set the offset to that of the first DIE and calculate the start of the
143 // next compilation unit header.
144 uint32_t offset = getFirstDIEOffset();
145 uint32_t next_cu_offset = getNextCompileUnitOffset();
146
147 DWARFDebugInfoEntryMinimal die;
148 // Keep a flat array of the DIE for binary lookup by DIE offset
149 uint32_t depth = 0;
150 // We are in our compile unit, parse starting at the offset
151 // we were told to parse
152
153 const uint8_t *fixed_form_sizes =
154 DWARFFormValue::getFixedFormSizesForAddressSize(getAddressByteSize());
155
156 while (offset < next_cu_offset &&
157 die.extractFast(this, fixed_form_sizes, &offset)) {
158
159 if (depth == 0) {
160 uint64_t base_addr =
161 die.getAttributeValueAsUnsigned(this, DW_AT_low_pc, -1U);
162 if (base_addr == -1U)
163 base_addr = die.getAttributeValueAsUnsigned(this, DW_AT_entry_pc, 0);
164 setBaseAddress(base_addr);
165 }
166
167 if (cu_die_only) {
168 addDIE(die);
169 return 1;
170 }
171 else if (depth == 0 && initial_die_array_size == 1) {
172 // Don't append the CU die as we already did that
173 } else {
174 addDIE (die);
175 }
176
177 const DWARFAbbreviationDeclaration *abbrDecl =
178 die.getAbbreviationDeclarationPtr();
179 if (abbrDecl) {
180 // Normal DIE
181 if (abbrDecl->hasChildren())
182 ++depth;
183 } else {
184 // NULL DIE.
185 if (depth > 0)
186 --depth;
187 if (depth == 0)
188 break; // We are done with this compile unit!
189 }
190
191 }
192
193 // Give a little bit of info if we encounter corrupt DWARF (our offset
194 // should always terminate at or before the start of the next compilation
195 // unit header).
196 if (offset > next_cu_offset) {
197 fprintf (stderr, "warning: DWARF compile unit extends beyond its bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), offset);
198 }
199
200 setDIERelations();
201 return DieArray.size();
202 }
0 //===-- DWARFCompileUnit.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_DWARFCOMPILEUNIT_H
10 #define LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H
11
12 #include "DWARFDebugAbbrev.h"
13 #include "DWARFDebugInfoEntry.h"
14 #include
15
16 namespace llvm {
17
18 class DWARFContext;
19 class raw_ostream;
20
21 class DWARFCompileUnit {
22 DWARFContext &Context;
23
24 uint32_t Offset;
25 uint32_t Length;
26 uint16_t Version;
27 const DWARFAbbreviationDeclarationSet *Abbrevs;
28 uint8_t AddrSize;
29 uint64_t BaseAddr;
30 // The compile unit debug information entry item.
31 std::vector DieArray;
32 public:
33 DWARFCompileUnit(DWARFContext &context) : Context(context) {
34 clear();
35 }
36
37 DWARFContext &getContext() const { return Context; }
38 DataExtractor getDebugInfoExtractor() const;
39
40 bool extract(DataExtractor debug_info, uint32_t* offset_ptr);
41 uint32_t extract(uint32_t offset, DataExtractor debug_info_data,
42 const DWARFAbbreviationDeclarationSet *abbrevs);
43
44 /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it
45 /// hasn't already been done.
46 size_t extractDIEsIfNeeded(bool cu_die_only);
47 void clear();
48 void dump(raw_ostream &OS);
49 uint32_t getOffset() const { return Offset; }
50 /// Size in bytes of the compile unit header.
51 uint32_t getSize() const { return 11; }
52 bool containsDIEOffset(uint32_t die_offset) const {
53 return die_offset >= getFirstDIEOffset() &&
54 die_offset < getNextCompileUnitOffset();
55 }
56 uint32_t getFirstDIEOffset() const { return Offset + getSize(); }
57 uint32_t getNextCompileUnitOffset() const { return Offset + Length + 4; }
58 /// Size in bytes of the .debug_info data associated with this compile unit.
59 size_t getDebugInfoSize() const { return Length + 4 - getSize(); }
60 uint32_t getLength() const { return Length; }
61 uint16_t getVersion() const { return Version; }
62 const DWARFAbbreviationDeclarationSet *getAbbreviations() const {
63 return Abbrevs;
64 }
65 uint8_t getAddressByteSize() const { return AddrSize; }
66 uint64_t getBaseAddress() const { return BaseAddr; }
67
68 void setBaseAddress(uint64_t base_addr) {
69 BaseAddr = base_addr;
70 }
71
72 /// setDIERelations - We read in all of the DIE entries into our flat list
73 /// of DIE entries and now we need to go back through all of them and set the
74 /// parent, sibling and child pointers for quick DIE navigation.
75 void setDIERelations();
76
77 void addDIE(DWARFDebugInfoEntryMinimal &die) {
78 // The average bytes per DIE entry has been seen to be
79 // around 14-20 so lets pre-reserve the needed memory for
80 // our DIE entries accordingly. Search forward for "Compute
81 // average bytes per DIE" to see #if'ed out code that does
82 // that determination.
83
84 // Only reserve the memory if we are adding children of
85 // the main compile unit DIE. The compile unit DIE is always
86 // the first entry, so if our size is 1, then we are adding
87 // the first compile unit child DIE and should reserve
88 // the memory.
89 if (DieArray.empty())
90 DieArray.reserve(getDebugInfoSize() / 14);
91 DieArray.push_back(die);
92 }
93 };
94
95 }
96
97 #endif
0 //===-- DWARFContext.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 "DWARFContext.h"
10 using namespace llvm;
11
12 void DWARFContext::dump(raw_ostream &OS) {
13 getDebugAbbrev()->dump(OS);
14 for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i)
15 getCompileUnitAtIndex(i)->dump(OS);
16 }
17
18 const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
19 if (Abbrev)
20 return Abbrev.get();
21
22 DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0);
23
24 Abbrev.reset(new DWARFDebugAbbrev());
25 Abbrev->parse(abbrData);
26 return Abbrev.get();
27 }
28
29 void DWARFContext::parseCompileUnits() {
30 uint32_t offset = 0;
31 const DataExtractor &debug_info_data = DataExtractor(getInfoSection(),
32 isLittleEndian(), 0);
33 while (debug_info_data.isValidOffset(offset)) {
34 CUs.push_back(DWARFCompileUnit(*this));
35 if (!CUs.back().extract(debug_info_data, &offset)) {
36 CUs.pop_back();
37 break;
38 }
39
40 offset = CUs.back().getNextCompileUnitOffset();
41 }
42 }
0 //===-- DWARFContext.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_DWARFCONTEXT_H
10 #define LLVM_DEBUGINFO_DWARFCONTEXT_H
11
12 #include "DWARFCompileUnit.h"
13 #include "llvm/DebugInfo/DIContext.h"
14 #include "llvm/ADT/OwningPtr.h"
15 #include "llvm/ADT/SmallVector.h"
16
17 namespace llvm {
18
19 class DWARFDebugAbbrev;
20
21 /// DWARFContext
22 /// This data structure is the top level entity that deals with dwarf debug
23 /// information parsing. The actual data is supplied through pure virtual
24 /// methods that a concrete implementation provides.
25 class DWARFContext : public DIContext {
26 bool IsLittleEndian;
27
28 SmallVector CUs;
29 OwningPtr Abbrev;
30
31 DWARFContext(DWARFContext &); // = delete
32 DWARFContext &operator=(DWARFContext &); // = delete
33
34 /// Read compile units from the debug_info section and store them in CUs.
35 void parseCompileUnits();
36 protected:
37 DWARFContext(bool isLittleEndian) : IsLittleEndian(isLittleEndian) {}
38 public:
39 virtual void dump(raw_ostream &OS);
40 /// Get the number of compile units in this context.
41 unsigned getNumCompileUnits() {
42 if (CUs.empty())
43 parseCompileUnits();
44 return CUs.size();
45 }
46 /// Get the compile unit at the specified index for this compile unit.
47 DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) {
48 if (CUs.empty())
49 parseCompileUnits();
50 return &CUs[index];
51 }
52
53 /// Get a pointer to the parsed DebugAbbrev object.
54 const DWARFDebugAbbrev *getDebugAbbrev();
55
56 bool isLittleEndian() const { return IsLittleEndian; }
57
58 virtual StringRef getInfoSection() = 0;
59 virtual StringRef getAbbrevSection() = 0;
60 virtual StringRef getARangeSection() = 0;
61 virtual StringRef getLineSection() = 0;
62 virtual StringRef getStringSection() = 0;
63
64 static bool isSupportedVersion(unsigned version) {
65 return version == 2 || version == 3;
66 }
67 };
68
69
70 /// DWARFContextInMemory is the simplest possible implementation of a
71 /// DWARFContext. It assumes all content is available in memory and stores
72 /// pointers to it.
73 class DWARFContextInMemory : public DWARFContext {
74 StringRef InfoSection;
75 StringRef AbbrevSection;
76 StringRef ARangeSection;
77 StringRef LineSection;
78 StringRef StringSection;
79 public:
80 DWARFContextInMemory(bool isLittleEndian,
81 StringRef infoSection,
82 StringRef abbrevSection,
83 StringRef aRangeSection,
84 StringRef lineSection,
85 StringRef stringSection)
86 : DWARFContext(isLittleEndian),
87 InfoSection(infoSection),
88 AbbrevSection(abbrevSection),
89 ARangeSection(aRangeSection),
90 LineSection(lineSection),
91 StringSection(stringSection)
92 {}
93
94 virtual StringRef getInfoSection() { return InfoSection; }
95 virtual StringRef getAbbrevSection() { return AbbrevSection; }
96 virtual StringRef getARangeSection() { return ARangeSection; }
97 virtual StringRef getLineSection() { return LineSection; }
98 virtual StringRef getStringSection() { return StringSection; }
99 };
100
101 }
102
103 #endif
0 //===-- DWARFDebugAbbrev.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 "DWARFDebugAbbrev.h"
10 #include "llvm/Support/Format.h"
11 #include "llvm/Support/raw_ostream.h"
12 using namespace llvm;
13
14 bool DWARFAbbreviationDeclarationSet::extract(DataExtractor data,
15 uint32_t* offset_ptr) {
16 const uint32_t beginOffset = *offset_ptr;
17 Offset = beginOffset;
18 clear();
19 DWARFAbbreviationDeclaration abbrevDeclaration;
20 uint32_t prevAbbrAode = 0;
21 while (abbrevDeclaration.extract(data, offset_ptr)) {
22 Decls.push_back(abbrevDeclaration);
23 if (IdxOffset == 0) {
24 IdxOffset = abbrevDeclaration.getCode();
25 } else {
26 if (prevAbbrAode + 1 != abbrevDeclaration.getCode())
27 IdxOffset = UINT32_MAX;// Out of order indexes, we can't do O(1) lookups
28 }
29 prevAbbrAode = abbrevDeclaration.getCode();
30 }
31 return beginOffset != *offset_ptr;
32 }
33
34
35 void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const {
36 for (unsigned i = 0, e = Decls.size(); i != e; ++i)
37 Decls[i].dump(OS);
38 }
39
40
41 const DWARFAbbreviationDeclaration*
42 DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(uint32_t abbrCode)
43 const {
44 if (IdxOffset == UINT32_MAX) {
45 DWARFAbbreviationDeclarationCollConstIter pos;
46 DWARFAbbreviationDeclarationCollConstIter end = Decls.end();
47 for (pos = Decls.begin(); pos != end; ++pos) {
48 if (pos->getCode() == abbrCode)
49 return &(*pos);
50 }
51 } else {
52 uint32_t idx = abbrCode - IdxOffset;
53 if (idx < Decls.size())
54 return &Decls[idx];
55 }
56 return NULL;
57 }
58
59 DWARFDebugAbbrev::DWARFDebugAbbrev() :
60 m_abbrevCollMap(),
61 m_prev_abbr_offset_pos(m_abbrevCollMap.end()) {}
62
63
64 void DWARFDebugAbbrev::parse(DataExtractor data) {
65 uint32_t offset = 0;
66
67 while (data.isValidOffset(offset)) {
68 uint32_t initial_cu_offset = offset;
69 DWARFAbbreviationDeclarationSet abbrevDeclSet;
70
71 if (abbrevDeclSet.extract(data, &offset))
72 m_abbrevCollMap[initial_cu_offset] = abbrevDeclSet;
73 else
74 break;
75 }
76 m_prev_abbr_offset_pos = m_abbrevCollMap.end();
77 }
78
79 void DWARFDebugAbbrev::dump(raw_ostream &OS) const {
80 if (m_abbrevCollMap.empty()) {
81 OS << "< EMPTY >\n";
82 return;
83 }
84
85 DWARFAbbreviationDeclarationCollMapConstIter pos;
86 for (pos = m_abbrevCollMap.begin(); pos != m_abbrevCollMap.end(); ++pos) {
87 OS << format("Abbrev table for offset: 0x%8.8x\n", pos->first);
88 pos->second.dump(OS);
89 }
90 }
91
92 const DWARFAbbreviationDeclarationSet*
93 DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t cu_abbr_offset) const {
94 DWARFAbbreviationDeclarationCollMapConstIter end = m_abbrevCollMap.end();
95 DWARFAbbreviationDeclarationCollMapConstIter pos;
96 if (m_prev_abbr_offset_pos != end &&
97 m_prev_abbr_offset_pos->first == cu_abbr_offset) {
98 return &(m_prev_abbr_offset_pos->second);
99 } else {
100 pos = m_abbrevCollMap.find(cu_abbr_offset);
101 m_prev_abbr_offset_pos = pos;
102 }
103
104 if (pos != m_abbrevCollMap.end())
105 return &(pos->second);
106 return NULL;
107 }
0 //===-- DWARFDebugAbbrev.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_DWARFDEBUGABBREV_H
10 #define LLVM_DEBUGINFO_DWARFDEBUGABBREV_H
11
12 #include "DWARFAbbreviationDeclaration.h"
13 #include
14 #include
15 #include
16
17 namespace llvm {
18
19 typedef std::vector
20 DWARFAbbreviationDeclarationColl;
21 typedef DWARFAbbreviationDeclarationColl::iterator
22 DWARFAbbreviationDeclarationCollIter;
23 typedef DWARFAbbreviationDeclarationColl::const_iterator
24 DWARFAbbreviationDeclarationCollConstIter;
25
26 class DWARFAbbreviationDeclarationSet {
27 uint64_t Offset;
28 uint32_t IdxOffset;
29 std::vector Decls;
30 public:
31 DWARFAbbreviationDeclarationSet()
32 : Offset(0), IdxOffset(0) {}
33
34 DWARFAbbreviationDeclarationSet(uint64_t offset, uint32_t idxOffset)
35 : Offset(offset), IdxOffset(idxOffset) {}
36
37 void clear() {
38 IdxOffset = 0;
39 Decls.clear();
40 }
41 uint64_t getOffset() const { return Offset; }
42 void dump(raw_ostream &OS) const;
43 bool extract(DataExtractor data, uint32_t* offset_ptr);
44
45 const DWARFAbbreviationDeclaration *
46 getAbbreviationDeclaration(uint32_t abbrCode) const;
47 };
48
49 typedef std::map
50 DWARFAbbreviationDeclarationCollMap;
51 typedef DWARFAbbreviationDeclarationCollMap::iterator
52 DWARFAbbreviationDeclarationCollMapIter;
53 typedef DWARFAbbreviationDeclarationCollMap::const_iterator
54 DWARFAbbreviationDeclarationCollMapConstIter;
55
56 class DWARFDebugAbbrev {
57 public:
58 DWARFDebugAbbrev();
59 const DWARFAbbreviationDeclarationSet *
60 getAbbreviationDeclarationSet(uint64_t cu_abbr_offset) const;
61 void dump(raw_ostream &OS) const;
62 void parse(DataExtractor data);
63 protected:
64 DWARFAbbreviationDeclarationCollMap m_abbrevCollMap;
65 mutable DWARFAbbreviationDeclarationCollMapConstIter m_prev_abbr_offset_pos;
66 };
67
68 }
69
70 #endif
0 //===-- DWARFDebugInfoEntry.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 "DWARFDebugInfoEntry.h"
10 #include "DWARFCompileUnit.h"
11 #include "DWARFContext.h"
12 #include "DWARFDebugAbbrev.h"
13 #include "DWARFFormValue.h"
14 #include "llvm/Support/Dwarf.h"
15 #include "llvm/Support/Format.h"
16 #include "llvm/Support/raw_ostream.h"
17 using namespace llvm;
18 using namespace dwarf;
19
20 void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS,
21 const DWARFCompileUnit *cu,
22 unsigned recurseDepth,
23 unsigned indent) const {
24 DataExtractor debug_info_data = cu->getDebugInfoExtractor();
25 uint32_t offset = Offset;
26
27 if (debug_info_data.isValidOffset(offset)) {
28 uint64_t abbrCode = debug_info_data.getULEB128(&offset);
29
30 OS.indent(indent) << format("\n0x%8.8x: ", Offset);
31 if (abbrCode) {
32 if (AbbrevDecl) {
33 OS << TagString(AbbrevDecl->getTag())
34 << format(" [%u] %c\n", abbrCode,
35 AbbrevDecl->hasChildren() ? '*': ' ');
36
37 // Dump all data in the .debug_info for the attributes
38 const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
39 for (uint32_t i = 0; i != numAttributes; ++i) {
40 uint16_t attr = AbbrevDecl->getAttrByIndex(i);
41 uint16_t form = AbbrevDecl->getFormByIndex(i);
42 dumpAttribute(OS, cu, &offset, attr, form, indent);
43 }
44
45 const DWARFDebugInfoEntryMinimal *child = getFirstChild();
46 if (recurseDepth > 0 && child) {
47 indent += 2;
48 while (child) {
49 child->dump(OS, cu, recurseDepth-1, indent);
50 child = child->getSibling();
51 }
52 indent -= 2;
53 }
54 } else {
55 OS << "Abbreviation code not found in 'debug_abbrev' class for code: "
56 << abbrCode << '\n';
57 }
58 } else {
59 OS << "NULL\n";
60 }
61 }
62 }
63
64 void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS,
65 const DWARFCompileUnit *cu,
66 uint32_t* offset_ptr,
67 uint16_t attr,
68 uint16_t form,
69 unsigned indent) const {
70 OS.indent(indent) << format("0x%8.8x: ", *offset_ptr)
71 << AttributeString(attr)
72 << " [" << FormEncodingString(form) << ']';
73
74 DWARFFormValue formValue(form);
75
76 if (!formValue.extractValue(cu->getDebugInfoExtractor(), offset_ptr, cu))
77 return;
78
79 OS << "\t(";
80 formValue.dump(OS, 0, cu);
81 OS << ")\n";
82 }
83
84 bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu,
85 const uint8_t *fixed_form_sizes,
86 uint32_t *offset_ptr) {
87 Offset = *offset_ptr;
88
89 DataExtractor debug_info_data = cu->getDebugInfoExtractor();
90 uint64_t abbrCode = debug_info_data.getULEB128(offset_ptr);
91
92 assert (fixed_form_sizes); // For best performance this should be specified!
93
94 if (abbrCode) {
95 uint32_t offset = *offset_ptr;
96
97 AbbrevDecl = cu->getAbbreviations()->getAbbreviationDeclaration(abbrCode);
98
99 // Skip all data in the .debug_info for the attributes
100 const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
101 uint32_t i;
102 uint16_t form;
103 for (i=0; i
104 form = AbbrevDecl->getFormByIndex(i);
105
106 const uint8_t fixed_skip_size = fixed_form_sizes[form];
107 if (fixed_skip_size)
108 offset += fixed_skip_size;
109 else {
110 bool form_is_indirect = false;
111 do {
112 form_is_indirect = false;
113 uint32_t form_size = 0;
114 switch (form) {
115 // Blocks if inlined data that have a length field and the data bytes
116 // inlined in the .debug_info.
117 case DW_FORM_block:
118 form_size = debug_info_data.getULEB128(&offset);
119 break;
120 case DW_FORM_block1:
121 form_size = debug_info_data.getU8(&offset);
122 break;
123 case DW_FORM_block2:
124 form_size = debug_info_data.getU16(&offset);
125 break;
126 case DW_FORM_block4:
127 form_size = debug_info_data.getU32(&offset);
128 break;
129
130 // Inlined NULL terminated C-strings
131 case DW_FORM_string:
132 debug_info_data.getCStr(&offset);
133 break;
134
135 // Compile unit address sized values
136 case DW_FORM_addr:
137 case DW_FORM_ref_addr:
138 form_size = cu->getAddressByteSize();
139 break;
140
141 // 1 byte values
142 case DW_FORM_data1:
143 case DW_FORM_flag:
144 case DW_FORM_ref1:
145 form_size = 1;
146 break;
147
148 // 2 byte values
149 case DW_FORM_data2:
150 case DW_FORM_ref2:
151 form_size = 2;
152 break;
153
154 // 4 byte values
155 case DW_FORM_strp:
156 case DW_FORM_data4:
157 case DW_FORM_ref4:
158 form_size = 4;
159 break;
160
161 // 8 byte values
162 case DW_FORM_data8:
163 case DW_FORM_ref8:
164 form_size = 8;
165 break;
166
167 // signed or unsigned LEB 128 values
168 case DW_FORM_sdata:
169 case DW_FORM_udata:
170 case DW_FORM_ref_udata:
171 debug_info_data.getULEB128(&offset);
172 break;
173
174 case DW_FORM_indirect:
175 form_is_indirect = true;
176 form = debug_info_data.getULEB128(&offset);
177 break;
178
179 default:
180 *offset_ptr = Offset;
181 return false;
182 }
183 offset += form_size;
184
185 } while (form_is_indirect);
186 }
187 }
188 *offset_ptr = offset;
189 return true;
190 } else {
191 AbbrevDecl = NULL;
192 return true; // NULL debug tag entry
193 }
194
195 return false;
196 }
197
198 bool
199 DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *cu,
200 uint32_t *offset_ptr) {
201 DataExtractor debug_info_data = cu->getDebugInfoExtractor();
202 const uint32_t cu_end_offset = cu->getNextCompileUnitOffset();
203 const uint8_t cu_addr_size = cu->getAddressByteSize();
204 uint32_t offset = *offset_ptr;
205 if ((offset < cu_end_offset) && debug_info_data.isValidOffset(offset)) {
206 Offset = offset;
207
208 uint64_t abbrCode = debug_info_data.getULEB128(&offset);
209
210 if (abbrCode) {
211 AbbrevDecl = cu->getAbbreviations()->getAbbreviationDeclaration(abbrCode);
212
213 if (AbbrevDecl) {
214 uint16_t tag = AbbrevDecl->getTag();
215
216 bool isCompileUnitTag = tag == DW_TAG_compile_unit;
217 if(cu && isCompileUnitTag)
218 const_cast(cu)->setBaseAddress(0);
219
220 // Skip all data in the .debug_info for the attributes
221 const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
222 for (uint32_t i = 0; i != numAttributes; ++i) {
223 uint16_t attr = AbbrevDecl->getAttrByIndex(i);
224 uint16_t form = AbbrevDecl->getFormByIndex(i);
225
226 if (isCompileUnitTag &&
227 ((attr == DW_AT_entry_pc) || (attr == DW_AT_low_pc))) {
228 DWARFFormValue form_value(form);
229 if (form_value.extractValue(debug_info_data, &offset, cu)) {
230 if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc)
231 const_cast(cu)
232 ->setBaseAddress(form_value.getUnsigned());
233 }
234 } else {
235 bool form_is_indirect = false;
236 do {
237 form_is_indirect = false;
238 register uint32_t form_size = 0;
239 switch (form) {
240 // Blocks if inlined data that have a length field and the data
241 // bytes // inlined in the .debug_info
242 case DW_FORM_block:
243 form_size = debug_info_data.getULEB128(&offset);
244 break;
245 case DW_FORM_block1:
246 form_size = debug_info_data.getU8(&offset);
247 break;
248 case DW_FORM_block2:
249 form_size = debug_info_data.getU16(&offset);
250 break;
251 case DW_FORM_block4:
252 form_size = debug_info_data.getU32(&offset);
253 break;
254
255 // Inlined NULL terminated C-strings
256 case DW_FORM_string:
257 debug_info_data.getCStr(&offset);
258 break;
259
260 // Compile unit address sized values
261 case DW_FORM_addr:
262 case DW_FORM_ref_addr:
263 form_size = cu_addr_size;
264 break;
265
266 // 1 byte values
267 case DW_FORM_data1:
268 case DW_FORM_flag:
269 case DW_FORM_ref1:
270 form_size = 1;
271 break;
272
273 // 2 byte values
274 case DW_FORM_data2:
275 case DW_FORM_ref2:
276 form_size = 2;
277 break;
278
279 // 4 byte values
280 case DW_FORM_strp:
281 form_size = 4;
282 break;
283
284 case DW_FORM_data4:
285 case DW_FORM_ref4:
286 form_size = 4;
287 break;
288
289 // 8 byte values
290 case DW_FORM_data8:
291 case DW_FORM_ref8:
292 form_size = 8;
293 break;
294
295 // signed or unsigned LEB 128 values
296 case DW_FORM_sdata:
297 case DW_FORM_udata:
298 case DW_FORM_ref_udata:
299 debug_info_data.getULEB128(&offset);
300 break;
301
302 case DW_FORM_indirect:
303 form = debug_info_data.getULEB128(&offset);
304 form_is_indirect = true;
305 break;
306
307 default:
308 *offset_ptr = offset;
309 return false;
310 }
311
312 offset += form_size;
313 } while (form_is_indirect);
314 }
315 }
316 *offset_ptr = offset;
317 return true;
318 }
319 } else {
320 AbbrevDecl = NULL;
321 *offset_ptr = offset;
322 return true; // NULL debug tag entry
323 }
324 }
325
326 return false;
327 }
328
329 uint32_t
330 DWARFDebugInfoEntryMinimal::getAttributeValue(const DWARFCompileUnit *cu,
331 const uint16_t attr,
332 DWARFFormValue &form_value,
333 uint32_t *end_attr_offset_ptr)
334 const {
335 if (AbbrevDecl) {
336 uint32_t attr_idx = AbbrevDecl->findAttributeIndex(attr);
337
338 if (attr_idx != -1U) {
339 uint32_t offset = getOffset();
340
341 DataExtractor debug_info_data = cu->getDebugInfoExtractor();
342
343 // Skip the abbreviation code so we are at the data for the attributes
344 debug_info_data.getULEB128(&offset);
345
346 uint32_t idx = 0;
347 while (idx < attr_idx)
348 DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(idx++),
349 debug_info_data, &offset, cu);
350
351 const uint32_t attr_offset = offset;
352 form_value = DWARFFormValue(AbbrevDecl->getFormByIndex(idx));
353 if (form_value.extractValue(debug_info_data, &offset, cu))
354 {
355 if (end_attr_offset_ptr)
356 *end_attr_offset_ptr = offset;
357 return attr_offset;
358 }
359 }
360 }
361
362 return 0;
363 }
364
365 const char*
366 DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
367 const DWARFCompileUnit* cu,
368 const uint16_t attr,
369 const char* fail_value) const {
370 DWARFFormValue form_value;
371 if (getAttributeValue(cu, attr, form_value)) {
372 DataExtractor stringExtractor(cu->getContext().getStringSection(),
373 false, 0);
374 return form_value.getAsCString(&stringExtractor);
375 }
376 return fail_value;
377 }
378
379 uint64_t
380 DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsigned(
381 const DWARFCompileUnit* cu,
382 const uint16_t attr,
383 uint64_t fail_value) const {
384 DWARFFormValue form_value;
385 if (getAttributeValue(cu, attr, form_value))
386 return form_value.getUnsigned();
387 return fail_value;
388 }
389
390 int64_t
391 DWARFDebugInfoEntryMinimal::getAttributeValueAsSigned(
392 const DWARFCompileUnit* cu,
393 const uint16_t attr,
394 int64_t fail_value) const {
395 DWARFFormValue form_value;
396 if (getAttributeValue(cu, attr, form_value))
397 return form_value.getSigned();
398 return fail_value;
399 }
400
401 uint64_t
402 DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(const DWARFCompileUnit* cu,
403 const uint16_t attr,
404 uint64_t fail_value) const {
405 DWARFFormValue form_value;
406 if (getAttributeValue(cu, attr, form_value))
407 return form_value.getReference(cu);
408 return fail_value;
409 }
0 //===-- DWARFDebugInfoEntry.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_DWARFDEBUGINFOENTRY_H
10 #define LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H
11
12 #include "DWARFAbbreviationDeclaration.h"
13 #include "llvm/Support/DataTypes.h"
14
15 namespace llvm {
16
17 class DWARFCompileUnit;
18 class DWARFContext;
19 class DWARFFormValue;
20
21 /// DWARFDebugInfoEntryMinimal - A DIE with only the minimum required data.
22 class DWARFDebugInfoEntryMinimal {
23 /// Offset within the .debug_info of the start of this entry.
24 uint64_t Offset;
25
26 /// How many to subtract from "this" to get the parent.
27 /// If zero this die has no parent.
28 uint32_t ParentIdx;
29
30 /// How many to add to "this" to get the sibling.
31 uint32_t SiblingIdx;
32
33 const DWARFAbbreviationDeclaration *AbbrevDecl;
34 public:
35 void dump(raw_ostream &OS, const DWARFCompileUnit *cu,
36 unsigned recurseDepth, unsigned indent = 0) const;
37 void dumpAttribute(raw_ostream &OS, const DWARFCompileUnit *cu,
38 uint32_t *offset_ptr, uint16_t attr, uint16_t form,
39 unsigned indent = 0) const;
40
41 bool extractFast(const DWARFCompileUnit *cu, const uint8_t *fixed_form_sizes,
42 uint32_t *offset_ptr);
43
44 /// Extract a debug info entry for a given compile unit from the
45 /// .debug_info and .debug_abbrev data starting at the given offset.
46 bool extract(const DWARFCompileUnit *cu, uint32_t *offset_ptr);
47
48 uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; }
49 bool isNULL() const { return AbbrevDecl == 0; }
50 uint64_t getOffset() const { return Offset; }
51 uint32_t getNumAttributes() const {
52 return !isNULL() ? AbbrevDecl->getNumAttributes() : 0;
53 }
54 bool hasChildren() const { return !isNULL() && AbbrevDecl->hasChildren(); }
55
56 // We know we are kept in a vector of contiguous entries, so we know
57 // our parent will be some index behind "this".
58 DWARFDebugInfoEntryMinimal *getParent() {
59 return ParentIdx > 0 ? this - ParentIdx : 0;
60 }
61 const DWARFDebugInfoEntryMinimal *getParent() const {
62 return ParentIdx > 0 ? this - ParentIdx : 0;
63 }
64 // We know we are kept in a vector of contiguous entries, so we know
65 // our sibling will be some index after "this".
66 DWARFDebugInfoEntryMinimal *getSibling() {
67 return SiblingIdx > 0 ? this + SiblingIdx : 0;
68 }
69 const DWARFDebugInfoEntryMinimal *getSibling() const {
70 return SiblingIdx > 0 ? this + SiblingIdx : 0;
71 }
72 // We know we are kept in a vector of contiguous entries, so we know
73 // we don't need to store our child pointer, if we have a child it will
74 // be the next entry in the list...
75 DWARFDebugInfoEntryMinimal *getFirstChild() {
76 return hasChildren() ? this + 1 : 0;
77 }
78 const DWARFDebugInfoEntryMinimal *getFirstChild() const {
79 return hasChildren() ? this + 1 : 0;
80 }
81
82 void setParent(DWARFDebugInfoEntryMinimal *parent) {
83 if (parent) {
84 // We know we are kept in a vector of contiguous entries, so we know
85 // our parent will be some index behind "this".
86 ParentIdx = this - parent;
87 }
88 else
89 ParentIdx = 0;
90 }
91 void setSibling(DWARFDebugInfoEntryMinimal *sibling) {
92 if (sibling)
93 {
94 // We know we are kept in a vector of contiguous entries, so we know
95 // our sibling will be some index after "this".
96 SiblingIdx = sibling - this;
97 sibling->setParent(getParent());
98 }
99 else
100 SiblingIdx = 0;
101 }
102
103 const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const {
104 return AbbrevDecl;
105 }
106
107 uint32_t getAttributeValue(const DWARFCompileUnit *cu,
108 const uint16_t attr, DWARFFormValue &formValue,
109 uint32_t *end_attr_offset_ptr = 0) const;
110
111 const char* getAttributeValueAsString(const DWARFCompileUnit* cu,
112 const uint16_t attr,
113 const char *fail_value) const;
114
115 uint64_t getAttributeValueAsUnsigned(const DWARFCompileUnit *cu,
116 const uint16_t attr,
117 uint64_t fail_value) const;
118
119 uint64_t getAttributeValueAsReference(const DWARFCompileUnit *cu,
120 const uint16_t attr,
121 uint64_t fail_value) const;
122
123 int64_t getAttributeValueAsSigned(const DWARFCompileUnit* cu,
124 const uint16_t attr,
125 int64_t fail_value) const;
126 };
127
128 }
129
130 #endif
0 //===-- DWARFFormValue.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 "DWARFFormValue.h"
10 #include "DWARFCompileUnit.h"
11 #include "llvm/Support/Dwarf.h"
12 #include "llvm/Support/Format.h"
13 #include "llvm/Support/raw_ostream.h"
14 #include
15 using namespace llvm;
16 using namespace dwarf;
17
18 static const uint8_t form_sizes_addr4[] = {
19 0, // 0x00 unused
20 4, // 0x01 DW_FORM_addr
21 0, // 0x02 unused
22 0, // 0x03 DW_FORM_block2
23 0, // 0x04 DW_FORM_block4
24 2, // 0x05 DW_FORM_data2
25 4, // 0x06 DW_FORM_data4
26 8, // 0x07 DW_FORM_data8
27 0, // 0x08 DW_FORM_string
28 0, // 0x09 DW_FORM_block
29 0, // 0x0a DW_FORM_block1
30 1, // 0x0b DW_FORM_data1
31 1, // 0x0c DW_FORM_flag
32 0, // 0x0d DW_FORM_sdata
33 4, // 0x0e DW_FORM_strp
34 0, // 0x0f DW_FORM_udata
35 4, // 0x10 DW_FORM_ref_addr
36 1, // 0x11 DW_FORM_ref1
37 2, // 0x12 DW_FORM_ref2
38 4, // 0x13 DW_FORM_ref4
39 8, // 0x14 DW_FORM_ref8
40 0, // 0x15 DW_FORM_ref_udata
41 0, // 0x16 DW_FORM_indirect
42 };
43
44 static const uint8_t form_sizes_addr8[] = {
45 0, // 0x00 unused
46 8, // 0x01 DW_FORM_addr
47 0, // 0x02 unused
48 0, // 0x03 DW_FORM_block2
49 0, // 0x04 DW_FORM_block4
50 2, // 0x05 DW_FORM_data2
51 4, // 0x06 DW_FORM_data4
52 8, // 0x07 DW_FORM_data8
53 0, // 0x08 DW_FORM_string
54 0, // 0x09 DW_FORM_block
55 0, // 0x0a DW_FORM_block1
56 1, // 0x0b DW_FORM_data1
57 1, // 0x0c DW_FORM_flag
58 0, // 0x0d DW_FORM_sdata
59 4, // 0x0e DW_FORM_strp
60 0, // 0x0f DW_FORM_udata
61 8, // 0x10 DW_FORM_ref_addr
62 1, // 0x11 DW_FORM_ref1
63 2, // 0x12 DW_FORM_ref2
64 4, // 0x13 DW_FORM_ref4
65 8, // 0x14 DW_FORM_ref8
66 0, // 0x15 DW_FORM_ref_udata
67 0, // 0x16 DW_FORM_indirect
68 };
69
70 const uint8_t *
71 DWARFFormValue::getFixedFormSizesForAddressSize(uint8_t addr_size) {
72 switch (addr_size) {
73 case 4: return form_sizes_addr4;
74 case 8: return form_sizes_addr8;
75 }
76 return NULL;
77 }
78
79 bool
80 DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
81 const DWARFCompileUnit* cu) {
82 bool indirect = false;
83 bool is_block = false;
84 Value.data = NULL;
85 // Read the value for the form into value and follow and DW_FORM_indirect
86 // instances we run into
87 do {
88 indirect = false;
89 switch (Form) {
90 case DW_FORM_addr:
91 case DW_FORM_ref_addr:
92 Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize());
93 break;
94 case DW_FORM_block:
95 Value.uval = data.getULEB128(offset_ptr);
96 is_block = true;
97 break;
98 case DW_FORM_block1:
99 Value.uval = data.getU8(offset_ptr);
100 is_block = true;
101 break;
102 case DW_FORM_block2:
103 Value.uval = data.getU16(offset_ptr);
104 is_block = true;
105 break;
106 case DW_FORM_block4:
107 Value.uval = data.getU32(offset_ptr);
108 is_block = true;
109 break;
110 case DW_FORM_data1:
111 case DW_FORM_ref1:
112 case DW_FORM_flag:
113 Value.uval = data.getU8(offset_ptr);
114 break;
115 case DW_FORM_data2:
116 case DW_FORM_ref2:
117 Value.uval = data.getU16(offset_ptr);
118 break;
119 case DW_FORM_data4:
120 case DW_FORM_ref4:
121 Value.uval = data.getU32(offset_ptr);
122 break;
123 case DW_FORM_data8:
124 case DW_FORM_ref8:
125 Value.uval = data.getU64(offset_ptr);
126 break;
127 case DW_FORM_sdata:
128 Value.sval = data.getSLEB128(offset_ptr);
129 break;
130 case DW_FORM_strp:
131 Value.uval = data.getU32(offset_ptr);
132 break;
133 case DW_FORM_udata:
134 case DW_FORM_ref_udata:
135 Value.uval = data.getULEB128(offset_ptr);
136 break;
137 case DW_FORM_string:
138 Value.cstr = data.getCStr(offset_ptr);
139 // Set the string value to also be the data for inlined cstr form
140 // values only so we can tell the differnence between DW_FORM_string
141 // and DW_FORM_strp form values
142 Value.data = (uint8_t*)Value.cstr;
143 break;
144 case DW_FORM_indirect:
145 Form = data.getULEB128(offset_ptr);
146 indirect = true;
147 break;
148 default:
149 return false;
150 }
151 } while (indirect);
152
153 if (is_block) {
154 StringRef str = data.getData().substr(*offset_ptr, Value.uval);
155 Value.data = NULL;
156 if (!str.empty()) {
157 Value.data = reinterpret_cast(str.data());
158 *offset_ptr += Value.uval;
159 }
160 }
161
162 return true;
163 }
164
165 bool
166 DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr,
167 const DWARFCompileUnit* cu) const {
168 return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu);
169 }
170
171 bool
172 DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
173 uint32_t *offset_ptr, const DWARFCompileUnit *cu) {
174 bool indirect = false;
175 do {
176 indirect = false;
177 switch (form) {
178 // Blocks if inlined data that have a length field and the data bytes
179 // inlined in the .debug_info
180 case DW_FORM_block: {
181 uint64_t size = debug_info_data.getULEB128(offset_ptr);
182 *offset_ptr += size;
183 return true;
184 }
185 case DW_FORM_block1: {
186 uint8_t size = debug_info_data.getU8(offset_ptr);
187 *offset_ptr += size;
188 return true;
189 }
190 case DW_FORM_block2: {
191 uint16_t size = debug_info_data.getU16(offset_ptr);
192 *offset_ptr += size;
193 return true;
194 }
195 case DW_FORM_block4: {
196 uint32_t size = debug_info_data.getU32(offset_ptr);
197 *offset_ptr += size;
198 return true;
199 }
200
201 // Inlined NULL terminated C-strings
202 case DW_FORM_string:
203 debug_info_data.getCStr(offset_ptr);
204 return true;
205
206 // Compile unit address sized values
207 case DW_FORM_addr:
208 case DW_FORM_ref_addr:
209 *offset_ptr += cu->getAddressByteSize();
210 return true;
211
212 // 1 byte values
213 case DW_FORM_data1:
214 case DW_FORM_flag:
215 case DW_FORM_ref1:
216 *offset_ptr += 1;
217 return true;
218
219 // 2 byte values
220 case DW_FORM_data2:
221 case DW_FORM_ref2:
222 *offset_ptr += 2;
223 return true;
224
225 // 4 byte values
226 case DW_FORM_strp:
227 case DW_FORM_data4:
228 case DW_FORM_ref4:
229 *offset_ptr += 4;
230 return true;
231
232 // 8 byte values
233 case DW_FORM_data8:
234 case DW_FORM_ref8:
235 *offset_ptr += 8;
236 return true;
237
238 // signed or unsigned LEB 128 values
239 // case DW_FORM_APPLE_db_str:
240 case DW_FORM_sdata:
241 case DW_FORM_udata:
242 case DW_FORM_ref_udata:
243 debug_info_data.getULEB128(offset_ptr);
244 return true;
245
246 case DW_FORM_indirect:
247 indirect = true;
248 form = debug_info_data.getULEB128(offset_ptr);
249 break;
250 default:
251 return false;
252 }
253 } while (indirect);
254 return true;
255 }
256
257 void
258 DWARFFormValue::dump(raw_ostream &OS, const DataExtractor *debug_str_data,
259 const DWARFCompileUnit *cu) const {
260 uint64_t uvalue = getUnsigned();
261 bool cu_relative_offset = false;
262
263 switch (Form)
264 {
265 case DW_FORM_addr: OS << format("0x%016x", uvalue); break;
266 case DW_FORM_flag:
267 case DW_FORM_data1: OS << format("0x%02x", uvalue); break;
268 case DW_FORM_data2: OS << format("0x%04x", uvalue); break;
269 case DW_FORM_data4: OS << format("0x%08x", uvalue); break;
270 case DW_FORM_data8: OS << format("0x%016x", uvalue); break;
271 case DW_FORM_string:
272 OS << '"';
273 OS.write_escaped(getAsCString(NULL));
274 OS << '"';
275 break;
276 case DW_FORM_block:
277 case DW_FORM_block1:
278 case DW_FORM_block2:
279 case DW_FORM_block4:
280 if (uvalue > 0) {
281 switch (Form) {
282 case DW_FORM_block: OS << format("<0x%llx> ", uvalue); break;
283 case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue); break;
284 case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break;
285 case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break;
286 default: break;
287 }
288
289 const uint8_t* data_ptr = Value.data;
290 if (data_ptr) {
291 // uvalue contains size of block
292 const uint8_t* end_data_ptr = data_ptr + uvalue;
293 while (data_ptr < end_data_ptr) {
294 OS << format("%2.2x ", *data_ptr);
295 ++data_ptr;
296 }
297 }
298 else
299 OS << "NULL";
300 }
301 break;
302
303 case DW_FORM_sdata: OS << getSigned(); break;
304 case DW_FORM_udata: OS << getUnsigned(); break;
305 case DW_FORM_strp:
306 if (debug_str_data) {
307 OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
308 const char* dbg_str = getAsCString(debug_str_data);
309 if (dbg_str) {
310 OS << '"';
311 OS.write_escaped(dbg_str);
312 OS << '"';
313 }
314 } else {
315 OS << format("0x%08x", uvalue);
316 }
317 break;
318 case DW_FORM_ref_addr:
319 OS << format("0x%016x", uvalue);
320 break;
321 case DW_FORM_ref1:
322 cu_relative_offset = true;
323 OS << format("cu + 0x%2.2x", (uint8_t)uvalue);
324 break;
325 case DW_FORM_ref2:
326 cu_relative_offset = true;
327 OS << format("cu + 0x%4.4x", (uint16_t)uvalue);
328 break;
329 case DW_FORM_ref4:
330 cu_relative_offset = true;
331 OS << format("cu + 0x%4.4x", (uint32_t)uvalue);
332 break;
333 case DW_FORM_ref8:
334 cu_relative_offset = true;
335 OS << format("cu + 0x%8.8llx", uvalue);
336 break;
337 case DW_FORM_ref_udata:
338 cu_relative_offset = true;
339 OS << format("cu + 0x%llx", uvalue);
340 break;
341
342 // All DW_FORM_indirect attributes should be resolved prior to calling
343 // this function
344 case DW_FORM_indirect:
345 OS << "DW_FORM_indirect";
346 break;
347 default:
348 OS << format("DW_FORM(0x%4.4x)", Form);
349 break;
350 }
351
352 if (cu_relative_offset)
353 OS << format(" => {0x%8.8x}", (uvalue + (cu ? cu->getOffset() : 0)));
354 }
355
356 const char*
357 DWARFFormValue::getAsCString(const DataExtractor *debug_str_data_ptr) const {
358 if (isInlinedCStr()) {
359 return Value.cstr;
360 } else if (debug_str_data_ptr) {
361 uint32_t offset = Value.uval;
362 return debug_str_data_ptr->getCStr(&offset);
363 }
364 return NULL;
365 }
366
367 uint64_t
368 DWARFFormValue::getReference(const DWARFCompileUnit *cu) const {
369 uint64_t die_offset = Value.uval;
370 switch (Form) {
371 case DW_FORM_ref1:
372 case DW_FORM_ref2:
373 case DW_FORM_ref4:
374 case DW_FORM_ref8:
375 case DW_FORM_ref_udata:
376 die_offset += (cu ? cu->getOffset() : 0);
377 break;
378 default:
379 break;
380 }
381
382 return die_offset;
383 }
384
385 bool
386 DWARFFormValue::resolveCompileUnitReferences(const DWARFCompileUnit* cu) {
387 switch (Form) {
388 case DW_FORM_ref1:
389 case DW_FORM_ref2:
390 case DW_FORM_ref4:
391 case DW_FORM_ref8:
392 case DW_FORM_ref_udata:
393 Value.uval += cu->getOffset();
394 Form = DW_FORM_ref_addr;
395 return true;
396 default:
397 break;
398 }
399
400 return false;
401 }
402
403 const uint8_t *DWARFFormValue::BlockData() const {
404 if (!isInlinedCStr())
405 return Value.data;
406 return NULL;
407 }
408
409 bool DWARFFormValue::isBlockForm(uint16_t form) {
410 switch (form)
411 {
412 case DW_FORM_block:
413 case DW_FORM_block1:
414 case DW_FORM_block2:
415 case DW_FORM_block4:
416 return true;
417 }
418 return false;
419 }
420
421 bool DWARFFormValue::isDataForm(uint16_t form) {
422 switch (form)
423 {
424 case DW_FORM_sdata:
425 case DW_FORM_udata:
426 case DW_FORM_data1:
427 case DW_FORM_data2:
428 case DW_FORM_data4:
429 case DW_FORM_data8:
430 return true;
431 }
432 return false;
433 }
0 //===-- DWARFFormValue.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_DWARFFORMVALUE_H
10 #define LLVM_DEBUGINFO_DWARFFORMVALUE_H
11
12 #include "llvm/Support/DataExtractor.h"
13
14 namespace llvm {
15
16 class DWARFCompileUnit;
17 class raw_ostream;
18
19 class DWARFFormValue {
20 public:
21 struct ValueType {
22 ValueType() : data(NULL) {
23 uval = 0;
24 }
25
26 union {
27 uint64_t uval;
28 int64_t sval;
29 const char* cstr;
30 };
31 const uint8_t* data;
32 };
33
34 enum {
35 eValueTypeInvalid = 0,
36 eValueTypeUnsigned,
37 eValueTypeSigned,
38 eValueTypeCStr,
39 eValueTypeBlock
40 };
41
42 private:
43 uint16_t Form; // Form for this value.
44 ValueType Value; // Contains all data for the form.
45
46 public:
47 DWARFFormValue(uint16_t form = 0) : Form(form) {}
48 uint16_t getForm() const { return Form; }
49 const ValueType& value() const { return Value; }
50 void dump(raw_ostream &OS, const DataExtractor *debug_str_data,
51 const DWARFCompileUnit* cu) const;
52 bool extractValue(DataExtractor data, uint32_t *offset_ptr,
53 const DWARFCompileUnit *cu);
54 bool isInlinedCStr() const {
55 return Value.data != NULL && Value.data == (uint8_t*)Value.cstr;
56 }
57 const uint8_t *BlockData() const;
58 uint64_t getReference(const DWARFCompileUnit* cu) const;
59
60 /// Resolve any compile unit specific references so that we don't need
61 /// the compile unit at a later time in order to work with the form
62 /// value.
63 bool resolveCompileUnitReferences(const DWARFCompileUnit* cu);
64 uint64_t getUnsigned() const { return Value.uval; }
65 int64_t getSigned() const { return Value.sval; }
66 const char *getAsCString(const DataExtractor *debug_str_data_ptr) const;
67 bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr,
68 const DWARFCompileUnit *cu) const;
69 static bool skipValue(uint16_t form, DataExtractor debug_info_data,
70 uint32_t *offset_ptr, const DWARFCompileUnit *cu);
71 static bool isBlockForm(uint16_t form);
72 static bool isDataForm(uint16_t form);
73 static const uint8_t *getFixedFormSizesForAddressSize(uint8_t addr_size);
74 };
75
76 }
77
78 #endif
0 ##===- lib/DebugInfo/Makefile ------------------------------*- Makefile -*-===##
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 LEVEL = ../..
10 LIBRARYNAME = LLVMDebugInfo
11 BUILD_ARCHIVE := 1
12
13 include $(LEVEL)/Makefile.common
1010 include $(LEVEL)/Makefile.config
1111
1212 PARALLEL_DIRS := VMCore AsmParser Bitcode Archive Analysis Transforms CodeGen \
13 Target ExecutionEngine Linker MC CompilerDriver Object
13 Target ExecutionEngine Linker MC CompilerDriver Object DebugInfo
1414
1515 include $(LEVEL)/Makefile.common
1616
3838 add_subdirectory(macho-dump)
3939 add_subdirectory(llvm-objdump)
4040 add_subdirectory(llvm-rtdyld)
41 add_subdirectory(llvm-dwarfdump)
4142
4243 add_subdirectory(bugpoint)
4344 add_subdirectory(bugpoint-passes)
2525 lli llvm-extract llvm-mc \
2626 bugpoint llvm-bcanalyzer llvm-stub \
2727 llvmc llvm-diff macho-dump llvm-objdump \
28 llvm-rtdyld
28 llvm-rtdyld llvm-dwarfdump
2929
3030 # Let users override the set of tools to build from the command line.
3131 ifdef ONLY_TOOLS
0 set(LLVM_LINK_COMPONENTS
1 DebugInfo
2 Object
3 )
4
5 add_llvm_tool(llvm-dwarfdump
6 llvm-dwarfdump.cpp
7 )
0 ##===- tools/llvm-dwarfdump/Makefile -----------------------*- Makefile -*-===##
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 LEVEL = ../..
9
10 TOOLNAME = llvm-dwarfdump
11 LINK_COMPONENTS = DebugInfo Object
12
13 # This tool has no plugins, optimize startup time.
14 TOOL_NO_EXPORTS = 1
15
16 include $(LEVEL)/Makefile.common
0 //===-- llvm-dwarfdump.cpp - Debug info dumping utility for llvm -----------===//
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 // This program is a utility that works like "dwarfdump".
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/ADT/OwningPtr.h"
14 #include "llvm/ADT/Triple.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/Object/ObjectFile.h"
17 #include "llvm/DebugInfo/DIContext.h"
18 #include "llvm/Support/CommandLine.h"
19 #include "llvm/Support/Debug.h"
20 #include "llvm/Support/Format.h"
21 #include "llvm/Support/ManagedStatic.h"
22 #include "llvm/Support/MemoryBuffer.h"
23 #include "llvm/Support/MemoryObject.h"
24 #include "llvm/Support/PrettyStackTrace.h"
25 #include "llvm/Support/Signals.h"
26 #include "llvm/Support/raw_ostream.h"
27 #include "llvm/Support/system_error.h"
28 #include
29 #include
30 using namespace llvm;
31 using namespace object;
32
33 static cl::list
34 InputFilenames(cl::Positional, cl::desc(""),
35 cl::ZeroOrMore);
36
37 static void DumpInput(const StringRef &Filename) {
38 OwningPtr Buff;
39
40 if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
41 errs() << Filename << ": " << ec.message() << "\n";
42 return;
43 }
44
45 OwningPtr Obj(ObjectFile::createObjectFile(Buff.take()));
46
47 outs() << '\n';
48 outs() << Filename
49 << ":\tfile format " << Obj->getFileFormatName() << "\n\n";
50
51 StringRef DebugInfoSection;
52 StringRef DebugAbbrevSection;
53 StringRef DebugLineSection;
54
55 error_code ec;
56 for (ObjectFile::section_iterator i = Obj->begin_sections(),
57 e = Obj->end_sections();
58 i != e; i.increment(ec)) {
59 StringRef name;
60 i->getName(name);
61 StringRef data;
62 i->getContents(data);
63 if (name.endswith("debug_info"))
64 DebugInfoSection = data;
65 else if (name.endswith("debug_abbrev"))
66 DebugAbbrevSection = data;
67 else if (name.endswith("debug_line"))
68 DebugLineSection = data;
69 }
70
71 OwningPtr dictx(DIContext::getDWARFContext(/*FIXME*/true,
72 DebugInfoSection,
73 DebugAbbrevSection));
74 dictx->dump(outs());
75 }
76
77 int main(int argc, char **argv) {
78 // Print a stack trace if we signal out.
79 sys::PrintStackTraceOnErrorSignal();
80 PrettyStackTraceProgram X(argc, argv);
81 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
82
83 cl::ParseCommandLineOptions(argc, argv, "llvm dwarf dumper\n");
84
85 // Defaults to a.out if no filenames specified.
86 if (InputFilenames.size() == 0)
87 InputFilenames.push_back("a.out");
88
89 std::for_each(InputFilenames.begin(), InputFilenames.end(), DumpInput);
90
91 return 0;
92 }