Line data Source code
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 "llvm/DebugInfo/DWARFContext.h"
11 : #include "llvm/ADT/SmallString.h"
12 : #include "llvm/ADT/StringSwitch.h"
13 : #include "llvm/DebugInfo/DWARFAcceleratorTable.h"
14 : #include "llvm/DebugInfo/DWARFDebugArangeSet.h"
15 : #include "llvm/Support/Compression.h"
16 : #include "llvm/Support/Dwarf.h"
17 : #include "llvm/Support/Format.h"
18 : #include "llvm/Support/Path.h"
19 : #include "llvm/Support/raw_ostream.h"
20 : #include <algorithm>
21 : using namespace llvm;
22 : using namespace dwarf;
23 : using namespace object;
24 :
25 : #define DEBUG_TYPE "dwarf"
26 :
27 : typedef DWARFDebugLine::LineTable DWARFLineTable;
28 : typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind;
29 : typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind;
30 :
31 380 : static void dumpPubSection(raw_ostream &OS, StringRef Name, StringRef Data,
32 : bool LittleEndian, bool GnuStyle) {
33 380 : OS << "\n." << Name << " contents:\n";
34 380 : DataExtractor pubNames(Data, LittleEndian, 0);
35 380 : uint32_t offset = 0;
36 1316 : while (pubNames.isValidOffset(offset)) {
37 264 : OS << "length = " << format("0x%08x", pubNames.getU32(&offset));
38 264 : OS << " version = " << format("0x%04x", pubNames.getU16(&offset));
39 264 : OS << " unit_offset = " << format("0x%08x", pubNames.getU32(&offset));
40 264 : OS << " unit_size = " << format("0x%08x", pubNames.getU32(&offset)) << '\n';
41 88 : if (GnuStyle)
42 2 : OS << "Offset Linkage Kind Name\n";
43 : else
44 86 : OS << "Offset Name\n";
45 :
46 321 : while (offset < Data.size()) {
47 321 : uint32_t dieRef = pubNames.getU32(&offset);
48 321 : if (dieRef == 0)
49 : break;
50 699 : OS << format("0x%8.8x ", dieRef);
51 233 : if (GnuStyle) {
52 22 : PubIndexEntryDescriptor desc(pubNames.getU8(&offset));
53 66 : OS << format("%-8s", dwarf::GDBIndexEntryLinkageString(desc.Linkage))
54 66 : << ' ' << format("%-8s", dwarf::GDBIndexEntryKindString(desc.Kind))
55 22 : << ' ';
56 : }
57 233 : OS << '\"' << pubNames.getCStr(&offset) << "\"\n";
58 : }
59 : }
60 380 : }
61 :
62 376 : static void dumpAccelSection(raw_ostream &OS, StringRef Name,
63 : const DWARFSection& Section, StringRef StringSection,
64 : bool LittleEndian) {
65 376 : DataExtractor AccelSection(Section.Data, LittleEndian, 0);
66 376 : DataExtractor StrData(StringSection, LittleEndian, 0);
67 376 : OS << "\n." << Name << " contents:\n";
68 376 : DWARFAcceleratorTable Accel(AccelSection, StrData, Section.Relocs);
69 376 : if (!Accel.extract())
70 376 : return;
71 36 : Accel.dump(OS);
72 : }
73 :
74 220 : void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
75 220 : if (DumpType == DIDT_All || DumpType == DIDT_Abbrev) {
76 96 : OS << ".debug_abbrev contents:\n";
77 96 : getDebugAbbrev()->dump(OS);
78 : }
79 :
80 220 : if (DumpType == DIDT_All || DumpType == DIDT_AbbrevDwo)
81 94 : if (const DWARFDebugAbbrev *D = getDebugAbbrevDWO()) {
82 94 : OS << "\n.debug_abbrev.dwo contents:\n";
83 94 : D->dump(OS);
84 : }
85 :
86 220 : if (DumpType == DIDT_All || DumpType == DIDT_Info) {
87 196 : OS << "\n.debug_info contents:\n";
88 394 : for (const auto &CU : compile_units())
89 198 : CU->dump(OS);
90 : }
91 :
92 314 : if ((DumpType == DIDT_All || DumpType == DIDT_InfoDwo) &&
93 : getNumDWOCompileUnits()) {
94 9 : OS << "\n.debug_info.dwo contents:\n";
95 18 : for (const auto &DWOCU : dwo_compile_units())
96 9 : DWOCU->dump(OS);
97 : }
98 :
99 316 : if ((DumpType == DIDT_All || DumpType == DIDT_Types) && getNumTypeUnits()) {
100 4 : OS << "\n.debug_types contents:\n";
101 25 : for (const auto &TUS : type_unit_sections())
102 34 : for (const auto &TU : TUS)
103 17 : TU->dump(OS);
104 : }
105 :
106 314 : if ((DumpType == DIDT_All || DumpType == DIDT_TypesDwo) &&
107 : getNumDWOTypeUnits()) {
108 9 : OS << "\n.debug_types.dwo contents:\n";
109 27 : for (const auto &DWOTUS : dwo_type_unit_sections())
110 16 : for (const auto &DWOTU : DWOTUS)
111 7 : DWOTU->dump(OS);
112 : }
113 :
114 220 : if (DumpType == DIDT_All || DumpType == DIDT_Loc) {
115 97 : OS << "\n.debug_loc contents:\n";
116 97 : getDebugLoc()->dump(OS);
117 : }
118 :
119 220 : if (DumpType == DIDT_All || DumpType == DIDT_LocDwo) {
120 94 : OS << "\n.debug_loc.dwo contents:\n";
121 94 : getDebugLocDWO()->dump(OS);
122 : }
123 :
124 220 : if (DumpType == DIDT_All || DumpType == DIDT_Frames) {
125 95 : OS << "\n.debug_frame contents:\n";
126 95 : getDebugFrame()->dump(OS);
127 : }
128 :
129 220 : uint32_t offset = 0;
130 220 : if (DumpType == DIDT_All || DumpType == DIDT_Aranges) {
131 95 : OS << "\n.debug_aranges contents:\n";
132 95 : DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0);
133 : DWARFDebugArangeSet set;
134 104 : while (set.extract(arangesData, &offset))
135 9 : set.dump(OS);
136 : }
137 :
138 220 : uint8_t savedAddressByteSize = 0;
139 220 : if (DumpType == DIDT_All || DumpType == DIDT_Line) {
140 104 : OS << "\n.debug_line contents:\n";
141 200 : for (const auto &CU : compile_units()) {
142 96 : savedAddressByteSize = CU->getAddressByteSize();
143 : unsigned stmtOffset =
144 : CU->getCompileUnitDIE()->getAttributeValueAsSectionOffset(
145 288 : CU.get(), DW_AT_stmt_list, -1U);
146 96 : if (stmtOffset != -1U) {
147 96 : DataExtractor lineData(getLineSection().Data, isLittleEndian(),
148 : savedAddressByteSize);
149 96 : DWARFDebugLine::LineTable LineTable;
150 96 : LineTable.parse(lineData, &getLineSection().Relocs, &stmtOffset);
151 96 : LineTable.dump(OS);
152 : }
153 : }
154 : }
155 :
156 220 : if (DumpType == DIDT_All || DumpType == DIDT_LineDwo) {
157 94 : OS << "\n.debug_line.dwo contents:\n";
158 94 : unsigned stmtOffset = 0;
159 94 : DataExtractor lineData(getLineDWOSection().Data, isLittleEndian(),
160 : savedAddressByteSize);
161 94 : DWARFDebugLine::LineTable LineTable;
162 197 : while (LineTable.Prologue.parse(lineData, &stmtOffset)) {
163 9 : LineTable.dump(OS);
164 9 : LineTable.clear();
165 94 : }
166 : }
167 :
168 220 : if (DumpType == DIDT_All || DumpType == DIDT_Str) {
169 94 : OS << "\n.debug_str contents:\n";
170 94 : DataExtractor strData(getStringSection(), isLittleEndian(), 0);
171 94 : offset = 0;
172 94 : uint32_t strOffset = 0;
173 794 : while (const char *s = strData.getCStr(&offset)) {
174 2100 : OS << format("0x%8.8x: \"%s\"\n", strOffset, s);
175 700 : strOffset = offset;
176 700 : }
177 : }
178 :
179 660 : if ((DumpType == DIDT_All || DumpType == DIDT_StrDwo) &&
180 408 : !getStringDWOSection().empty()) {
181 9 : OS << "\n.debug_str.dwo contents:\n";
182 9 : DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0);
183 9 : offset = 0;
184 9 : uint32_t strDWOOffset = 0;
185 122 : while (const char *s = strDWOData.getCStr(&offset)) {
186 339 : OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s);
187 113 : strDWOOffset = offset;
188 113 : }
189 : }
190 :
191 220 : if (DumpType == DIDT_All || DumpType == DIDT_Ranges) {
192 95 : OS << "\n.debug_ranges contents:\n";
193 : // In fact, different compile units may have different address byte
194 : // sizes, but for simplicity we just use the address byte size of the last
195 : // compile unit (there is no easy and fast way to associate address range
196 : // list and the compile unit it describes).
197 95 : DataExtractor rangesData(getRangeSection(), isLittleEndian(),
198 95 : savedAddressByteSize);
199 95 : offset = 0;
200 : DWARFDebugRangeList rangeList;
201 143 : while (rangeList.extract(rangesData, &offset))
202 48 : rangeList.dump(OS);
203 : }
204 :
205 220 : if (DumpType == DIDT_All || DumpType == DIDT_Pubnames)
206 98 : dumpPubSection(OS, "debug_pubnames", getPubNamesSection(),
207 294 : isLittleEndian(), false);
208 :
209 220 : if (DumpType == DIDT_All || DumpType == DIDT_Pubtypes)
210 94 : dumpPubSection(OS, "debug_pubtypes", getPubTypesSection(),
211 282 : isLittleEndian(), false);
212 :
213 220 : if (DumpType == DIDT_All || DumpType == DIDT_GnuPubnames)
214 94 : dumpPubSection(OS, "debug_gnu_pubnames", getGnuPubNamesSection(),
215 282 : isLittleEndian(), true /* GnuStyle */);
216 :
217 220 : if (DumpType == DIDT_All || DumpType == DIDT_GnuPubtypes)
218 94 : dumpPubSection(OS, "debug_gnu_pubtypes", getGnuPubTypesSection(),
219 282 : isLittleEndian(), true /* GnuStyle */);
220 :
221 660 : if ((DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) &&
222 408 : !getStringOffsetDWOSection().empty()) {
223 9 : OS << "\n.debug_str_offsets.dwo contents:\n";
224 9 : DataExtractor strOffsetExt(getStringOffsetDWOSection(), isLittleEndian(),
225 9 : 0);
226 9 : offset = 0;
227 9 : uint64_t size = getStringOffsetDWOSection().size();
228 131 : while (offset < size) {
229 339 : OS << format("0x%8.8x: ", offset);
230 339 : OS << format("%8.8x\n", strOffsetExt.getU32(&offset));
231 : }
232 : }
233 :
234 220 : if (DumpType == DIDT_All || DumpType == DIDT_AppleNames)
235 94 : dumpAccelSection(OS, "apple_names", getAppleNamesSection(),
236 188 : getStringSection(), isLittleEndian());
237 :
238 220 : if (DumpType == DIDT_All || DumpType == DIDT_AppleTypes)
239 94 : dumpAccelSection(OS, "apple_types", getAppleTypesSection(),
240 188 : getStringSection(), isLittleEndian());
241 :
242 220 : if (DumpType == DIDT_All || DumpType == DIDT_AppleNamespaces)
243 94 : dumpAccelSection(OS, "apple_namespaces", getAppleNamespacesSection(),
244 188 : getStringSection(), isLittleEndian());
245 :
246 220 : if (DumpType == DIDT_All || DumpType == DIDT_AppleObjC)
247 94 : dumpAccelSection(OS, "apple_objc", getAppleObjCSection(),
248 188 : getStringSection(), isLittleEndian());
249 220 : }
250 :
251 1120 : const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
252 2240 : if (Abbrev)
253 : return Abbrev.get();
254 :
255 358 : DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0);
256 :
257 358 : Abbrev.reset(new DWARFDebugAbbrev());
258 716 : Abbrev->extract(abbrData);
259 716 : return Abbrev.get();
260 : }
261 :
262 208 : const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() {
263 416 : if (AbbrevDWO)
264 : return AbbrevDWO.get();
265 :
266 95 : DataExtractor abbrData(getAbbrevDWOSection(), isLittleEndian(), 0);
267 95 : AbbrevDWO.reset(new DWARFDebugAbbrev());
268 190 : AbbrevDWO->extract(abbrData);
269 190 : return AbbrevDWO.get();
270 : }
271 :
272 97 : const DWARFDebugLoc *DWARFContext::getDebugLoc() {
273 194 : if (Loc)
274 : return Loc.get();
275 :
276 97 : DataExtractor LocData(getLocSection().Data, isLittleEndian(), 0);
277 194 : Loc.reset(new DWARFDebugLoc(getLocSection().Relocs));
278 : // assume all compile units have the same address byte size
279 97 : if (getNumCompileUnits())
280 162 : Loc->parse(LocData, getCompileUnitAtIndex(0)->getAddressByteSize());
281 194 : return Loc.get();
282 : }
283 :
284 94 : const DWARFDebugLocDWO *DWARFContext::getDebugLocDWO() {
285 188 : if (LocDWO)
286 : return LocDWO.get();
287 :
288 94 : DataExtractor LocData(getLocDWOSection().Data, isLittleEndian(), 0);
289 188 : LocDWO.reset(new DWARFDebugLocDWO());
290 188 : LocDWO->parse(LocData);
291 188 : return LocDWO.get();
292 : }
293 :
294 376 : const DWARFDebugAranges *DWARFContext::getDebugAranges() {
295 752 : if (Aranges)
296 : return Aranges.get();
297 :
298 278 : Aranges.reset(new DWARFDebugAranges());
299 278 : Aranges->generate(this);
300 278 : return Aranges.get();
301 : }
302 :
303 95 : const DWARFDebugFrame *DWARFContext::getDebugFrame() {
304 190 : if (DebugFrame)
305 : return DebugFrame.get();
306 :
307 : // There's a "bug" in the DWARFv3 standard with respect to the target address
308 : // size within debug frame sections. While DWARF is supposed to be independent
309 : // of its container, FDEs have fields with size being "target address size",
310 : // which isn't specified in DWARF in general. It's only specified for CUs, but
311 : // .eh_frame can appear without a .debug_info section. Follow the example of
312 : // other tools (libdwarf) and extract this from the container (ObjectFile
313 : // provides this information). This problem is fixed in DWARFv4
314 : // See this dwarf-discuss discussion for more details:
315 : // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html
316 95 : DataExtractor debugFrameData(getDebugFrameSection(), isLittleEndian(),
317 190 : getAddressSize());
318 95 : DebugFrame.reset(new DWARFDebugFrame());
319 190 : DebugFrame->parse(debugFrameData);
320 190 : return DebugFrame.get();
321 : }
322 :
323 : const DWARFLineTable *
324 1373 : DWARFContext::getLineTableForUnit(DWARFUnit *cu) {
325 2746 : if (!Line)
326 462 : Line.reset(new DWARFDebugLine(&getLineSection().Relocs));
327 :
328 : unsigned stmtOffset =
329 : cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset(
330 1373 : cu, DW_AT_stmt_list, -1U);
331 1373 : if (stmtOffset == -1U)
332 : return nullptr; // No line table for this compile unit.
333 :
334 : // See if the line table is cached.
335 2608 : if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset))
336 : return lt;
337 :
338 : // We have to parse it first.
339 323 : DataExtractor lineData(getLineSection().Data, isLittleEndian(),
340 323 : cu->getAddressByteSize());
341 646 : return Line->getOrParseLineTable(lineData, stmtOffset);
342 : }
343 :
344 1007 : void DWARFContext::parseCompileUnits() {
345 1007 : CUs.parse(*this, getInfoSection());
346 1007 : }
347 :
348 100 : void DWARFContext::parseTypeUnits() {
349 200 : if (!TUs.empty())
350 100 : return;
351 401 : for (const auto &I : getTypesSections()) {
352 34 : TUs.push_back(DWARFUnitSection<DWARFTypeUnit>());
353 34 : TUs.back().parse(*this, I.second);
354 : }
355 : }
356 :
357 105 : void DWARFContext::parseDWOCompileUnits() {
358 105 : DWOCUs.parseDWO(*this, getInfoDWOSection());
359 105 : }
360 :
361 103 : void DWARFContext::parseDWOTypeUnits() {
362 206 : if (!DWOTUs.empty())
363 103 : return;
364 385 : for (const auto &I : getTypesDWOSections()) {
365 18 : DWOTUs.push_back(DWARFUnitSection<DWARFTypeUnit>());
366 18 : DWOTUs.back().parseDWO(*this, I.second);
367 : }
368 : }
369 :
370 376 : DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) {
371 376 : parseCompileUnits();
372 752 : return CUs.getUnitForOffset(Offset);
373 : }
374 :
375 376 : DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) {
376 : // First, get the offset of the compile unit.
377 376 : uint32_t CUOffset = getDebugAranges()->findAddress(Address);
378 : // Retrieve the compile unit.
379 376 : return getCompileUnitForOffset(CUOffset);
380 : }
381 :
382 6 : static bool getFunctionNameForAddress(DWARFCompileUnit *CU, uint64_t Address,
383 : FunctionNameKind Kind,
384 : std::string &FunctionName) {
385 6 : if (Kind == FunctionNameKind::None)
386 : return false;
387 : // The address may correspond to instruction in some inlined function,
388 : // so we have to build the chain of inlined functions and take the
389 : // name of the topmost function in it.
390 : const DWARFDebugInfoEntryInlinedChain &InlinedChain =
391 0 : CU->getInlinedChainForAddress(Address);
392 0 : if (InlinedChain.DIEs.size() == 0)
393 : return false;
394 0 : const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0];
395 0 : if (const char *Name =
396 0 : TopFunctionDIE.getSubroutineName(InlinedChain.U, Kind)) {
397 : FunctionName = Name;
398 0 : return true;
399 : }
400 : return false;
401 : }
402 :
403 0 : DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address,
404 : DILineInfoSpecifier Spec) {
405 0 : DILineInfo Result;
406 :
407 0 : DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
408 0 : if (!CU)
409 : return Result;
410 0 : getFunctionNameForAddress(CU, Address, Spec.FNKind, Result.FunctionName);
411 0 : if (Spec.FLIKind != FileLineInfoKind::None) {
412 0 : if (const DWARFLineTable *LineTable = getLineTableForUnit(CU))
413 : LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(),
414 0 : Spec.FLIKind, Result);
415 : }
416 : return Result;
417 : }
418 :
419 : DILineInfoTable
420 6 : DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
421 : DILineInfoSpecifier Spec) {
422 : DILineInfoTable Lines;
423 6 : DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
424 6 : if (!CU)
425 : return Lines;
426 :
427 12 : std::string FunctionName = "<invalid>";
428 6 : getFunctionNameForAddress(CU, Address, Spec.FNKind, FunctionName);
429 :
430 : // If the Specifier says we don't need FileLineInfo, just
431 : // return the top-most function at the starting address.
432 6 : if (Spec.FLIKind == FileLineInfoKind::None) {
433 0 : DILineInfo Result;
434 : Result.FunctionName = FunctionName;
435 0 : Lines.push_back(std::make_pair(Address, Result));
436 0 : return Lines;
437 : }
438 :
439 6 : const DWARFLineTable *LineTable = getLineTableForUnit(CU);
440 :
441 : // Get the index of row we're looking for in the line table.
442 : std::vector<uint32_t> RowVector;
443 6 : if (!LineTable->lookupAddressRange(Address, Size, RowVector))
444 : return Lines;
445 :
446 55 : for (uint32_t RowIndex : RowVector) {
447 : // Take file number and line/column from the row.
448 62 : const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex];
449 31 : DILineInfo Result;
450 : LineTable->getFileNameByIndex(Row.File, CU->getCompilationDir(),
451 31 : Spec.FLIKind, Result.FileName);
452 : Result.FunctionName = FunctionName;
453 31 : Result.Line = Row.Line;
454 31 : Result.Column = Row.Column;
455 93 : Lines.push_back(std::make_pair(Row.Address, Result));
456 31 : }
457 :
458 : return Lines;
459 : }
460 :
461 : DIInliningInfo
462 370 : DWARFContext::getInliningInfoForAddress(uint64_t Address,
463 : DILineInfoSpecifier Spec) {
464 : DIInliningInfo InliningInfo;
465 :
466 370 : DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
467 370 : if (!CU)
468 : return InliningInfo;
469 :
470 219 : const DWARFLineTable *LineTable = nullptr;
471 : const DWARFDebugInfoEntryInlinedChain &InlinedChain =
472 219 : CU->getInlinedChainForAddress(Address);
473 438 : if (InlinedChain.DIEs.size() == 0) {
474 : // If there is no DIE for address (e.g. it is in unavailable .dwo file),
475 : // try to at least get file/line info from symbol table.
476 2 : if (Spec.FLIKind != FileLineInfoKind::None) {
477 2 : DILineInfo Frame;
478 2 : LineTable = getLineTableForUnit(CU);
479 4 : if (LineTable &&
480 : LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(),
481 2 : Spec.FLIKind, Frame))
482 2 : InliningInfo.addFrame(Frame);
483 : }
484 : return InliningInfo;
485 : }
486 :
487 217 : uint32_t CallFile = 0, CallLine = 0, CallColumn = 0;
488 715 : for (uint32_t i = 0, n = InlinedChain.DIEs.size(); i != n; i++) {
489 562 : const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain.DIEs[i];
490 281 : DILineInfo Frame;
491 : // Get function name if necessary.
492 281 : if (const char *Name =
493 281 : FunctionDIE.getSubroutineName(InlinedChain.U, Spec.FNKind))
494 : Frame.FunctionName = Name;
495 281 : if (Spec.FLIKind != FileLineInfoKind::None) {
496 281 : if (i == 0) {
497 : // For the topmost frame, initialize the line table of this
498 : // compile unit and fetch file/line info from it.
499 217 : LineTable = getLineTableForUnit(CU);
500 : // For the topmost routine, get file/line info from line table.
501 217 : if (LineTable)
502 : LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(),
503 217 : Spec.FLIKind, Frame);
504 : } else {
505 : // Otherwise, use call file, call line and call column from
506 : // previous DIE in inlined chain.
507 64 : if (LineTable)
508 : LineTable->getFileNameByIndex(CallFile, CU->getCompilationDir(),
509 64 : Spec.FLIKind, Frame.FileName);
510 64 : Frame.Line = CallLine;
511 64 : Frame.Column = CallColumn;
512 : }
513 : // Get call file/line/column of a current DIE.
514 281 : if (i + 1 < n) {
515 : FunctionDIE.getCallerFrame(InlinedChain.U, CallFile, CallLine,
516 64 : CallColumn);
517 : }
518 : }
519 : InliningInfo.addFrame(Frame);
520 281 : }
521 : return InliningInfo;
522 : }
523 :
524 20 : static bool consumeCompressedDebugSectionHeader(StringRef &data,
525 : uint64_t &OriginalSize) {
526 : // Consume "ZLIB" prefix.
527 20 : if (!data.startswith("ZLIB"))
528 : return false;
529 20 : data = data.substr(4);
530 : // Consume uncompressed section size (big-endian 8 bytes).
531 : DataExtractor extractor(data, false, 8);
532 20 : uint32_t Offset = 0;
533 20 : OriginalSize = extractor.getU64(&Offset);
534 20 : if (Offset == 0)
535 : return false;
536 40 : data = data.substr(Offset);
537 20 : return true;
538 : }
539 :
540 367 : DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj)
541 367 : : IsLittleEndian(Obj.isLittleEndian()),
542 10276 : AddressSize(Obj.getBytesInAddress()) {
543 11708 : for (const SectionRef &Section : Obj.sections()) {
544 : StringRef name;
545 : Section.getName(name);
546 : // Skip BSS and Virtual sections, they aren't interesting.
547 10240 : bool IsBSS = Section.isBSS();
548 10240 : if (IsBSS)
549 9436 : continue;
550 9910 : bool IsVirtual = Section.isVirtual();
551 9910 : if (IsVirtual)
552 : continue;
553 : StringRef data;
554 : Section.getContents(data);
555 :
556 19820 : name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.
557 :
558 : // Check if debug info section is compressed with zlib.
559 9910 : if (name.startswith("zdebug_")) {
560 : uint64_t OriginalSize;
561 40 : if (!zlib::isAvailable() ||
562 20 : !consumeCompressedDebugSectionHeader(data, OriginalSize))
563 0 : continue;
564 40 : UncompressedSections.resize(UncompressedSections.size() + 1);
565 40 : if (zlib::uncompress(data, UncompressedSections.back(), OriginalSize) !=
566 : zlib::StatusOK) {
567 0 : UncompressedSections.pop_back();
568 : continue;
569 : }
570 : // Make data point to uncompressed section contents and save its contents.
571 20 : name = name.substr(1);
572 60 : data = UncompressedSections.back();
573 : }
574 :
575 : StringRef *SectionData =
576 : StringSwitch<StringRef *>(name)
577 29730 : .Case("debug_info", &InfoSection.Data)
578 29730 : .Case("debug_abbrev", &AbbrevSection)
579 29730 : .Case("debug_loc", &LocSection.Data)
580 29730 : .Case("debug_line", &LineSection.Data)
581 29730 : .Case("debug_aranges", &ARangeSection)
582 29730 : .Case("debug_frame", &DebugFrameSection)
583 29730 : .Case("debug_str", &StringSection)
584 29730 : .Case("debug_ranges", &RangeSection)
585 29730 : .Case("debug_pubnames", &PubNamesSection)
586 29730 : .Case("debug_pubtypes", &PubTypesSection)
587 29730 : .Case("debug_gnu_pubnames", &GnuPubNamesSection)
588 29730 : .Case("debug_gnu_pubtypes", &GnuPubTypesSection)
589 29730 : .Case("debug_info.dwo", &InfoDWOSection.Data)
590 29730 : .Case("debug_abbrev.dwo", &AbbrevDWOSection)
591 29730 : .Case("debug_loc.dwo", &LocDWOSection.Data)
592 29730 : .Case("debug_line.dwo", &LineDWOSection.Data)
593 29730 : .Case("debug_str.dwo", &StringDWOSection)
594 29730 : .Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
595 29730 : .Case("debug_addr", &AddrSection)
596 29730 : .Case("apple_names", &AppleNamesSection.Data)
597 29730 : .Case("apple_types", &AppleTypesSection.Data)
598 29730 : .Case("apple_namespaces", &AppleNamespacesSection.Data)
599 29730 : .Case("apple_namespac", &AppleNamespacesSection.Data)
600 29730 : .Case("apple_objc", &AppleObjCSection.Data)
601 : // Any more debug info sections go here.
602 19820 : .Default(nullptr);
603 9910 : if (SectionData) {
604 2455 : *SectionData = data;
605 2455 : if (name == "debug_ranges") {
606 : // FIXME: Use the other dwo range section when we emit it.
607 265 : RangeDWOSection = data;
608 : }
609 7455 : } else if (name == "debug_types") {
610 : // Find debug_types data by section rather than name as there are
611 : // multiple, comdat grouped, debug_types sections.
612 17 : TypesSections[Section].Data = data;
613 7438 : } else if (name == "debug_types.dwo") {
614 13 : TypesDWOSections[Section].Data = data;
615 : }
616 :
617 9910 : section_iterator RelocatedSection = Section.getRelocatedSection();
618 19820 : if (RelocatedSection == Obj.section_end())
619 : continue;
620 :
621 : StringRef RelSecName;
622 1767 : RelocatedSection->getName(RelSecName);
623 : RelSecName = RelSecName.substr(
624 3534 : RelSecName.find_first_not_of("._")); // Skip . and _ prefixes.
625 :
626 : // TODO: Add support for relocations in other sections as needed.
627 : // Record relocations for the debug_info and debug_line sections.
628 : RelocAddrMap *Map = StringSwitch<RelocAddrMap*>(RelSecName)
629 5301 : .Case("debug_info", &InfoSection.Relocs)
630 5301 : .Case("debug_loc", &LocSection.Relocs)
631 5301 : .Case("debug_info.dwo", &InfoDWOSection.Relocs)
632 5301 : .Case("debug_line", &LineSection.Relocs)
633 5301 : .Case("apple_names", &AppleNamesSection.Relocs)
634 5301 : .Case("apple_types", &AppleTypesSection.Relocs)
635 5301 : .Case("apple_namespaces", &AppleNamespacesSection.Relocs)
636 5301 : .Case("apple_namespac", &AppleNamespacesSection.Relocs)
637 5301 : .Case("apple_objc", &AppleObjCSection.Relocs)
638 3534 : .Default(nullptr);
639 1767 : if (!Map) {
640 : // Find debug_types relocs by section rather than name as there are
641 : // multiple, comdat grouped, debug_types sections.
642 980 : if (RelSecName == "debug_types")
643 17 : Map = &TypesSections[*RelocatedSection].Relocs;
644 963 : else if (RelSecName == "debug_types.dwo")
645 0 : Map = &TypesDWOSections[*RelocatedSection].Relocs;
646 : else
647 : continue;
648 : }
649 :
650 2412 : if (Section.relocation_begin() != Section.relocation_end()) {
651 852 : uint64_t SectionSize = RelocatedSection->getSize();
652 4680 : for (const RelocationRef &Reloc : Section.relocations()) {
653 : uint64_t Address;
654 : Reloc.getOffset(Address);
655 : uint64_t Type;
656 : Reloc.getType(Type);
657 2976 : uint64_t SymAddr = 0;
658 2976 : object::symbol_iterator Sym = Reloc.getSymbol();
659 8928 : if (Sym != Obj.symbol_end())
660 2330 : Sym->getAddress(SymAddr);
661 :
662 : object::RelocVisitor V(Obj);
663 2976 : object::RelocToApply R(V.visit(Type, Reloc, SymAddr));
664 2976 : if (V.error()) {
665 : SmallString<32> Name;
666 671 : std::error_code ec(Reloc.getTypeName(Name));
667 671 : if (ec) {
668 0 : errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n";
669 : }
670 671 : errs() << "error: failed to compute relocation: "
671 671 : << Name << "\n";
672 : continue;
673 : }
674 :
675 2305 : if (Address + R.Width > SectionSize) {
676 0 : errs() << "error: " << R.Width << "-byte relocation starting "
677 0 : << Address << " bytes into section " << name << " which is "
678 0 : << SectionSize << " bytes long.\n";
679 0 : continue;
680 : }
681 2305 : if (R.Width > 8) {
682 0 : errs() << "error: can't handle a relocation of more than 8 bytes at "
683 0 : "a time.\n";
684 0 : continue;
685 : }
686 : DEBUG(dbgs() << "Writing " << format("%p", R.Value)
687 : << " at " << format("%p", Address)
688 : << " with width " << format("%d", R.Width)
689 : << "\n");
690 6915 : Map->insert(std::make_pair(Address, std::make_pair(R.Width, R.Value)));
691 : }
692 : }
693 : }
694 367 : }
695 :
696 0 : void DWARFContextInMemory::anchor() { }
|