comparison llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp @ 236:c4bab56944e8 llvm-original

LLVM 16
author kono
date Wed, 09 Nov 2022 17:45:10 +0900
parents 79ff65ed7e25
children 1f2b6ac9f198
comparison
equal deleted inserted replaced
232:70dce7da266c 236:c4bab56944e8
8 8
9 #include <thread> 9 #include <thread>
10 #include <unordered_set> 10 #include <unordered_set>
11 11
12 #include "llvm/DebugInfo/DIContext.h" 12 #include "llvm/DebugInfo/DIContext.h"
13 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
13 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 14 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
14 #include "llvm/Support/Error.h" 15 #include "llvm/Support/Error.h"
15 #include "llvm/Support/ThreadPool.h" 16 #include "llvm/Support/ThreadPool.h"
16 #include "llvm/Support/raw_ostream.h" 17 #include "llvm/Support/raw_ostream.h"
17 18
258 259
259 260
260 if (!CUI.LineTable->lookupAddressRange(SecAddress, RangeSize, RowVector)) { 261 if (!CUI.LineTable->lookupAddressRange(SecAddress, RangeSize, RowVector)) {
261 // If we have a DW_TAG_subprogram but no line entries, fall back to using 262 // If we have a DW_TAG_subprogram but no line entries, fall back to using
262 // the DW_AT_decl_file an d DW_AT_decl_line if we have both attributes. 263 // the DW_AT_decl_file an d DW_AT_decl_line if we have both attributes.
263 if (auto FileIdx = 264 std::string FilePath = Die.getDeclFile(
264 dwarf::toUnsigned(Die.findRecursively({dwarf::DW_AT_decl_file}))) { 265 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath);
265 if (auto Line = 266 if (FilePath.empty())
266 dwarf::toUnsigned(Die.findRecursively({dwarf::DW_AT_decl_line}))) { 267 return;
267 LineEntry LE(StartAddress, CUI.DWARFToGSYMFileIndex(Gsym, *FileIdx), 268 if (auto Line =
268 *Line); 269 dwarf::toUnsigned(Die.findRecursively({dwarf::DW_AT_decl_line}))) {
269 FI.OptLineTable = LineTable(); 270 LineEntry LE(StartAddress, Gsym.insertFile(FilePath), *Line);
270 FI.OptLineTable->push(LE); 271 FI.OptLineTable = LineTable();
271 // LE.Addr = EndAddress; 272 FI.OptLineTable->push(LE);
272 // FI.OptLineTable->push(LE);
273 }
274 } 273 }
275 return; 274 return;
276 } 275 }
277 276
278 FI.OptLineTable = LineTable(); 277 FI.OptLineTable = LineTable();
287 // we will get a RowIndex for the previous valid line table row which won't 286 // we will get a RowIndex for the previous valid line table row which won't
288 // be contained in our function. This is usually a bug in the DWARF due to 287 // be contained in our function. This is usually a bug in the DWARF due to
289 // linker problems or LTO or other DWARF re-linking so it is worth emitting 288 // linker problems or LTO or other DWARF re-linking so it is worth emitting
290 // an error, but not worth stopping the creation of the GSYM. 289 // an error, but not worth stopping the creation of the GSYM.
291 if (!FI.Range.contains(RowAddress)) { 290 if (!FI.Range.contains(RowAddress)) {
292 if (RowAddress < FI.Range.Start) { 291 if (RowAddress < FI.Range.start()) {
293 Log << "error: DIE has a start address whose LowPC is between the " 292 Log << "error: DIE has a start address whose LowPC is between the "
294 "line table Row[" << RowIndex << "] with address " 293 "line table Row[" << RowIndex << "] with address "
295 << HEX64(RowAddress) << " and the next one.\n"; 294 << HEX64(RowAddress) << " and the next one.\n";
296 Die.dump(Log, 0, DIDumpOptions::getForSingleDIE()); 295 Die.dump(Log, 0, DIDumpOptions::getForSingleDIE());
297 RowAddress = FI.Range.Start; 296 RowAddress = FI.Range.start();
298 } else { 297 } else {
299 continue; 298 continue;
300 } 299 }
301 } 300 }
302 301
392 // and the debug info wasn't able to be stripped from the DWARF. If 391 // and the debug info wasn't able to be stripped from the DWARF. If
393 // the LowPC isn't zero or -1, then we should emit an error. 392 // the LowPC isn't zero or -1, then we should emit an error.
394 if (Range.LowPC != 0) { 393 if (Range.LowPC != 0) {
395 if (!Gsym.isQuiet()) { 394 if (!Gsym.isQuiet()) {
396 // Unexpected invalid address, emit a warning 395 // Unexpected invalid address, emit a warning
397 Log << "warning: DIE has an address range whose start address is " 396 OS << "warning: DIE has an address range whose start address is "
398 "not in any executable sections (" 397 "not in any executable sections ("
399 << *Gsym.GetValidTextRanges() 398 << *Gsym.GetValidTextRanges()
400 << ") and will not be processed:\n"; 399 << ") and will not be processed:\n";
401 Die.dump(Log, 0, DIDumpOptions::getForSingleDIE()); 400 Die.dump(OS, 0, DIDumpOptions::getForSingleDIE());
402 } 401 }
403 } 402 }
404 break; 403 break;
405 } 404 }
406 405
407 FunctionInfo FI; 406 FunctionInfo FI;
408 FI.setStartAddress(Range.LowPC); 407 FI.Range = {Range.LowPC, Range.HighPC};
409 FI.setEndAddress(Range.HighPC);
410 FI.Name = *NameIndex; 408 FI.Name = *NameIndex;
411 if (CUI.LineTable) { 409 if (CUI.LineTable) {
412 convertFunctionLineTable(OS, CUI, Die, Gsym, FI); 410 convertFunctionLineTable(OS, CUI, Die, Gsym, FI);
413 } 411 }
414 if (hasInlineInfo(Die, 0)) { 412 if (hasInlineInfo(Die, 0)) {
427 handleDie(OS, CUI, ChildDie); 425 handleDie(OS, CUI, ChildDie);
428 } 426 }
429 427
430 Error DwarfTransformer::convert(uint32_t NumThreads) { 428 Error DwarfTransformer::convert(uint32_t NumThreads) {
431 size_t NumBefore = Gsym.getNumFunctionInfos(); 429 size_t NumBefore = Gsym.getNumFunctionInfos();
430 auto getDie = [&](DWARFUnit &DwarfUnit) -> DWARFDie {
431 DWARFDie ReturnDie = DwarfUnit.getUnitDIE(false);
432 if (llvm::Optional<uint64_t> DWOId = DwarfUnit.getDWOId()) {
433 DWARFUnit *DWOCU = DwarfUnit.getNonSkeletonUnitDIE(false).getDwarfUnit();
434 if (!DWOCU->isDWOUnit()) {
435 std::string DWOName = dwarf::toString(
436 DwarfUnit.getUnitDIE().find(
437 {dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
438 "");
439 Log << "warning: Unable to retrieve DWO .debug_info section for "
440 << DWOName << "\n";
441 } else {
442 ReturnDie = DWOCU->getUnitDIE(false);
443 }
444 }
445 return ReturnDie;
446 };
432 if (NumThreads == 1) { 447 if (NumThreads == 1) {
433 // Parse all DWARF data from this thread, use the same string/file table 448 // Parse all DWARF data from this thread, use the same string/file table
434 // for everything 449 // for everything
435 for (const auto &CU : DICtx.compile_units()) { 450 for (const auto &CU : DICtx.compile_units()) {
436 DWARFDie Die = CU->getUnitDIE(false); 451 DWARFDie Die = getDie(*CU);
437 CUInfo CUI(DICtx, dyn_cast<DWARFCompileUnit>(CU.get())); 452 CUInfo CUI(DICtx, dyn_cast<DWARFCompileUnit>(CU.get()));
438 handleDie(Log, CUI, Die); 453 handleDie(Log, CUI, Die);
439 } 454 }
440 } else { 455 } else {
441 // LLVM Dwarf parser is not thread-safe and we need to parse all DWARF up 456 // LLVM Dwarf parser is not thread-safe and we need to parse all DWARF up
456 pool.wait(); 471 pool.wait();
457 472
458 // Now convert all DWARF to GSYM in a thread pool. 473 // Now convert all DWARF to GSYM in a thread pool.
459 std::mutex LogMutex; 474 std::mutex LogMutex;
460 for (const auto &CU : DICtx.compile_units()) { 475 for (const auto &CU : DICtx.compile_units()) {
461 DWARFDie Die = CU->getUnitDIE(false /*CUDieOnly*/); 476 DWARFDie Die = getDie(*CU);
462 if (Die) { 477 if (Die) {
463 CUInfo CUI(DICtx, dyn_cast<DWARFCompileUnit>(CU.get())); 478 CUInfo CUI(DICtx, dyn_cast<DWARFCompileUnit>(CU.get()));
464 pool.async([this, CUI, &LogMutex, Die]() mutable { 479 pool.async([this, CUI, &LogMutex, Die]() mutable {
465 std::string ThreadLogStorage; 480 std::string ThreadLogStorage;
466 raw_string_ostream ThreadOS(ThreadLogStorage); 481 raw_string_ostream ThreadOS(ThreadLogStorage);
531 Log << "error: address " << HEX64(Addr) << " has " 546 Log << "error: address " << HEX64(Addr) << " has "
532 << NumDwarfInlineInfos << " DWARF inline frames and GSYM has " 547 << NumDwarfInlineInfos << " DWARF inline frames and GSYM has "
533 << LR->Locations.size() << "\n"; 548 << LR->Locations.size() << "\n";
534 Log << " " << NumDwarfInlineInfos << " DWARF frames:\n"; 549 Log << " " << NumDwarfInlineInfos << " DWARF frames:\n";
535 for (size_t Idx = 0; Idx < NumDwarfInlineInfos; ++Idx) { 550 for (size_t Idx = 0; Idx < NumDwarfInlineInfos; ++Idx) {
536 const auto dii = DwarfInlineInfos.getFrame(Idx); 551 const auto &dii = DwarfInlineInfos.getFrame(Idx);
537 Log << " [" << Idx << "]: " << dii.FunctionName << " @ " 552 Log << " [" << Idx << "]: " << dii.FunctionName << " @ "
538 << dii.FileName << ':' << dii.Line << '\n'; 553 << dii.FileName << ':' << dii.Line << '\n';
539 } 554 }
540 Log << " " << LR->Locations.size() << " GSYM frames:\n"; 555 Log << " " << LR->Locations.size() << " GSYM frames:\n";
541 for (size_t Idx = 0, count = LR->Locations.size(); 556 for (size_t Idx = 0, count = LR->Locations.size();
551 566
552 for (size_t Idx = 0, count = LR->Locations.size(); Idx < count; 567 for (size_t Idx = 0, count = LR->Locations.size(); Idx < count;
553 ++Idx) { 568 ++Idx) {
554 const auto &gii = LR->Locations[Idx]; 569 const auto &gii = LR->Locations[Idx];
555 if (Idx < NumDwarfInlineInfos) { 570 if (Idx < NumDwarfInlineInfos) {
556 const auto dii = DwarfInlineInfos.getFrame(Idx); 571 const auto &dii = DwarfInlineInfos.getFrame(Idx);
557 gsymFilename = LR->getSourceFile(Idx); 572 gsymFilename = LR->getSourceFile(Idx);
558 // Verify function name 573 // Verify function name
559 if (dii.FunctionName.find(gii.Name.str()) != 0) 574 if (dii.FunctionName.find(gii.Name.str()) != 0)
560 Log << "error: address " << HEX64(Addr) << " DWARF function \"" 575 Log << "error: address " << HEX64(Addr) << " DWARF function \""
561 << dii.FunctionName.c_str() 576 << dii.FunctionName.c_str()