]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/DebugInfo/DWARFContext.cpp
MFV r248590,248594:
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / DebugInfo / DWARFContext.cpp
1 //===-- DWARFContext.cpp --------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "DWARFContext.h"
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/Support/Dwarf.h"
13 #include "llvm/Support/Format.h"
14 #include "llvm/Support/Path.h"
15 #include "llvm/Support/raw_ostream.h"
16 #include <algorithm>
17 using namespace llvm;
18 using namespace dwarf;
19
20 typedef DWARFDebugLine::LineTable DWARFLineTable;
21
22 void DWARFContext::dump(raw_ostream &OS) {
23   OS << ".debug_abbrev contents:\n";
24   getDebugAbbrev()->dump(OS);
25
26   OS << "\n.debug_info contents:\n";
27   for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i)
28     getCompileUnitAtIndex(i)->dump(OS);
29
30   OS << "\n.debug_aranges contents:\n";
31   DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0);
32   uint32_t offset = 0;
33   DWARFDebugArangeSet set;
34   while (set.extract(arangesData, &offset))
35     set.dump(OS);
36
37   uint8_t savedAddressByteSize = 0;
38   OS << "\n.debug_lines contents:\n";
39   for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) {
40     DWARFCompileUnit *cu = getCompileUnitAtIndex(i);
41     savedAddressByteSize = cu->getAddressByteSize();
42     unsigned stmtOffset =
43       cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
44                                                            -1U);
45     if (stmtOffset != -1U) {
46       DataExtractor lineData(getLineSection(), isLittleEndian(),
47                              savedAddressByteSize);
48       DWARFDebugLine::DumpingState state(OS);
49       DWARFDebugLine::parseStatementTable(lineData, &stmtOffset, state);
50     }
51   }
52
53   OS << "\n.debug_str contents:\n";
54   DataExtractor strData(getStringSection(), isLittleEndian(), 0);
55   offset = 0;
56   uint32_t lastOffset = 0;
57   while (const char *s = strData.getCStr(&offset)) {
58     OS << format("0x%8.8x: \"%s\"\n", lastOffset, s);
59     lastOffset = offset;
60   }
61
62   OS << "\n.debug_ranges contents:\n";
63   // In fact, different compile units may have different address byte
64   // sizes, but for simplicity we just use the address byte size of the last
65   // compile unit (there is no easy and fast way to associate address range
66   // list and the compile unit it describes).
67   DataExtractor rangesData(getRangeSection(), isLittleEndian(),
68                            savedAddressByteSize);
69   offset = 0;
70   DWARFDebugRangeList rangeList;
71   while (rangeList.extract(rangesData, &offset))
72     rangeList.dump(OS);
73 }
74
75 const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
76   if (Abbrev)
77     return Abbrev.get();
78
79   DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0);
80
81   Abbrev.reset(new DWARFDebugAbbrev());
82   Abbrev->parse(abbrData);
83   return Abbrev.get();
84 }
85
86 const DWARFDebugAranges *DWARFContext::getDebugAranges() {
87   if (Aranges)
88     return Aranges.get();
89
90   DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0);
91
92   Aranges.reset(new DWARFDebugAranges());
93   Aranges->extract(arangesData);
94   if (Aranges->isEmpty()) // No aranges in file, generate them from the DIEs.
95     Aranges->generate(this);
96   return Aranges.get();
97 }
98
99 const DWARFLineTable *
100 DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
101   if (!Line)
102     Line.reset(new DWARFDebugLine());
103
104   unsigned stmtOffset =
105     cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
106                                                          -1U);
107   if (stmtOffset == -1U)
108     return 0; // No line table for this compile unit.
109
110   // See if the line table is cached.
111   if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset))
112     return lt;
113
114   // We have to parse it first.
115   DataExtractor lineData(getLineSection(), isLittleEndian(),
116                          cu->getAddressByteSize());
117   return Line->getOrParseLineTable(lineData, stmtOffset);
118 }
119
120 void DWARFContext::parseCompileUnits() {
121   uint32_t offset = 0;
122   const DataExtractor &DIData = DataExtractor(getInfoSection(),
123                                               isLittleEndian(), 0);
124   while (DIData.isValidOffset(offset)) {
125     CUs.push_back(DWARFCompileUnit(*this));
126     if (!CUs.back().extract(DIData, &offset)) {
127       CUs.pop_back();
128       break;
129     }
130
131     offset = CUs.back().getNextCompileUnitOffset();
132   }
133 }
134
135 namespace {
136   struct OffsetComparator {
137     bool operator()(const DWARFCompileUnit &LHS,
138                     const DWARFCompileUnit &RHS) const {
139       return LHS.getOffset() < RHS.getOffset();
140     }
141     bool operator()(const DWARFCompileUnit &LHS, uint32_t RHS) const {
142       return LHS.getOffset() < RHS;
143     }
144     bool operator()(uint32_t LHS, const DWARFCompileUnit &RHS) const {
145       return LHS < RHS.getOffset();
146     }
147   };
148 }
149
150 DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) {
151   if (CUs.empty())
152     parseCompileUnits();
153
154   DWARFCompileUnit *CU = std::lower_bound(CUs.begin(), CUs.end(), Offset,
155                                           OffsetComparator());
156   if (CU != CUs.end())
157     return &*CU;
158   return 0;
159 }
160
161 DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) {
162   // First, get the offset of the compile unit.
163   uint32_t CUOffset = getDebugAranges()->findAddress(Address);
164   // Retrieve the compile unit.
165   return getCompileUnitForOffset(CUOffset);
166 }
167
168 static bool getFileNameForCompileUnit(DWARFCompileUnit *CU,
169                                       const DWARFLineTable *LineTable,
170                                       uint64_t FileIndex,
171                                       bool NeedsAbsoluteFilePath,
172                                       std::string &FileName) {
173   if (CU == 0 ||
174       LineTable == 0 ||
175       !LineTable->getFileNameByIndex(FileIndex, NeedsAbsoluteFilePath,
176                                      FileName))
177     return false;
178   if (NeedsAbsoluteFilePath && sys::path::is_relative(FileName)) {
179     // We may still need to append compilation directory of compile unit.
180     SmallString<16> AbsolutePath;
181     if (const char *CompilationDir = CU->getCompilationDir()) {
182       sys::path::append(AbsolutePath, CompilationDir);
183     }
184     sys::path::append(AbsolutePath, FileName);
185     FileName = AbsolutePath.str();
186   }
187   return true;
188 }
189
190 static bool getFileLineInfoForCompileUnit(DWARFCompileUnit *CU,
191                                           const DWARFLineTable *LineTable,
192                                           uint64_t Address,
193                                           bool NeedsAbsoluteFilePath,
194                                           std::string &FileName,
195                                           uint32_t &Line, uint32_t &Column) {
196   if (CU == 0 || LineTable == 0)
197     return false;
198   // Get the index of row we're looking for in the line table.
199   uint32_t RowIndex = LineTable->lookupAddress(Address);
200   if (RowIndex == -1U)
201     return false;
202   // Take file number and line/column from the row.
203   const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex];
204   if (!getFileNameForCompileUnit(CU, LineTable, Row.File,
205                                  NeedsAbsoluteFilePath, FileName))
206     return false;
207   Line = Row.Line;
208   Column = Row.Column;
209   return true;
210 }
211
212 DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address,
213     DILineInfoSpecifier Specifier) {
214   DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
215   if (!CU)
216     return DILineInfo();
217   std::string FileName = "<invalid>";
218   std::string FunctionName = "<invalid>";
219   uint32_t Line = 0;
220   uint32_t Column = 0;
221   if (Specifier.needs(DILineInfoSpecifier::FunctionName)) {
222     // The address may correspond to instruction in some inlined function,
223     // so we have to build the chain of inlined functions and take the
224     // name of the topmost function in it.
225     const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain =
226         CU->getInlinedChainForAddress(Address);
227     if (InlinedChain.size() > 0) {
228       const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain[0];
229       if (const char *Name = TopFunctionDIE.getSubroutineName(CU))
230         FunctionName = Name;
231     }
232   }
233   if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
234     const DWARFLineTable *LineTable = getLineTableForCompileUnit(CU);
235     const bool NeedsAbsoluteFilePath =
236         Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath);
237     getFileLineInfoForCompileUnit(CU, LineTable, Address,
238                                   NeedsAbsoluteFilePath,
239                                   FileName, Line, Column);
240   }
241   return DILineInfo(StringRef(FileName), StringRef(FunctionName),
242                     Line, Column);
243 }
244
245 DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address,
246     DILineInfoSpecifier Specifier) {
247   DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
248   if (!CU)
249     return DIInliningInfo();
250
251   const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain =
252       CU->getInlinedChainForAddress(Address);
253   if (InlinedChain.size() == 0)
254     return DIInliningInfo();
255
256   DIInliningInfo InliningInfo;
257   uint32_t CallFile = 0, CallLine = 0, CallColumn = 0;
258   const DWARFLineTable *LineTable = 0;
259   for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) {
260     const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain[i];
261     std::string FileName = "<invalid>";
262     std::string FunctionName = "<invalid>";
263     uint32_t Line = 0;
264     uint32_t Column = 0;
265     // Get function name if necessary.
266     if (Specifier.needs(DILineInfoSpecifier::FunctionName)) {
267       if (const char *Name = FunctionDIE.getSubroutineName(CU))
268         FunctionName = Name;
269     }
270     if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
271       const bool NeedsAbsoluteFilePath =
272           Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath);
273       if (i == 0) {
274         // For the topmost frame, initialize the line table of this
275         // compile unit and fetch file/line info from it.
276         LineTable = getLineTableForCompileUnit(CU);
277         // For the topmost routine, get file/line info from line table.
278         getFileLineInfoForCompileUnit(CU, LineTable, Address,
279                                       NeedsAbsoluteFilePath,
280                                       FileName, Line, Column);
281       } else {
282         // Otherwise, use call file, call line and call column from
283         // previous DIE in inlined chain.
284         getFileNameForCompileUnit(CU, LineTable, CallFile,
285                                   NeedsAbsoluteFilePath, FileName);
286         Line = CallLine;
287         Column = CallColumn;
288       }
289       // Get call file/line/column of a current DIE.
290       if (i + 1 < n) {
291         FunctionDIE.getCallerFrame(CU, CallFile, CallLine, CallColumn);
292       }
293     }
294     DILineInfo Frame(StringRef(FileName), StringRef(FunctionName),
295                      Line, Column);
296     InliningInfo.addFrame(Frame);
297   }
298   return InliningInfo;
299 }
300
301 void DWARFContextInMemory::anchor() { }