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/Support/Dwarf.h" 13 #include "llvm/Support/Format.h" 14 #include "llvm/Support/Path.h" 15 #include "llvm/Support/raw_ostream.h" 16 #include <algorithm> 17 using namespace llvm; 18 using namespace dwarf; 19 20 typedef DWARFDebugLine::LineTable DWARFLineTable; 21 22 void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { 23 if (DumpType == DIDT_All || DumpType == DIDT_Abbrev) { 24 OS << ".debug_abbrev contents:\n"; 25 getDebugAbbrev()->dump(OS); 26 } 27 28 if (DumpType == DIDT_All || DumpType == DIDT_Info) { 29 OS << "\n.debug_info contents:\n"; 30 for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) 31 getCompileUnitAtIndex(i)->dump(OS); 32 } 33 34 if (DumpType == DIDT_All || DumpType == DIDT_Frames) { 35 OS << "\n.debug_frame contents:\n"; 36 getDebugFrame()->dump(OS); 37 } 38 39 uint32_t offset = 0; 40 if (DumpType == DIDT_All || DumpType == DIDT_Aranges) { 41 OS << "\n.debug_aranges contents:\n"; 42 DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0); 43 DWARFDebugArangeSet set; 44 while (set.extract(arangesData, &offset)) 45 set.dump(OS); 46 } 47 48 uint8_t savedAddressByteSize = 0; 49 if (DumpType == DIDT_All || DumpType == DIDT_Line) { 50 OS << "\n.debug_line contents:\n"; 51 for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) { 52 DWARFCompileUnit *cu = getCompileUnitAtIndex(i); 53 savedAddressByteSize = cu->getAddressByteSize(); 54 unsigned stmtOffset = 55 cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list, 56 -1U); 57 if (stmtOffset != -1U) { 58 DataExtractor lineData(getLineSection(), isLittleEndian(), 59 savedAddressByteSize); 60 DWARFDebugLine::DumpingState state(OS); 61 DWARFDebugLine::parseStatementTable(lineData, &lineRelocMap(), &stmtOffset, state); 62 } 63 } 64 } 65 66 if (DumpType == DIDT_All || DumpType == DIDT_Str) { 67 OS << "\n.debug_str contents:\n"; 68 DataExtractor strData(getStringSection(), isLittleEndian(), 0); 69 offset = 0; 70 uint32_t strOffset = 0; 71 while (const char *s = strData.getCStr(&offset)) { 72 OS << format("0x%8.8x: \"%s\"\n", strOffset, s); 73 strOffset = offset; 74 } 75 } 76 77 if (DumpType == DIDT_All || DumpType == DIDT_Ranges) { 78 OS << "\n.debug_ranges contents:\n"; 79 // In fact, different compile units may have different address byte 80 // sizes, but for simplicity we just use the address byte size of the last 81 // compile unit (there is no easy and fast way to associate address range 82 // list and the compile unit it describes). 83 DataExtractor rangesData(getRangeSection(), isLittleEndian(), 84 savedAddressByteSize); 85 offset = 0; 86 DWARFDebugRangeList rangeList; 87 while (rangeList.extract(rangesData, &offset)) 88 rangeList.dump(OS); 89 } 90 91 if (DumpType == DIDT_All || DumpType == DIDT_Pubnames) { 92 OS << "\n.debug_pubnames contents:\n"; 93 DataExtractor pubNames(getPubNamesSection(), isLittleEndian(), 0); 94 offset = 0; 95 OS << "Length: " << pubNames.getU32(&offset) << "\n"; 96 OS << "Version: " << pubNames.getU16(&offset) << "\n"; 97 OS << "Offset in .debug_info: " << pubNames.getU32(&offset) << "\n"; 98 OS << "Size: " << pubNames.getU32(&offset) << "\n"; 99 OS << "\n Offset Name\n"; 100 while (offset < getPubNamesSection().size()) { 101 uint32_t n = pubNames.getU32(&offset); 102 if (n == 0) 103 break; 104 OS << format("%8x ", n); 105 OS << pubNames.getCStr(&offset) << "\n"; 106 } 107 } 108 109 if (DumpType == DIDT_All || DumpType == DIDT_AbbrevDwo) { 110 OS << "\n.debug_abbrev.dwo contents:\n"; 111 getDebugAbbrevDWO()->dump(OS); 112 } 113 114 if (DumpType == DIDT_All || DumpType == DIDT_InfoDwo) { 115 OS << "\n.debug_info.dwo contents:\n"; 116 for (unsigned i = 0, e = getNumDWOCompileUnits(); i != e; ++i) 117 getDWOCompileUnitAtIndex(i)->dump(OS); 118 } 119 120 if (DumpType == DIDT_All || DumpType == DIDT_StrDwo) { 121 OS << "\n.debug_str.dwo contents:\n"; 122 DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0); 123 offset = 0; 124 uint32_t strDWOOffset = 0; 125 while (const char *s = strDWOData.getCStr(&offset)) { 126 OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s); 127 strDWOOffset = offset; 128 } 129 } 130 131 if (DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) { 132 OS << "\n.debug_str_offsets.dwo contents:\n"; 133 DataExtractor strOffsetExt(getStringOffsetDWOSection(), isLittleEndian(), 0); 134 offset = 0; 135 while (offset < getStringOffsetDWOSection().size()) { 136 OS << format("0x%8.8x: ", offset); 137 OS << format("%8.8x\n", strOffsetExt.getU32(&offset)); 138 } 139 } 140 } 141 142 const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() { 143 if (Abbrev) 144 return Abbrev.get(); 145 146 DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0); 147 148 Abbrev.reset(new DWARFDebugAbbrev()); 149 Abbrev->parse(abbrData); 150 return Abbrev.get(); 151 } 152 153 const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() { 154 if (AbbrevDWO) 155 return AbbrevDWO.get(); 156 157 DataExtractor abbrData(getAbbrevDWOSection(), isLittleEndian(), 0); 158 AbbrevDWO.reset(new DWARFDebugAbbrev()); 159 AbbrevDWO->parse(abbrData); 160 return AbbrevDWO.get(); 161 } 162 163 const DWARFDebugAranges *DWARFContext::getDebugAranges() { 164 if (Aranges) 165 return Aranges.get(); 166 167 DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0); 168 169 Aranges.reset(new DWARFDebugAranges()); 170 Aranges->extract(arangesData); 171 // Generate aranges from DIEs: even if .debug_aranges section is present, 172 // it may describe only a small subset of compilation units, so we need to 173 // manually build aranges for the rest of them. 174 Aranges->generate(this); 175 return Aranges.get(); 176 } 177 178 const DWARFDebugFrame *DWARFContext::getDebugFrame() { 179 if (DebugFrame) 180 return DebugFrame.get(); 181 182 // There's a "bug" in the DWARFv3 standard with respect to the target address 183 // size within debug frame sections. While DWARF is supposed to be independent 184 // of its container, FDEs have fields with size being "target address size", 185 // which isn't specified in DWARF in general. It's only specified for CUs, but 186 // .eh_frame can appear without a .debug_info section. Follow the example of 187 // other tools (libdwarf) and extract this from the container (ObjectFile 188 // provides this information). This problem is fixed in DWARFv4 189 // See this dwarf-discuss discussion for more details: 190 // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html 191 DataExtractor debugFrameData(getDebugFrameSection(), isLittleEndian(), 192 getAddressSize()); 193 DebugFrame.reset(new DWARFDebugFrame()); 194 DebugFrame->parse(debugFrameData); 195 return DebugFrame.get(); 196 } 197 198 const DWARFLineTable * 199 DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) { 200 if (!Line) 201 Line.reset(new DWARFDebugLine(&lineRelocMap())); 202 203 unsigned stmtOffset = 204 cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list, 205 -1U); 206 if (stmtOffset == -1U) 207 return 0; // No line table for this compile unit. 208 209 // See if the line table is cached. 210 if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset)) 211 return lt; 212 213 // We have to parse it first. 214 DataExtractor lineData(getLineSection(), isLittleEndian(), 215 cu->getAddressByteSize()); 216 return Line->getOrParseLineTable(lineData, stmtOffset); 217 } 218 219 void DWARFContext::parseCompileUnits() { 220 uint32_t offset = 0; 221 const DataExtractor &DIData = DataExtractor(getInfoSection(), 222 isLittleEndian(), 0); 223 while (DIData.isValidOffset(offset)) { 224 CUs.push_back(DWARFCompileUnit(getDebugAbbrev(), getInfoSection(), 225 getAbbrevSection(), getRangeSection(), 226 getStringSection(), StringRef(), 227 getAddrSection(), 228 &infoRelocMap(), 229 isLittleEndian())); 230 if (!CUs.back().extract(DIData, &offset)) { 231 CUs.pop_back(); 232 break; 233 } 234 235 offset = CUs.back().getNextCompileUnitOffset(); 236 } 237 } 238 239 void DWARFContext::parseDWOCompileUnits() { 240 uint32_t offset = 0; 241 const DataExtractor &DIData = DataExtractor(getInfoDWOSection(), 242 isLittleEndian(), 0); 243 while (DIData.isValidOffset(offset)) { 244 DWOCUs.push_back(DWARFCompileUnit(getDebugAbbrevDWO(), getInfoDWOSection(), 245 getAbbrevDWOSection(), 246 getRangeDWOSection(), 247 getStringDWOSection(), 248 getStringOffsetDWOSection(), 249 getAddrSection(), 250 &infoDWORelocMap(), 251 isLittleEndian())); 252 if (!DWOCUs.back().extract(DIData, &offset)) { 253 DWOCUs.pop_back(); 254 break; 255 } 256 257 offset = DWOCUs.back().getNextCompileUnitOffset(); 258 } 259 } 260 261 namespace { 262 struct OffsetComparator { 263 bool operator()(const DWARFCompileUnit &LHS, 264 const DWARFCompileUnit &RHS) const { 265 return LHS.getOffset() < RHS.getOffset(); 266 } 267 bool operator()(const DWARFCompileUnit &LHS, uint32_t RHS) const { 268 return LHS.getOffset() < RHS; 269 } 270 bool operator()(uint32_t LHS, const DWARFCompileUnit &RHS) const { 271 return LHS < RHS.getOffset(); 272 } 273 }; 274 } 275 276 DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) { 277 if (CUs.empty()) 278 parseCompileUnits(); 279 280 DWARFCompileUnit *CU = std::lower_bound(CUs.begin(), CUs.end(), Offset, 281 OffsetComparator()); 282 if (CU != CUs.end()) 283 return &*CU; 284 return 0; 285 } 286 287 DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) { 288 // First, get the offset of the compile unit. 289 uint32_t CUOffset = getDebugAranges()->findAddress(Address); 290 // Retrieve the compile unit. 291 return getCompileUnitForOffset(CUOffset); 292 } 293 294 static bool getFileNameForCompileUnit(DWARFCompileUnit *CU, 295 const DWARFLineTable *LineTable, 296 uint64_t FileIndex, 297 bool NeedsAbsoluteFilePath, 298 std::string &FileName) { 299 if (CU == 0 || 300 LineTable == 0 || 301 !LineTable->getFileNameByIndex(FileIndex, NeedsAbsoluteFilePath, 302 FileName)) 303 return false; 304 if (NeedsAbsoluteFilePath && sys::path::is_relative(FileName)) { 305 // We may still need to append compilation directory of compile unit. 306 SmallString<16> AbsolutePath; 307 if (const char *CompilationDir = CU->getCompilationDir()) { 308 sys::path::append(AbsolutePath, CompilationDir); 309 } 310 sys::path::append(AbsolutePath, FileName); 311 FileName = AbsolutePath.str(); 312 } 313 return true; 314 } 315 316 static bool getFileLineInfoForCompileUnit(DWARFCompileUnit *CU, 317 const DWARFLineTable *LineTable, 318 uint64_t Address, 319 bool NeedsAbsoluteFilePath, 320 std::string &FileName, 321 uint32_t &Line, uint32_t &Column) { 322 if (CU == 0 || LineTable == 0) 323 return false; 324 // Get the index of row we're looking for in the line table. 325 uint32_t RowIndex = LineTable->lookupAddress(Address); 326 if (RowIndex == -1U) 327 return false; 328 // Take file number and line/column from the row. 329 const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex]; 330 if (!getFileNameForCompileUnit(CU, LineTable, Row.File, 331 NeedsAbsoluteFilePath, FileName)) 332 return false; 333 Line = Row.Line; 334 Column = Row.Column; 335 return true; 336 } 337 338 DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address, 339 DILineInfoSpecifier Specifier) { 340 DWARFCompileUnit *CU = getCompileUnitForAddress(Address); 341 if (!CU) 342 return DILineInfo(); 343 std::string FileName = "<invalid>"; 344 std::string FunctionName = "<invalid>"; 345 uint32_t Line = 0; 346 uint32_t Column = 0; 347 if (Specifier.needs(DILineInfoSpecifier::FunctionName)) { 348 // The address may correspond to instruction in some inlined function, 349 // so we have to build the chain of inlined functions and take the 350 // name of the topmost function in it. 351 const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain = 352 CU->getInlinedChainForAddress(Address); 353 if (InlinedChain.size() > 0) { 354 const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain[0]; 355 if (const char *Name = TopFunctionDIE.getSubroutineName(CU)) 356 FunctionName = Name; 357 } 358 } 359 if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) { 360 const DWARFLineTable *LineTable = getLineTableForCompileUnit(CU); 361 const bool NeedsAbsoluteFilePath = 362 Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath); 363 getFileLineInfoForCompileUnit(CU, LineTable, Address, 364 NeedsAbsoluteFilePath, 365 FileName, Line, Column); 366 } 367 return DILineInfo(StringRef(FileName), StringRef(FunctionName), 368 Line, Column); 369 } 370 371 DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address, 372 uint64_t Size, 373 DILineInfoSpecifier Specifier) { 374 DILineInfoTable Lines; 375 DWARFCompileUnit *CU = getCompileUnitForAddress(Address); 376 if (!CU) 377 return Lines; 378 379 std::string FunctionName = "<invalid>"; 380 if (Specifier.needs(DILineInfoSpecifier::FunctionName)) { 381 // The address may correspond to instruction in some inlined function, 382 // so we have to build the chain of inlined functions and take the 383 // name of the topmost function in it. 384 const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain = 385 CU->getInlinedChainForAddress(Address); 386 if (InlinedChain.size() > 0) { 387 const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain[0]; 388 if (const char *Name = TopFunctionDIE.getSubroutineName(CU)) 389 FunctionName = Name; 390 } 391 } 392 393 StringRef FuncNameRef = StringRef(FunctionName); 394 395 // If the Specifier says we don't need FileLineInfo, just 396 // return the top-most function at the starting address. 397 if (!Specifier.needs(DILineInfoSpecifier::FileLineInfo)) { 398 Lines.push_back(std::make_pair(Address, 399 DILineInfo(StringRef("<invalid>"), 400 FuncNameRef, 0, 0))); 401 return Lines; 402 } 403 404 const DWARFLineTable *LineTable = getLineTableForCompileUnit(CU); 405 const bool NeedsAbsoluteFilePath = 406 Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath); 407 408 // Get the index of row we're looking for in the line table. 409 std::vector<uint32_t> RowVector; 410 if (!LineTable->lookupAddressRange(Address, Size, RowVector)) 411 return Lines; 412 413 uint32_t NumRows = RowVector.size(); 414 for (uint32_t i = 0; i < NumRows; ++i) { 415 uint32_t RowIndex = RowVector[i]; 416 // Take file number and line/column from the row. 417 const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex]; 418 std::string FileName = "<invalid>"; 419 getFileNameForCompileUnit(CU, LineTable, Row.File, 420 NeedsAbsoluteFilePath, FileName); 421 Lines.push_back(std::make_pair(Row.Address, 422 DILineInfo(StringRef(FileName), 423 FuncNameRef, Row.Line, Row.Column))); 424 } 425 426 return Lines; 427 } 428 429 DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address, 430 DILineInfoSpecifier Specifier) { 431 DWARFCompileUnit *CU = getCompileUnitForAddress(Address); 432 if (!CU) 433 return DIInliningInfo(); 434 435 const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain = 436 CU->getInlinedChainForAddress(Address); 437 if (InlinedChain.size() == 0) 438 return DIInliningInfo(); 439 440 DIInliningInfo InliningInfo; 441 uint32_t CallFile = 0, CallLine = 0, CallColumn = 0; 442 const DWARFLineTable *LineTable = 0; 443 for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) { 444 const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain[i]; 445 std::string FileName = "<invalid>"; 446 std::string FunctionName = "<invalid>"; 447 uint32_t Line = 0; 448 uint32_t Column = 0; 449 // Get function name if necessary. 450 if (Specifier.needs(DILineInfoSpecifier::FunctionName)) { 451 if (const char *Name = FunctionDIE.getSubroutineName(CU)) 452 FunctionName = Name; 453 } 454 if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) { 455 const bool NeedsAbsoluteFilePath = 456 Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath); 457 if (i == 0) { 458 // For the topmost frame, initialize the line table of this 459 // compile unit and fetch file/line info from it. 460 LineTable = getLineTableForCompileUnit(CU); 461 // For the topmost routine, get file/line info from line table. 462 getFileLineInfoForCompileUnit(CU, LineTable, Address, 463 NeedsAbsoluteFilePath, 464 FileName, Line, Column); 465 } else { 466 // Otherwise, use call file, call line and call column from 467 // previous DIE in inlined chain. 468 getFileNameForCompileUnit(CU, LineTable, CallFile, 469 NeedsAbsoluteFilePath, FileName); 470 Line = CallLine; 471 Column = CallColumn; 472 } 473 // Get call file/line/column of a current DIE. 474 if (i + 1 < n) { 475 FunctionDIE.getCallerFrame(CU, CallFile, CallLine, CallColumn); 476 } 477 } 478 DILineInfo Frame(StringRef(FileName), StringRef(FunctionName), 479 Line, Column); 480 InliningInfo.addFrame(Frame); 481 } 482 return InliningInfo; 483 } 484 485 DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : 486 IsLittleEndian(Obj->isLittleEndian()), 487 AddressSize(Obj->getBytesInAddress()) { 488 error_code ec; 489 for (object::section_iterator i = Obj->begin_sections(), 490 e = Obj->end_sections(); 491 i != e; i.increment(ec)) { 492 StringRef name; 493 i->getName(name); 494 StringRef data; 495 i->getContents(data); 496 497 name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes. 498 if (name == "debug_info") 499 InfoSection = data; 500 else if (name == "debug_abbrev") 501 AbbrevSection = data; 502 else if (name == "debug_line") 503 LineSection = data; 504 else if (name == "debug_aranges") 505 ARangeSection = data; 506 else if (name == "debug_frame") 507 DebugFrameSection = data; 508 else if (name == "debug_str") 509 StringSection = data; 510 else if (name == "debug_ranges") { 511 // FIXME: Use the other dwo range section when we emit it. 512 RangeDWOSection = data; 513 RangeSection = data; 514 } 515 else if (name == "debug_pubnames") 516 PubNamesSection = data; 517 else if (name == "debug_info.dwo") 518 InfoDWOSection = data; 519 else if (name == "debug_abbrev.dwo") 520 AbbrevDWOSection = data; 521 else if (name == "debug_str.dwo") 522 StringDWOSection = data; 523 else if (name == "debug_str_offsets.dwo") 524 StringOffsetDWOSection = data; 525 else if (name == "debug_addr") 526 AddrSection = data; 527 // Any more debug info sections go here. 528 else 529 continue; 530 531 // TODO: Add support for relocations in other sections as needed. 532 // Record relocations for the debug_info and debug_line sections. 533 RelocAddrMap *Map; 534 if (name == "debug_info") 535 Map = &InfoRelocMap; 536 else if (name == "debug_info.dwo") 537 Map = &InfoDWORelocMap; 538 else if (name == "debug_line") 539 Map = &LineRelocMap; 540 else 541 continue; 542 543 if (i->begin_relocations() != i->end_relocations()) { 544 uint64_t SectionSize; 545 i->getSize(SectionSize); 546 for (object::relocation_iterator reloc_i = i->begin_relocations(), 547 reloc_e = i->end_relocations(); 548 reloc_i != reloc_e; reloc_i.increment(ec)) { 549 uint64_t Address; 550 reloc_i->getAddress(Address); 551 uint64_t Type; 552 reloc_i->getType(Type); 553 uint64_t SymAddr = 0; 554 // ELF relocations may need the symbol address 555 if (Obj->isELF()) { 556 object::SymbolRef Sym; 557 reloc_i->getSymbol(Sym); 558 Sym.getAddress(SymAddr); 559 } 560 561 object::RelocVisitor V(Obj->getFileFormatName()); 562 // The section address is always 0 for debug sections. 563 object::RelocToApply R(V.visit(Type, *reloc_i, 0, SymAddr)); 564 if (V.error()) { 565 SmallString<32> Name; 566 error_code ec(reloc_i->getTypeName(Name)); 567 if (ec) { 568 errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n"; 569 } 570 errs() << "error: failed to compute relocation: " 571 << Name << "\n"; 572 continue; 573 } 574 575 if (Address + R.Width > SectionSize) { 576 errs() << "error: " << R.Width << "-byte relocation starting " 577 << Address << " bytes into section " << name << " which is " 578 << SectionSize << " bytes long.\n"; 579 continue; 580 } 581 if (R.Width > 8) { 582 errs() << "error: can't handle a relocation of more than 8 bytes at " 583 "a time.\n"; 584 continue; 585 } 586 DEBUG(dbgs() << "Writing " << format("%p", R.Value) 587 << " at " << format("%p", Address) 588 << " with width " << format("%d", R.Width) 589 << "\n"); 590 Map->insert(std::make_pair(Address, std::make_pair(R.Width, R.Value))); 591 } 592 } 593 } 594 } 595 596 void DWARFContextInMemory::anchor() { } 597