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