From d1a0a587011dc8de63e0f648168ec9c1c9d6c864 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Tue, 4 Mar 2014 00:31:48 +0000 Subject: [PATCH] llvm-objdump: Split printCOFFUnwindInfo into small functions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202772 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/llvm-objdump/COFFDump.cpp | 228 ++++++++++++++++++++++------------------ 1 file changed, 123 insertions(+), 105 deletions(-) diff --git a/tools/llvm-objdump/COFFDump.cpp b/tools/llvm-objdump/COFFDump.cpp index 424ae7c71d5..74d4e369597 100644 --- a/tools/llvm-objdump/COFFDump.cpp +++ b/tools/llvm-objdump/COFFDump.cpp @@ -378,27 +378,20 @@ static void printExportTable(const COFFObjectFile *Obj) { } } -void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) { - const coff_file_header *Header; - if (error(Obj->getCOFFHeader(Header))) return; - - if (Header->Machine != COFF::IMAGE_FILE_MACHINE_AMD64) { - errs() << "Unsupported image machine type " - "(currently only AMD64 is supported).\n"; - return; - } - - const coff_section *Pdata = 0; - +// Given the COFF object file, this function returns the relocations for .pdata +// and the pointer to "runtime function" structs. +static bool getPDataSection(const COFFObjectFile *Obj, + std::vector &Rels, + const RuntimeFunction *&RFStart, int &NumRFs) { for (section_iterator SI = Obj->section_begin(), SE = Obj->section_end(); SI != SE; ++SI) { StringRef Name; - if (error(SI->getName(Name))) continue; - - if (Name != ".pdata") continue; + if (error(SI->getName(Name))) + continue; + if (Name != ".pdata") + continue; - Pdata = Obj->getCOFFSection(SI); - std::vector Rels; + const coff_section *Pdata = Obj->getCOFFSection(SI); for (relocation_iterator RI = SI->relocation_begin(), RE = SI->relocation_end(); RI != RE; ++RI) @@ -408,98 +401,123 @@ void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) { std::sort(Rels.begin(), Rels.end(), RelocAddressLess); ArrayRef Contents; - if (error(Obj->getSectionContents(Pdata, Contents))) continue; - if (Contents.empty()) continue; - - ArrayRef RFs( - reinterpret_cast(Contents.data()), - Contents.size() / sizeof(RuntimeFunction)); - for (const RuntimeFunction &RF : RFs) { - const uint64_t SectionOffset = - std::distance(RFs.begin(), &RF) * sizeof(RuntimeFunction); - - outs() << "Function Table:\n"; - - outs() << " Start Address: "; - printCOFFSymbolAddress(outs(), Rels, - SectionOffset + - /*offsetof(RuntimeFunction, StartAddress)*/ 0, - RF.StartAddress); - outs() << "\n"; - - outs() << " End Address: "; - printCOFFSymbolAddress(outs(), Rels, - SectionOffset + - /*offsetof(RuntimeFunction, EndAddress)*/ 4, - RF.EndAddress); - outs() << "\n"; - - outs() << " Unwind Info Address: "; - printCOFFSymbolAddress( - outs(), Rels, SectionOffset + - /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8, - RF.UnwindInfoOffset); - outs() << "\n"; - - ArrayRef XContents; - uint64_t UnwindInfoOffset = 0; - if (error(getSectionContents(Obj, Rels, SectionOffset + - /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8, - XContents, UnwindInfoOffset))) continue; - if (XContents.empty()) continue; - - UnwindInfoOffset += RF.UnwindInfoOffset; - if (UnwindInfoOffset > XContents.size()) - continue; + if (error(Obj->getSectionContents(Pdata, Contents))) + continue; + if (Contents.empty()) + continue; - const Win64EH::UnwindInfo *UI = - reinterpret_cast - (XContents.data() + UnwindInfoOffset); - - // The casts to int are required in order to output the value as number. - // Without the casts the value would be interpreted as char data (which - // results in garbage output). - outs() << " Version: " << static_cast(UI->getVersion()) << "\n"; - outs() << " Flags: " << static_cast(UI->getFlags()); - if (UI->getFlags()) { - if (UI->getFlags() & UNW_ExceptionHandler) - outs() << " UNW_ExceptionHandler"; - if (UI->getFlags() & UNW_TerminateHandler) - outs() << " UNW_TerminateHandler"; - if (UI->getFlags() & UNW_ChainInfo) - outs() << " UNW_ChainInfo"; - } - outs() << "\n"; - outs() << " Size of prolog: " - << static_cast(UI->PrologSize) << "\n"; - outs() << " Number of Codes: " - << static_cast(UI->NumCodes) << "\n"; - // Maybe this should move to output of UOP_SetFPReg? - if (UI->getFrameRegister()) { - outs() << " Frame register: " - << getUnwindRegisterName(UI->getFrameRegister()) - << "\n"; - outs() << " Frame offset: " - << 16 * UI->getFrameOffset() - << "\n"; - } else { - outs() << " No frame pointer used\n"; - } - if (UI->getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) { - // FIXME: Output exception handler data - } else if (UI->getFlags() & UNW_ChainInfo) { - // FIXME: Output chained unwind info - } + RFStart = reinterpret_cast(Contents.data()); + NumRFs = Contents.size() / sizeof(RuntimeFunction); + return true; + } + return false; +} - if (UI->NumCodes) - outs() << " Unwind Codes:\n"; +static void printRuntimeFunction(const COFFObjectFile *Obj, + const RuntimeFunction &RF, + uint64_t SectionOffset, + const std::vector &Rels) { + outs() << "Function Table:\n"; + + outs() << " Start Address: "; + printCOFFSymbolAddress(outs(), Rels, + SectionOffset + + /*offsetof(RuntimeFunction, StartAddress)*/ 0, + RF.StartAddress); + outs() << "\n"; - printAllUnwindCodes(ArrayRef(&UI->UnwindCodes[0], - UI->NumCodes)); + outs() << " End Address: "; + printCOFFSymbolAddress(outs(), Rels, + SectionOffset + + /*offsetof(RuntimeFunction, EndAddress)*/ 4, + RF.EndAddress); + outs() << "\n"; - outs() << "\n\n"; - outs().flush(); - } + outs() << " Unwind Info Address: "; + printCOFFSymbolAddress(outs(), Rels, + SectionOffset + + /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8, + RF.UnwindInfoOffset); + outs() << "\n"; + + ArrayRef XContents; + uint64_t UnwindInfoOffset = 0; + if (error(getSectionContents( + Obj, Rels, SectionOffset + + /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8, + XContents, UnwindInfoOffset))) + return; + if (XContents.empty()) + return; + + UnwindInfoOffset += RF.UnwindInfoOffset; + if (UnwindInfoOffset > XContents.size()) + return; + + const Win64EH::UnwindInfo *UI = reinterpret_cast( + XContents.data() + UnwindInfoOffset); + + // The casts to int are required in order to output the value as number. + // Without the casts the value would be interpreted as char data (which + // results in garbage output). + outs() << " Version: " << static_cast(UI->getVersion()) << "\n"; + outs() << " Flags: " << static_cast(UI->getFlags()); + if (UI->getFlags()) { + if (UI->getFlags() & UNW_ExceptionHandler) + outs() << " UNW_ExceptionHandler"; + if (UI->getFlags() & UNW_TerminateHandler) + outs() << " UNW_TerminateHandler"; + if (UI->getFlags() & UNW_ChainInfo) + outs() << " UNW_ChainInfo"; + } + outs() << "\n"; + outs() << " Size of prolog: " << static_cast(UI->PrologSize) << "\n"; + outs() << " Number of Codes: " << static_cast(UI->NumCodes) << "\n"; + // Maybe this should move to output of UOP_SetFPReg? + if (UI->getFrameRegister()) { + outs() << " Frame register: " + << getUnwindRegisterName(UI->getFrameRegister()) << "\n"; + outs() << " Frame offset: " << 16 * UI->getFrameOffset() << "\n"; + } else { + outs() << " No frame pointer used\n"; + } + if (UI->getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) { + // FIXME: Output exception handler data + } else if (UI->getFlags() & UNW_ChainInfo) { + // FIXME: Output chained unwind info + } + + if (UI->NumCodes) + outs() << " Unwind Codes:\n"; + + printAllUnwindCodes(ArrayRef(&UI->UnwindCodes[0], UI->NumCodes)); + + outs() << "\n\n"; + outs().flush(); +} + +void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) { + const coff_file_header *Header; + if (error(Obj->getCOFFHeader(Header))) + return; + + if (Header->Machine != COFF::IMAGE_FILE_MACHINE_AMD64) { + errs() << "Unsupported image machine type " + "(currently only AMD64 is supported).\n"; + return; + } + + std::vector Rels; + const RuntimeFunction *RFStart; + int NumRFs; + if (!getPDataSection(Obj, Rels, RFStart, NumRFs)) + return; + ArrayRef RFs(RFStart, NumRFs); + + for (const RuntimeFunction &RF : RFs) { + uint64_t SectionOffset = + std::distance(RFs.begin(), &RF) * sizeof(RuntimeFunction); + printRuntimeFunction(Obj, RF, SectionOffset, Rels); } } -- 2.11.0