llvm.org GIT mirror llvm / d1a0a58
llvm-objdump: Split printCOFFUnwindInfo into small functions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202772 91177308-0d34-0410-b5e6-96231b3b80d8 Rui Ueyama 6 years ago
1 changed file(s) with 128 addition(s) and 110 deletion(s). Raw diff Collapse all Expand all
377377 }
378378 }
379379
380 void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
381 const coff_file_header *Header;
382 if (error(Obj->getCOFFHeader(Header))) return;
383
384 if (Header->Machine != COFF::IMAGE_FILE_MACHINE_AMD64) {
385 errs() << "Unsupported image machine type "
386 "(currently only AMD64 is supported).\n";
387 return;
388 }
389
390 const coff_section *Pdata = 0;
391
380 // Given the COFF object file, this function returns the relocations for .pdata
381 // and the pointer to "runtime function" structs.
382 static bool getPDataSection(const COFFObjectFile *Obj,
383 std::vector &Rels,
384 const RuntimeFunction *&RFStart, int &NumRFs) {
392385 for (section_iterator SI = Obj->section_begin(), SE = Obj->section_end();
393386 SI != SE; ++SI) {
394387 StringRef Name;
395 if (error(SI->getName(Name))) continue;
396
397 if (Name != ".pdata") continue;
398
399 Pdata = Obj->getCOFFSection(SI);
400 std::vector Rels;
388 if (error(SI->getName(Name)))
389 continue;
390 if (Name != ".pdata")
391 continue;
392
393 const coff_section *Pdata = Obj->getCOFFSection(SI);
401394 for (relocation_iterator RI = SI->relocation_begin(),
402395 RE = SI->relocation_end();
403396 RI != RE; ++RI)
407400 std::sort(Rels.begin(), Rels.end(), RelocAddressLess);
408401
409402 ArrayRef Contents;
410 if (error(Obj->getSectionContents(Pdata, Contents))) continue;
411 if (Contents.empty()) continue;
412
413 ArrayRef RFs(
414 reinterpret_cast(Contents.data()),
415 Contents.size() / sizeof(RuntimeFunction));
416 for (const RuntimeFunction &RF : RFs) {
417 const uint64_t SectionOffset =
418 std::distance(RFs.begin(), &RF) * sizeof(RuntimeFunction);
419
420 outs() << "Function Table:\n";
421
422 outs() << " Start Address: ";
423 printCOFFSymbolAddress(outs(), Rels,
424 SectionOffset +
425 /*offsetof(RuntimeFunction, StartAddress)*/ 0,
426 RF.StartAddress);
427 outs() << "\n";
428
429 outs() << " End Address: ";
430 printCOFFSymbolAddress(outs(), Rels,
431 SectionOffset +
432 /*offsetof(RuntimeFunction, EndAddress)*/ 4,
433 RF.EndAddress);
434 outs() << "\n";
435
436 outs() << " Unwind Info Address: ";
437 printCOFFSymbolAddress(
438 outs(), Rels, SectionOffset +
439 /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8,
440 RF.UnwindInfoOffset);
441 outs() << "\n";
442
443 ArrayRef XContents;
444 uint64_t UnwindInfoOffset = 0;
445 if (error(getSectionContents(Obj, Rels, SectionOffset +
446 /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8,
447 XContents, UnwindInfoOffset))) continue;
448 if (XContents.empty()) continue;
449
450 UnwindInfoOffset += RF.UnwindInfoOffset;
451 if (UnwindInfoOffset > XContents.size())
452 continue;
453
454 const Win64EH::UnwindInfo *UI =
455 reinterpret_cast
456 (XContents.data() + UnwindInfoOffset);
457
458 // The casts to int are required in order to output the value as number.
459 // Without the casts the value would be interpreted as char data (which
460 // results in garbage output).
461 outs() << " Version: " << static_cast(UI->getVersion()) << "\n";
462 outs() << " Flags: " << static_cast(UI->getFlags());
463 if (UI->getFlags()) {
464 if (UI->getFlags() & UNW_ExceptionHandler)
465 outs() << " UNW_ExceptionHandler";
466 if (UI->getFlags() & UNW_TerminateHandler)
467 outs() << " UNW_TerminateHandler";
468 if (UI->getFlags() & UNW_ChainInfo)
469 outs() << " UNW_ChainInfo";
470 }
471 outs() << "\n";
472 outs() << " Size of prolog: "
473 << static_cast(UI->PrologSize) << "\n";
474 outs() << " Number of Codes: "
475 << static_cast(UI->NumCodes) << "\n";
476 // Maybe this should move to output of UOP_SetFPReg?
477 if (UI->getFrameRegister()) {
478 outs() << " Frame register: "
479 << getUnwindRegisterName(UI->getFrameRegister())
480 << "\n";
481 outs() << " Frame offset: "
482 << 16 * UI->getFrameOffset()
483 << "\n";
484 } else {
485 outs() << " No frame pointer used\n";
486 }
487 if (UI->getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) {
488 // FIXME: Output exception handler data
489 } else if (UI->getFlags() & UNW_ChainInfo) {
490 // FIXME: Output chained unwind info
491 }
492
493 if (UI->NumCodes)
494 outs() << " Unwind Codes:\n";
495
496 printAllUnwindCodes(ArrayRef(&UI->UnwindCodes[0],
497 UI->NumCodes));
498
499 outs() << "\n\n";
500 outs().flush();
501 }
403 if (error(Obj->getSectionContents(Pdata, Contents)))
404 continue;
405 if (Contents.empty())
406 continue;
407
408 RFStart = reinterpret_cast(Contents.data());
409 NumRFs = Contents.size() / sizeof(RuntimeFunction);
410 return true;
411 }
412 return false;
413 }
414
415 static void printRuntimeFunction(const COFFObjectFile *Obj,
416 const RuntimeFunction &RF,
417 uint64_t SectionOffset,
418 const std::vector &Rels) {
419 outs() << "Function Table:\n";
420
421 outs() << " Start Address: ";
422 printCOFFSymbolAddress(outs(), Rels,
423 SectionOffset +
424 /*offsetof(RuntimeFunction, StartAddress)*/ 0,
425 RF.StartAddress);
426 outs() << "\n";
427
428 outs() << " End Address: ";
429 printCOFFSymbolAddress(outs(), Rels,
430 SectionOffset +
431 /*offsetof(RuntimeFunction, EndAddress)*/ 4,
432 RF.EndAddress);
433 outs() << "\n";
434
435 outs() << " Unwind Info Address: ";
436 printCOFFSymbolAddress(outs(), Rels,
437 SectionOffset +
438 /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8,
439 RF.UnwindInfoOffset);
440 outs() << "\n";
441
442 ArrayRef XContents;
443 uint64_t UnwindInfoOffset = 0;
444 if (error(getSectionContents(
445 Obj, Rels, SectionOffset +
446 /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8,
447 XContents, UnwindInfoOffset)))
448 return;
449 if (XContents.empty())
450 return;
451
452 UnwindInfoOffset += RF.UnwindInfoOffset;
453 if (UnwindInfoOffset > XContents.size())
454 return;
455
456 const Win64EH::UnwindInfo *UI = reinterpret_cast(
457 XContents.data() + UnwindInfoOffset);
458
459 // The casts to int are required in order to output the value as number.
460 // Without the casts the value would be interpreted as char data (which
461 // results in garbage output).
462 outs() << " Version: " << static_cast(UI->getVersion()) << "\n";
463 outs() << " Flags: " << static_cast(UI->getFlags());
464 if (UI->getFlags()) {
465 if (UI->getFlags() & UNW_ExceptionHandler)
466 outs() << " UNW_ExceptionHandler";
467 if (UI->getFlags() & UNW_TerminateHandler)
468 outs() << " UNW_TerminateHandler";
469 if (UI->getFlags() & UNW_ChainInfo)
470 outs() << " UNW_ChainInfo";
471 }
472 outs() << "\n";
473 outs() << " Size of prolog: " << static_cast(UI->PrologSize) << "\n";
474 outs() << " Number of Codes: " << static_cast(UI->NumCodes) << "\n";
475 // Maybe this should move to output of UOP_SetFPReg?
476 if (UI->getFrameRegister()) {
477 outs() << " Frame register: "
478 << getUnwindRegisterName(UI->getFrameRegister()) << "\n";
479 outs() << " Frame offset: " << 16 * UI->getFrameOffset() << "\n";
480 } else {
481 outs() << " No frame pointer used\n";
482 }
483 if (UI->getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) {
484 // FIXME: Output exception handler data
485 } else if (UI->getFlags() & UNW_ChainInfo) {
486 // FIXME: Output chained unwind info
487 }
488
489 if (UI->NumCodes)
490 outs() << " Unwind Codes:\n";
491
492 printAllUnwindCodes(ArrayRef(&UI->UnwindCodes[0], UI->NumCodes));
493
494 outs() << "\n\n";
495 outs().flush();
496 }
497
498 void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
499 const coff_file_header *Header;
500 if (error(Obj->getCOFFHeader(Header)))
501 return;
502
503 if (Header->Machine != COFF::IMAGE_FILE_MACHINE_AMD64) {
504 errs() << "Unsupported image machine type "
505 "(currently only AMD64 is supported).\n";
506 return;
507 }
508
509 std::vector Rels;
510 const RuntimeFunction *RFStart;
511 int NumRFs;
512 if (!getPDataSection(Obj, Rels, RFStart, NumRFs))
513 return;
514 ArrayRef RFs(RFStart, NumRFs);
515
516 for (const RuntimeFunction &RF : RFs) {
517 uint64_t SectionOffset =
518 std::distance(RFs.begin(), &RF) * sizeof(RuntimeFunction);
519 printRuntimeFunction(Obj, RF, SectionOffset, Rels);
502520 }
503521 }
504522