LCOV - code coverage report
Current view: top level - lib/DebugInfo - DWARFContext.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 364 393 92.6 %
Date: 2015-01-30 11:55:44 Functions: 21 23 91.3 %
Legend: Lines: hit not hit

          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() { }

Generated by: LCOV version 1.11