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