LLVM API Documentation
00001 //===-- DWARFContext.cpp --------------------------------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "DWARFContext.h" 00011 #include "DWARFDebugArangeSet.h" 00012 00013 #include "llvm/ADT/SmallString.h" 00014 #include "llvm/ADT/StringSwitch.h" 00015 #include "llvm/Support/Compression.h" 00016 #include "llvm/Support/Dwarf.h" 00017 #include "llvm/Support/Format.h" 00018 #include "llvm/Support/Path.h" 00019 #include "llvm/Support/raw_ostream.h" 00020 #include <algorithm> 00021 using namespace llvm; 00022 using namespace dwarf; 00023 using namespace object; 00024 00025 #define DEBUG_TYPE "dwarf" 00026 00027 typedef DWARFDebugLine::LineTable DWARFLineTable; 00028 typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind; 00029 typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind; 00030 00031 static void dumpPubSection(raw_ostream &OS, StringRef Name, StringRef Data, 00032 bool LittleEndian, bool GnuStyle) { 00033 OS << "\n." << Name << " contents:\n"; 00034 DataExtractor pubNames(Data, LittleEndian, 0); 00035 uint32_t offset = 0; 00036 while (pubNames.isValidOffset(offset)) { 00037 OS << "length = " << format("0x%08x", pubNames.getU32(&offset)); 00038 OS << " version = " << format("0x%04x", pubNames.getU16(&offset)); 00039 OS << " unit_offset = " << format("0x%08x", pubNames.getU32(&offset)); 00040 OS << " unit_size = " << format("0x%08x", pubNames.getU32(&offset)) << '\n'; 00041 if (GnuStyle) 00042 OS << "Offset Linkage Kind Name\n"; 00043 else 00044 OS << "Offset Name\n"; 00045 00046 while (offset < Data.size()) { 00047 uint32_t dieRef = pubNames.getU32(&offset); 00048 if (dieRef == 0) 00049 break; 00050 OS << format("0x%8.8x ", dieRef); 00051 if (GnuStyle) { 00052 PubIndexEntryDescriptor desc(pubNames.getU8(&offset)); 00053 OS << format("%-8s", dwarf::GDBIndexEntryLinkageString(desc.Linkage)) 00054 << ' ' << format("%-8s", dwarf::GDBIndexEntryKindString(desc.Kind)) 00055 << ' '; 00056 } 00057 OS << '\"' << pubNames.getCStr(&offset) << "\"\n"; 00058 } 00059 } 00060 } 00061 00062 void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { 00063 if (DumpType == DIDT_All || DumpType == DIDT_Abbrev) { 00064 OS << ".debug_abbrev contents:\n"; 00065 getDebugAbbrev()->dump(OS); 00066 } 00067 00068 if (DumpType == DIDT_All || DumpType == DIDT_AbbrevDwo) 00069 if (const DWARFDebugAbbrev *D = getDebugAbbrevDWO()) { 00070 OS << "\n.debug_abbrev.dwo contents:\n"; 00071 D->dump(OS); 00072 } 00073 00074 if (DumpType == DIDT_All || DumpType == DIDT_Info) { 00075 OS << "\n.debug_info contents:\n"; 00076 for (const auto &CU : compile_units()) 00077 CU->dump(OS); 00078 } 00079 00080 if ((DumpType == DIDT_All || DumpType == DIDT_InfoDwo) && 00081 getNumDWOCompileUnits()) { 00082 OS << "\n.debug_info.dwo contents:\n"; 00083 for (const auto &DWOCU : dwo_compile_units()) 00084 DWOCU->dump(OS); 00085 } 00086 00087 if ((DumpType == DIDT_All || DumpType == DIDT_Types) && getNumTypeUnits()) { 00088 OS << "\n.debug_types contents:\n"; 00089 for (const auto &TU : type_units()) 00090 TU->dump(OS); 00091 } 00092 00093 if ((DumpType == DIDT_All || DumpType == DIDT_TypesDwo) && 00094 getNumDWOTypeUnits()) { 00095 OS << "\n.debug_types.dwo contents:\n"; 00096 for (const auto &DWOTU : dwo_type_units()) 00097 DWOTU->dump(OS); 00098 } 00099 00100 if (DumpType == DIDT_All || DumpType == DIDT_Loc) { 00101 OS << "\n.debug_loc contents:\n"; 00102 getDebugLoc()->dump(OS); 00103 } 00104 00105 if (DumpType == DIDT_All || DumpType == DIDT_LocDwo) { 00106 OS << "\n.debug_loc.dwo contents:\n"; 00107 getDebugLocDWO()->dump(OS); 00108 } 00109 00110 if (DumpType == DIDT_All || DumpType == DIDT_Frames) { 00111 OS << "\n.debug_frame contents:\n"; 00112 getDebugFrame()->dump(OS); 00113 } 00114 00115 uint32_t offset = 0; 00116 if (DumpType == DIDT_All || DumpType == DIDT_Aranges) { 00117 OS << "\n.debug_aranges contents:\n"; 00118 DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0); 00119 DWARFDebugArangeSet set; 00120 while (set.extract(arangesData, &offset)) 00121 set.dump(OS); 00122 } 00123 00124 uint8_t savedAddressByteSize = 0; 00125 if (DumpType == DIDT_All || DumpType == DIDT_Line) { 00126 OS << "\n.debug_line contents:\n"; 00127 for (const auto &CU : compile_units()) { 00128 savedAddressByteSize = CU->getAddressByteSize(); 00129 unsigned stmtOffset = 00130 CU->getCompileUnitDIE()->getAttributeValueAsSectionOffset( 00131 CU.get(), DW_AT_stmt_list, -1U); 00132 if (stmtOffset != -1U) { 00133 DataExtractor lineData(getLineSection().Data, isLittleEndian(), 00134 savedAddressByteSize); 00135 DWARFDebugLine::LineTable LineTable; 00136 LineTable.parse(lineData, &getLineSection().Relocs, &stmtOffset); 00137 LineTable.dump(OS); 00138 } 00139 } 00140 } 00141 00142 if (DumpType == DIDT_All || DumpType == DIDT_LineDwo) { 00143 OS << "\n.debug_line.dwo contents:\n"; 00144 unsigned stmtOffset = 0; 00145 DataExtractor lineData(getLineDWOSection().Data, isLittleEndian(), 00146 savedAddressByteSize); 00147 DWARFDebugLine::LineTable LineTable; 00148 while (LineTable.Prologue.parse(lineData, &stmtOffset)) { 00149 LineTable.dump(OS); 00150 LineTable.clear(); 00151 } 00152 } 00153 00154 if (DumpType == DIDT_All || DumpType == DIDT_Str) { 00155 OS << "\n.debug_str contents:\n"; 00156 DataExtractor strData(getStringSection(), isLittleEndian(), 0); 00157 offset = 0; 00158 uint32_t strOffset = 0; 00159 while (const char *s = strData.getCStr(&offset)) { 00160 OS << format("0x%8.8x: \"%s\"\n", strOffset, s); 00161 strOffset = offset; 00162 } 00163 } 00164 00165 if ((DumpType == DIDT_All || DumpType == DIDT_StrDwo) && 00166 !getStringDWOSection().empty()) { 00167 OS << "\n.debug_str.dwo contents:\n"; 00168 DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0); 00169 offset = 0; 00170 uint32_t strDWOOffset = 0; 00171 while (const char *s = strDWOData.getCStr(&offset)) { 00172 OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s); 00173 strDWOOffset = offset; 00174 } 00175 } 00176 00177 if (DumpType == DIDT_All || DumpType == DIDT_Ranges) { 00178 OS << "\n.debug_ranges contents:\n"; 00179 // In fact, different compile units may have different address byte 00180 // sizes, but for simplicity we just use the address byte size of the last 00181 // compile unit (there is no easy and fast way to associate address range 00182 // list and the compile unit it describes). 00183 DataExtractor rangesData(getRangeSection(), isLittleEndian(), 00184 savedAddressByteSize); 00185 offset = 0; 00186 DWARFDebugRangeList rangeList; 00187 while (rangeList.extract(rangesData, &offset)) 00188 rangeList.dump(OS); 00189 } 00190 00191 if (DumpType == DIDT_All || DumpType == DIDT_Pubnames) 00192 dumpPubSection(OS, "debug_pubnames", getPubNamesSection(), 00193 isLittleEndian(), false); 00194 00195 if (DumpType == DIDT_All || DumpType == DIDT_Pubtypes) 00196 dumpPubSection(OS, "debug_pubtypes", getPubTypesSection(), 00197 isLittleEndian(), false); 00198 00199 if (DumpType == DIDT_All || DumpType == DIDT_GnuPubnames) 00200 dumpPubSection(OS, "debug_gnu_pubnames", getGnuPubNamesSection(), 00201 isLittleEndian(), true /* GnuStyle */); 00202 00203 if (DumpType == DIDT_All || DumpType == DIDT_GnuPubtypes) 00204 dumpPubSection(OS, "debug_gnu_pubtypes", getGnuPubTypesSection(), 00205 isLittleEndian(), true /* GnuStyle */); 00206 00207 if ((DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) && 00208 !getStringOffsetDWOSection().empty()) { 00209 OS << "\n.debug_str_offsets.dwo contents:\n"; 00210 DataExtractor strOffsetExt(getStringOffsetDWOSection(), isLittleEndian(), 00211 0); 00212 offset = 0; 00213 uint64_t size = getStringOffsetDWOSection().size(); 00214 while (offset < size) { 00215 OS << format("0x%8.8x: ", offset); 00216 OS << format("%8.8x\n", strOffsetExt.getU32(&offset)); 00217 } 00218 } 00219 } 00220 00221 const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() { 00222 if (Abbrev) 00223 return Abbrev.get(); 00224 00225 DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0); 00226 00227 Abbrev.reset(new DWARFDebugAbbrev()); 00228 Abbrev->extract(abbrData); 00229 return Abbrev.get(); 00230 } 00231 00232 const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() { 00233 if (AbbrevDWO) 00234 return AbbrevDWO.get(); 00235 00236 DataExtractor abbrData(getAbbrevDWOSection(), isLittleEndian(), 0); 00237 AbbrevDWO.reset(new DWARFDebugAbbrev()); 00238 AbbrevDWO->extract(abbrData); 00239 return AbbrevDWO.get(); 00240 } 00241 00242 const DWARFDebugLoc *DWARFContext::getDebugLoc() { 00243 if (Loc) 00244 return Loc.get(); 00245 00246 DataExtractor LocData(getLocSection().Data, isLittleEndian(), 0); 00247 Loc.reset(new DWARFDebugLoc(getLocSection().Relocs)); 00248 // assume all compile units have the same address byte size 00249 if (getNumCompileUnits()) 00250 Loc->parse(LocData, getCompileUnitAtIndex(0)->getAddressByteSize()); 00251 return Loc.get(); 00252 } 00253 00254 const DWARFDebugLocDWO *DWARFContext::getDebugLocDWO() { 00255 if (LocDWO) 00256 return LocDWO.get(); 00257 00258 DataExtractor LocData(getLocDWOSection().Data, isLittleEndian(), 0); 00259 LocDWO.reset(new DWARFDebugLocDWO()); 00260 LocDWO->parse(LocData); 00261 return LocDWO.get(); 00262 } 00263 00264 const DWARFDebugAranges *DWARFContext::getDebugAranges() { 00265 if (Aranges) 00266 return Aranges.get(); 00267 00268 Aranges.reset(new DWARFDebugAranges()); 00269 Aranges->generate(this); 00270 return Aranges.get(); 00271 } 00272 00273 const DWARFDebugFrame *DWARFContext::getDebugFrame() { 00274 if (DebugFrame) 00275 return DebugFrame.get(); 00276 00277 // There's a "bug" in the DWARFv3 standard with respect to the target address 00278 // size within debug frame sections. While DWARF is supposed to be independent 00279 // of its container, FDEs have fields with size being "target address size", 00280 // which isn't specified in DWARF in general. It's only specified for CUs, but 00281 // .eh_frame can appear without a .debug_info section. Follow the example of 00282 // other tools (libdwarf) and extract this from the container (ObjectFile 00283 // provides this information). This problem is fixed in DWARFv4 00284 // See this dwarf-discuss discussion for more details: 00285 // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html 00286 DataExtractor debugFrameData(getDebugFrameSection(), isLittleEndian(), 00287 getAddressSize()); 00288 DebugFrame.reset(new DWARFDebugFrame()); 00289 DebugFrame->parse(debugFrameData); 00290 return DebugFrame.get(); 00291 } 00292 00293 const DWARFLineTable * 00294 DWARFContext::getLineTableForUnit(DWARFUnit *cu) { 00295 if (!Line) 00296 Line.reset(new DWARFDebugLine(&getLineSection().Relocs)); 00297 00298 unsigned stmtOffset = 00299 cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset( 00300 cu, DW_AT_stmt_list, -1U); 00301 if (stmtOffset == -1U) 00302 return nullptr; // No line table for this compile unit. 00303 00304 // See if the line table is cached. 00305 if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset)) 00306 return lt; 00307 00308 // We have to parse it first. 00309 DataExtractor lineData(getLineSection().Data, isLittleEndian(), 00310 cu->getAddressByteSize()); 00311 return Line->getOrParseLineTable(lineData, stmtOffset); 00312 } 00313 00314 void DWARFContext::parseCompileUnits() { 00315 if (!CUs.empty()) 00316 return; 00317 uint32_t offset = 0; 00318 const DataExtractor &DIData = DataExtractor(getInfoSection().Data, 00319 isLittleEndian(), 0); 00320 while (DIData.isValidOffset(offset)) { 00321 std::unique_ptr<DWARFCompileUnit> CU(new DWARFCompileUnit(*this, 00322 getDebugAbbrev(), getInfoSection().Data, getRangeSection(), 00323 getStringSection(), StringRef(), getAddrSection(), 00324 &getInfoSection().Relocs, isLittleEndian(), CUs)); 00325 if (!CU->extract(DIData, &offset)) { 00326 break; 00327 } 00328 CUs.push_back(std::move(CU)); 00329 offset = CUs.back()->getNextUnitOffset(); 00330 } 00331 } 00332 00333 void DWARFContext::parseTypeUnits() { 00334 if (!TUs.empty()) 00335 return; 00336 for (const auto &I : getTypesSections()) { 00337 uint32_t offset = 0; 00338 const DataExtractor &DIData = 00339 DataExtractor(I.second.Data, isLittleEndian(), 0); 00340 while (DIData.isValidOffset(offset)) { 00341 std::unique_ptr<DWARFTypeUnit> TU(new DWARFTypeUnit(*this, 00342 getDebugAbbrev(), I.second.Data, getRangeSection(), 00343 getStringSection(), StringRef(), getAddrSection(), 00344 &I.second.Relocs, isLittleEndian(), TUs)); 00345 if (!TU->extract(DIData, &offset)) 00346 break; 00347 TUs.push_back(std::move(TU)); 00348 offset = TUs.back()->getNextUnitOffset(); 00349 } 00350 } 00351 } 00352 00353 void DWARFContext::parseDWOCompileUnits() { 00354 if (!DWOCUs.empty()) 00355 return; 00356 uint32_t offset = 0; 00357 const DataExtractor &DIData = 00358 DataExtractor(getInfoDWOSection().Data, isLittleEndian(), 0); 00359 while (DIData.isValidOffset(offset)) { 00360 std::unique_ptr<DWARFCompileUnit> DWOCU(new DWARFCompileUnit(*this, 00361 getDebugAbbrevDWO(), getInfoDWOSection().Data, getRangeDWOSection(), 00362 getStringDWOSection(), getStringOffsetDWOSection(), getAddrSection(), 00363 &getInfoDWOSection().Relocs, isLittleEndian(), DWOCUs)); 00364 if (!DWOCU->extract(DIData, &offset)) { 00365 break; 00366 } 00367 DWOCUs.push_back(std::move(DWOCU)); 00368 offset = DWOCUs.back()->getNextUnitOffset(); 00369 } 00370 } 00371 00372 void DWARFContext::parseDWOTypeUnits() { 00373 if (!DWOTUs.empty()) 00374 return; 00375 for (const auto &I : getTypesDWOSections()) { 00376 uint32_t offset = 0; 00377 const DataExtractor &DIData = 00378 DataExtractor(I.second.Data, isLittleEndian(), 0); 00379 while (DIData.isValidOffset(offset)) { 00380 std::unique_ptr<DWARFTypeUnit> TU(new DWARFTypeUnit(*this, 00381 getDebugAbbrevDWO(), I.second.Data, getRangeDWOSection(), 00382 getStringDWOSection(), getStringOffsetDWOSection(), getAddrSection(), 00383 &I.second.Relocs, isLittleEndian(), DWOTUs)); 00384 if (!TU->extract(DIData, &offset)) 00385 break; 00386 DWOTUs.push_back(std::move(TU)); 00387 offset = DWOTUs.back()->getNextUnitOffset(); 00388 } 00389 } 00390 } 00391 00392 DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) { 00393 parseCompileUnits(); 00394 return CUs.getUnitForOffset(Offset); 00395 } 00396 00397 DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) { 00398 // First, get the offset of the compile unit. 00399 uint32_t CUOffset = getDebugAranges()->findAddress(Address); 00400 // Retrieve the compile unit. 00401 return getCompileUnitForOffset(CUOffset); 00402 } 00403 00404 static bool getFileNameForUnit(DWARFCompileUnit *U, 00405 const DWARFLineTable *LineTable, 00406 uint64_t FileIndex, FileLineInfoKind Kind, 00407 std::string &FileName) { 00408 if (!U || !LineTable || Kind == FileLineInfoKind::None || 00409 !LineTable->getFileNameByIndex(FileIndex, Kind, FileName)) 00410 return false; 00411 if (Kind == FileLineInfoKind::AbsoluteFilePath && 00412 sys::path::is_relative(FileName)) { 00413 // We may still need to append compilation directory of compile unit. 00414 SmallString<16> AbsolutePath; 00415 if (const char *CompilationDir = U->getCompilationDir()) { 00416 sys::path::append(AbsolutePath, CompilationDir); 00417 } 00418 sys::path::append(AbsolutePath, FileName); 00419 FileName = AbsolutePath.str(); 00420 } 00421 return true; 00422 } 00423 00424 static bool getFileLineInfoForCompileUnit(DWARFCompileUnit *CU, 00425 const DWARFLineTable *LineTable, 00426 uint64_t Address, 00427 FileLineInfoKind Kind, 00428 DILineInfo &Result) { 00429 if (!CU || !LineTable) 00430 return false; 00431 // Get the index of row we're looking for in the line table. 00432 uint32_t RowIndex = LineTable->lookupAddress(Address); 00433 if (RowIndex == -1U) 00434 return false; 00435 // Take file number and line/column from the row. 00436 const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex]; 00437 if (!getFileNameForUnit(CU, LineTable, Row.File, Kind, 00438 Result.FileName)) 00439 return false; 00440 Result.Line = Row.Line; 00441 Result.Column = Row.Column; 00442 return true; 00443 } 00444 00445 static bool getFunctionNameForAddress(DWARFCompileUnit *CU, uint64_t Address, 00446 FunctionNameKind Kind, 00447 std::string &FunctionName) { 00448 if (Kind == FunctionNameKind::None) 00449 return false; 00450 // The address may correspond to instruction in some inlined function, 00451 // so we have to build the chain of inlined functions and take the 00452 // name of the topmost function in it. 00453 const DWARFDebugInfoEntryInlinedChain &InlinedChain = 00454 CU->getInlinedChainForAddress(Address); 00455 if (InlinedChain.DIEs.size() == 0) 00456 return false; 00457 const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0]; 00458 if (const char *Name = 00459 TopFunctionDIE.getSubroutineName(InlinedChain.U, Kind)) { 00460 FunctionName = Name; 00461 return true; 00462 } 00463 return false; 00464 } 00465 00466 DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address, 00467 DILineInfoSpecifier Spec) { 00468 DILineInfo Result; 00469 00470 DWARFCompileUnit *CU = getCompileUnitForAddress(Address); 00471 if (!CU) 00472 return Result; 00473 getFunctionNameForAddress(CU, Address, Spec.FNKind, Result.FunctionName); 00474 if (Spec.FLIKind != FileLineInfoKind::None) { 00475 const DWARFLineTable *LineTable = getLineTableForUnit(CU); 00476 getFileLineInfoForCompileUnit(CU, LineTable, Address, Spec.FLIKind, Result); 00477 } 00478 return Result; 00479 } 00480 00481 DILineInfoTable 00482 DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size, 00483 DILineInfoSpecifier Spec) { 00484 DILineInfoTable Lines; 00485 DWARFCompileUnit *CU = getCompileUnitForAddress(Address); 00486 if (!CU) 00487 return Lines; 00488 00489 std::string FunctionName = "<invalid>"; 00490 getFunctionNameForAddress(CU, Address, Spec.FNKind, FunctionName); 00491 00492 // If the Specifier says we don't need FileLineInfo, just 00493 // return the top-most function at the starting address. 00494 if (Spec.FLIKind == FileLineInfoKind::None) { 00495 DILineInfo Result; 00496 Result.FunctionName = FunctionName; 00497 Lines.push_back(std::make_pair(Address, Result)); 00498 return Lines; 00499 } 00500 00501 const DWARFLineTable *LineTable = getLineTableForUnit(CU); 00502 00503 // Get the index of row we're looking for in the line table. 00504 std::vector<uint32_t> RowVector; 00505 if (!LineTable->lookupAddressRange(Address, Size, RowVector)) 00506 return Lines; 00507 00508 for (uint32_t RowIndex : RowVector) { 00509 // Take file number and line/column from the row. 00510 const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex]; 00511 DILineInfo Result; 00512 getFileNameForUnit(CU, LineTable, Row.File, Spec.FLIKind, 00513 Result.FileName); 00514 Result.FunctionName = FunctionName; 00515 Result.Line = Row.Line; 00516 Result.Column = Row.Column; 00517 Lines.push_back(std::make_pair(Row.Address, Result)); 00518 } 00519 00520 return Lines; 00521 } 00522 00523 DIInliningInfo 00524 DWARFContext::getInliningInfoForAddress(uint64_t Address, 00525 DILineInfoSpecifier Spec) { 00526 DIInliningInfo InliningInfo; 00527 00528 DWARFCompileUnit *CU = getCompileUnitForAddress(Address); 00529 if (!CU) 00530 return InliningInfo; 00531 00532 const DWARFLineTable *LineTable = nullptr; 00533 const DWARFDebugInfoEntryInlinedChain &InlinedChain = 00534 CU->getInlinedChainForAddress(Address); 00535 if (InlinedChain.DIEs.size() == 0) { 00536 // If there is no DIE for address (e.g. it is in unavailable .dwo file), 00537 // try to at least get file/line info from symbol table. 00538 if (Spec.FLIKind != FileLineInfoKind::None) { 00539 DILineInfo Frame; 00540 LineTable = getLineTableForUnit(CU); 00541 if (getFileLineInfoForCompileUnit(CU, LineTable, Address, Spec.FLIKind, 00542 Frame)) { 00543 InliningInfo.addFrame(Frame); 00544 } 00545 } 00546 return InliningInfo; 00547 } 00548 00549 uint32_t CallFile = 0, CallLine = 0, CallColumn = 0; 00550 for (uint32_t i = 0, n = InlinedChain.DIEs.size(); i != n; i++) { 00551 const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain.DIEs[i]; 00552 DILineInfo Frame; 00553 // Get function name if necessary. 00554 if (const char *Name = 00555 FunctionDIE.getSubroutineName(InlinedChain.U, Spec.FNKind)) 00556 Frame.FunctionName = Name; 00557 if (Spec.FLIKind != FileLineInfoKind::None) { 00558 if (i == 0) { 00559 // For the topmost frame, initialize the line table of this 00560 // compile unit and fetch file/line info from it. 00561 LineTable = getLineTableForUnit(CU); 00562 // For the topmost routine, get file/line info from line table. 00563 getFileLineInfoForCompileUnit(CU, LineTable, Address, Spec.FLIKind, 00564 Frame); 00565 } else { 00566 // Otherwise, use call file, call line and call column from 00567 // previous DIE in inlined chain. 00568 getFileNameForUnit(CU, LineTable, CallFile, Spec.FLIKind, 00569 Frame.FileName); 00570 Frame.Line = CallLine; 00571 Frame.Column = CallColumn; 00572 } 00573 // Get call file/line/column of a current DIE. 00574 if (i + 1 < n) { 00575 FunctionDIE.getCallerFrame(InlinedChain.U, CallFile, CallLine, 00576 CallColumn); 00577 } 00578 } 00579 InliningInfo.addFrame(Frame); 00580 } 00581 return InliningInfo; 00582 } 00583 00584 static bool consumeCompressedDebugSectionHeader(StringRef &data, 00585 uint64_t &OriginalSize) { 00586 // Consume "ZLIB" prefix. 00587 if (!data.startswith("ZLIB")) 00588 return false; 00589 data = data.substr(4); 00590 // Consume uncompressed section size (big-endian 8 bytes). 00591 DataExtractor extractor(data, false, 8); 00592 uint32_t Offset = 0; 00593 OriginalSize = extractor.getU64(&Offset); 00594 if (Offset == 0) 00595 return false; 00596 data = data.substr(Offset); 00597 return true; 00598 } 00599 00600 DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile &Obj) 00601 : IsLittleEndian(Obj.isLittleEndian()), 00602 AddressSize(Obj.getBytesInAddress()) { 00603 for (const SectionRef &Section : Obj.sections()) { 00604 StringRef name; 00605 Section.getName(name); 00606 StringRef data; 00607 Section.getContents(data); 00608 00609 name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes. 00610 00611 // Check if debug info section is compressed with zlib. 00612 if (name.startswith("zdebug_")) { 00613 uint64_t OriginalSize; 00614 if (!zlib::isAvailable() || 00615 !consumeCompressedDebugSectionHeader(data, OriginalSize)) 00616 continue; 00617 UncompressedSections.resize(UncompressedSections.size() + 1); 00618 if (zlib::uncompress(data, UncompressedSections.back(), OriginalSize) != 00619 zlib::StatusOK) { 00620 UncompressedSections.pop_back(); 00621 continue; 00622 } 00623 // Make data point to uncompressed section contents and save its contents. 00624 name = name.substr(1); 00625 data = UncompressedSections.back(); 00626 } 00627 00628 StringRef *SectionData = 00629 StringSwitch<StringRef *>(name) 00630 .Case("debug_info", &InfoSection.Data) 00631 .Case("debug_abbrev", &AbbrevSection) 00632 .Case("debug_loc", &LocSection.Data) 00633 .Case("debug_line", &LineSection.Data) 00634 .Case("debug_aranges", &ARangeSection) 00635 .Case("debug_frame", &DebugFrameSection) 00636 .Case("debug_str", &StringSection) 00637 .Case("debug_ranges", &RangeSection) 00638 .Case("debug_pubnames", &PubNamesSection) 00639 .Case("debug_pubtypes", &PubTypesSection) 00640 .Case("debug_gnu_pubnames", &GnuPubNamesSection) 00641 .Case("debug_gnu_pubtypes", &GnuPubTypesSection) 00642 .Case("debug_info.dwo", &InfoDWOSection.Data) 00643 .Case("debug_abbrev.dwo", &AbbrevDWOSection) 00644 .Case("debug_loc.dwo", &LocDWOSection.Data) 00645 .Case("debug_line.dwo", &LineDWOSection.Data) 00646 .Case("debug_str.dwo", &StringDWOSection) 00647 .Case("debug_str_offsets.dwo", &StringOffsetDWOSection) 00648 .Case("debug_addr", &AddrSection) 00649 // Any more debug info sections go here. 00650 .Default(nullptr); 00651 if (SectionData) { 00652 *SectionData = data; 00653 if (name == "debug_ranges") { 00654 // FIXME: Use the other dwo range section when we emit it. 00655 RangeDWOSection = data; 00656 } 00657 } else if (name == "debug_types") { 00658 // Find debug_types data by section rather than name as there are 00659 // multiple, comdat grouped, debug_types sections. 00660 TypesSections[Section].Data = data; 00661 } else if (name == "debug_types.dwo") { 00662 TypesDWOSections[Section].Data = data; 00663 } 00664 00665 section_iterator RelocatedSection = Section.getRelocatedSection(); 00666 if (RelocatedSection == Obj.section_end()) 00667 continue; 00668 00669 StringRef RelSecName; 00670 RelocatedSection->getName(RelSecName); 00671 RelSecName = RelSecName.substr( 00672 RelSecName.find_first_not_of("._")); // Skip . and _ prefixes. 00673 00674 // TODO: Add support for relocations in other sections as needed. 00675 // Record relocations for the debug_info and debug_line sections. 00676 RelocAddrMap *Map = StringSwitch<RelocAddrMap*>(RelSecName) 00677 .Case("debug_info", &InfoSection.Relocs) 00678 .Case("debug_loc", &LocSection.Relocs) 00679 .Case("debug_info.dwo", &InfoDWOSection.Relocs) 00680 .Case("debug_line", &LineSection.Relocs) 00681 .Default(nullptr); 00682 if (!Map) { 00683 // Find debug_types relocs by section rather than name as there are 00684 // multiple, comdat grouped, debug_types sections. 00685 if (RelSecName == "debug_types") 00686 Map = &TypesSections[*RelocatedSection].Relocs; 00687 else if (RelSecName == "debug_types.dwo") 00688 Map = &TypesDWOSections[*RelocatedSection].Relocs; 00689 else 00690 continue; 00691 } 00692 00693 if (Section.relocation_begin() != Section.relocation_end()) { 00694 uint64_t SectionSize; 00695 RelocatedSection->getSize(SectionSize); 00696 for (const RelocationRef &Reloc : Section.relocations()) { 00697 uint64_t Address; 00698 Reloc.getOffset(Address); 00699 uint64_t Type; 00700 Reloc.getType(Type); 00701 uint64_t SymAddr = 0; 00702 // ELF relocations may need the symbol address 00703 if (Obj.isELF()) { 00704 object::symbol_iterator Sym = Reloc.getSymbol(); 00705 Sym->getAddress(SymAddr); 00706 } 00707 00708 object::RelocVisitor V(Obj.getFileFormatName()); 00709 // The section address is always 0 for debug sections. 00710 object::RelocToApply R(V.visit(Type, Reloc, 0, SymAddr)); 00711 if (V.error()) { 00712 SmallString<32> Name; 00713 std::error_code ec(Reloc.getTypeName(Name)); 00714 if (ec) { 00715 errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n"; 00716 } 00717 errs() << "error: failed to compute relocation: " 00718 << Name << "\n"; 00719 continue; 00720 } 00721 00722 if (Address + R.Width > SectionSize) { 00723 errs() << "error: " << R.Width << "-byte relocation starting " 00724 << Address << " bytes into section " << name << " which is " 00725 << SectionSize << " bytes long.\n"; 00726 continue; 00727 } 00728 if (R.Width > 8) { 00729 errs() << "error: can't handle a relocation of more than 8 bytes at " 00730 "a time.\n"; 00731 continue; 00732 } 00733 DEBUG(dbgs() << "Writing " << format("%p", R.Value) 00734 << " at " << format("%p", Address) 00735 << " with width " << format("%d", R.Width) 00736 << "\n"); 00737 Map->insert(std::make_pair(Address, std::make_pair(R.Width, R.Value))); 00738 } 00739 } 00740 } 00741 } 00742 00743 void DWARFContextInMemory::anchor() { }