1eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer//===-- COFFDump.cpp - COFF-specific dumper ---------------------*- C++ -*-===// 2eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// 3eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// The LLVM Compiler Infrastructure 4eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// 5eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// This file is distributed under the University of Illinois Open Source 6eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// License. See LICENSE.TXT for details. 7eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// 8eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer//===----------------------------------------------------------------------===// 9eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer/// 10eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer/// \file 11eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer/// \brief This file implements the COFF-specific dumper for llvm-objdump. 12eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer/// It outputs the Win64 EH data structures as plain text. 1336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// The encoding of the unwind codes is described in MSDN: 14eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer/// http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx 15eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer/// 16eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer//===----------------------------------------------------------------------===// 17eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 18eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer#include "llvm-objdump.h" 19eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer#include "llvm/Object/COFF.h" 20eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer#include "llvm/Object/ObjectFile.h" 21eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer#include "llvm/Support/Format.h" 22eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer#include "llvm/Support/SourceMgr.h" 237f00f87767036e74445aad0164eea13cf2642610Chandler Carruth#include "llvm/Support/Win64EH.h" 24eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer#include "llvm/Support/raw_ostream.h" 25eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer#include <algorithm> 26eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer#include <cstring> 27cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include <system_error> 28eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 29eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencerusing namespace llvm; 30eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencerusing namespace object; 31eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencerusing namespace llvm::Win64EH; 32eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 33eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// Returns the name of the unwind code. 34eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencerstatic StringRef getUnwindCodeTypeName(uint8_t Code) { 35eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer switch(Code) { 36eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer default: llvm_unreachable("Invalid unwind code"); 37eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_PushNonVol: return "UOP_PushNonVol"; 38eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_AllocLarge: return "UOP_AllocLarge"; 39eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_AllocSmall: return "UOP_AllocSmall"; 40eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_SetFPReg: return "UOP_SetFPReg"; 41eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_SaveNonVol: return "UOP_SaveNonVol"; 42eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_SaveNonVolBig: return "UOP_SaveNonVolBig"; 43eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_SaveXMM128: return "UOP_SaveXMM128"; 44eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_SaveXMM128Big: return "UOP_SaveXMM128Big"; 45eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_PushMachFrame: return "UOP_PushMachFrame"; 46eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer } 47eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer} 48eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 49eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// Returns the name of a referenced register. 50eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencerstatic StringRef getUnwindRegisterName(uint8_t Reg) { 51eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer switch(Reg) { 52eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer default: llvm_unreachable("Invalid register"); 53eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case 0: return "RAX"; 54eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case 1: return "RCX"; 55eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case 2: return "RDX"; 56eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case 3: return "RBX"; 57eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case 4: return "RSP"; 58eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case 5: return "RBP"; 59eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case 6: return "RSI"; 60eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case 7: return "RDI"; 61eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case 8: return "R8"; 62eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case 9: return "R9"; 63eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case 10: return "R10"; 64eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case 11: return "R11"; 65eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case 12: return "R12"; 66eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case 13: return "R13"; 67eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case 14: return "R14"; 68eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case 15: return "R15"; 69eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer } 70eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer} 71eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 72eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// Calculates the number of array slots required for the unwind code. 73eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencerstatic unsigned getNumUsedSlots(const UnwindCode &UnwindCode) { 74eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer switch (UnwindCode.getUnwindOp()) { 75eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer default: llvm_unreachable("Invalid unwind code"); 76eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_PushNonVol: 77eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_AllocSmall: 78eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_SetFPReg: 79eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_PushMachFrame: 80eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer return 1; 81eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_SaveNonVol: 82eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_SaveXMM128: 83eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer return 2; 84eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_SaveNonVolBig: 85eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_SaveXMM128Big: 86eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer return 3; 87eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_AllocLarge: 88eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer return (UnwindCode.getOpInfo() == 0) ? 2 : 3; 89eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer } 90eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer} 91eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 92eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// Prints one unwind code. Because an unwind code can occupy up to 3 slots in 93eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// the unwind codes array, this function requires that the correct number of 94eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// slots is provided. 95eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencerstatic void printUnwindCode(ArrayRef<UnwindCode> UCs) { 96eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer assert(UCs.size() >= getNumUsedSlots(UCs[0])); 9736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << format(" 0x%02x: ", unsigned(UCs[0].u.CodeOffset)) 98eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer << getUnwindCodeTypeName(UCs[0].getUnwindOp()); 99eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer switch (UCs[0].getUnwindOp()) { 100eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_PushNonVol: 101eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer outs() << " " << getUnwindRegisterName(UCs[0].getOpInfo()); 102eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer break; 103eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_AllocLarge: 104eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer if (UCs[0].getOpInfo() == 0) { 105eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer outs() << " " << UCs[1].FrameOffset; 106eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer } else { 107eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer outs() << " " << UCs[1].FrameOffset 108eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16); 109eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer } 110eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer break; 111eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_AllocSmall: 112eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer outs() << " " << ((UCs[0].getOpInfo() + 1) * 8); 113eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer break; 114eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_SetFPReg: 115eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer outs() << " "; 116eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer break; 117eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_SaveNonVol: 118eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer outs() << " " << getUnwindRegisterName(UCs[0].getOpInfo()) 119eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer << format(" [0x%04x]", 8 * UCs[1].FrameOffset); 120eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer break; 121eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_SaveNonVolBig: 122eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer outs() << " " << getUnwindRegisterName(UCs[0].getOpInfo()) 123eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer << format(" [0x%08x]", UCs[1].FrameOffset 124eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16)); 125eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer break; 126eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_SaveXMM128: 127eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer outs() << " XMM" << static_cast<uint32_t>(UCs[0].getOpInfo()) 128eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer << format(" [0x%04x]", 16 * UCs[1].FrameOffset); 129eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer break; 130eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_SaveXMM128Big: 131eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer outs() << " XMM" << UCs[0].getOpInfo() 132eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer << format(" [0x%08x]", UCs[1].FrameOffset 133eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16)); 134eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer break; 135eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer case UOP_PushMachFrame: 136eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer outs() << " " << (UCs[0].getOpInfo() ? "w/o" : "w") 137eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer << " error code"; 138eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer break; 139eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer } 140eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer outs() << "\n"; 141eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer} 142eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 143eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencerstatic void printAllUnwindCodes(ArrayRef<UnwindCode> UCs) { 144eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer for (const UnwindCode *I = UCs.begin(), *E = UCs.end(); I < E; ) { 145eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer unsigned UsedSlots = getNumUsedSlots(*I); 146eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer if (UsedSlots > UCs.size()) { 147eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer outs() << "Unwind data corrupted: Encountered unwind op " 148eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer << getUnwindCodeTypeName((*I).getUnwindOp()) 149eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer << " which requires " << UsedSlots 150eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer << " slots, but only " << UCs.size() 151eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer << " remaining in buffer"; 152eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer return ; 153eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer } 154eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer printUnwindCode(ArrayRef<UnwindCode>(I, E)); 155eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer I += UsedSlots; 156eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer } 157eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer} 158eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 159eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// Given a symbol sym this functions returns the address and section of it. 160cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic std::error_code 161cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesresolveSectionAndAddress(const COFFObjectFile *Obj, const SymbolRef &Sym, 162cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines const coff_section *&ResolvedSection, 163cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines uint64_t &ResolvedAddr) { 164cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = Sym.getAddress(ResolvedAddr)) 16536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 16636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines section_iterator iter(Obj->section_begin()); 167cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = Sym.getSection(iter)) 16836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 16936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ResolvedSection = Obj->getCOFFSection(*iter); 170eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer return object_error::success; 171eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer} 172eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 173eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// Given a vector of relocations for a section and an offset into this section 174eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// the function returns the symbol used for the relocation at the offset. 175cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic std::error_code resolveSymbol(const std::vector<RelocationRef> &Rels, 176cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines uint64_t Offset, SymbolRef &Sym) { 177eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer for (std::vector<RelocationRef>::const_iterator I = Rels.begin(), 178eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer E = Rels.end(); 179eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer I != E; ++I) { 180eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer uint64_t Ofs; 181cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = I->getOffset(Ofs)) 18236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 183eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer if (Ofs == Offset) { 1846c1202c459ffa6d693ad92fa84e43902bc780bcaRafael Espindola Sym = *I->getSymbol(); 18536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::success; 186eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer } 187eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer } 18836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::parse_failed; 189eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer} 190eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 191eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// Given a vector of relocations for a section and an offset into this section 192eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// the function resolves the symbol used for the relocation at the offset and 193eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// returns the section content and the address inside the content pointed to 194eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// by the symbol. 195cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic std::error_code 196cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesgetSectionContents(const COFFObjectFile *Obj, 197cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines const std::vector<RelocationRef> &Rels, uint64_t Offset, 198cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines ArrayRef<uint8_t> &Contents, uint64_t &Addr) { 199eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer SymbolRef Sym; 200cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = resolveSymbol(Rels, Offset, Sym)) 20136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 202eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer const coff_section *Section; 203cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = resolveSectionAndAddress(Obj, Sym, Section, Addr)) 20436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 205cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = Obj->getSectionContents(Section, Contents)) 20636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 207eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer return object_error::success; 208eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer} 209eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 210eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// Given a vector of relocations for a section and an offset into this section 211eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// the function returns the name of the symbol used for the relocation at the 212eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer// offset. 213cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic std::error_code resolveSymbolName(const std::vector<RelocationRef> &Rels, 214cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines uint64_t Offset, StringRef &Name) { 215eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer SymbolRef Sym; 216cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = resolveSymbol(Rels, Offset, Sym)) 21736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 218cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = Sym.getName(Name)) 21936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 220eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer return object_error::success; 221eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer} 222eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 223eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencerstatic void printCOFFSymbolAddress(llvm::raw_ostream &Out, 224eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer const std::vector<RelocationRef> &Rels, 225eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer uint64_t Offset, uint32_t Disp) { 226eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer StringRef Sym; 22736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!resolveSymbolName(Rels, Offset, Sym)) { 22836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Out << Sym; 22936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Disp > 0) 23036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Out << format(" + 0x%04x", Disp); 23136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 23236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Out << format("0x%04x", Disp); 233eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer } 23436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 23536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 23636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic void 23736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesprintSEHTable(const COFFObjectFile *Obj, uint32_t TableVA, int Count) { 23836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Count == 0) 23936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 24036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 24136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const pe32_header *PE32Header; 24236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (error(Obj->getPE32Header(PE32Header))) 24336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 24436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t ImageBase = PE32Header->ImageBase; 24536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uintptr_t IntPtr = 0; 24636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (error(Obj->getVaPtr(TableVA, IntPtr))) 24736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 24836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const support::ulittle32_t *P = (const support::ulittle32_t *)IntPtr; 24936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << "SEH Table:"; 25036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (int I = 0; I < Count; ++I) 25136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << format(" 0x%x", P[I] + ImageBase); 25236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << "\n\n"; 25336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 25436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 25536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic void printLoadConfiguration(const COFFObjectFile *Obj) { 25636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Skip if it's not executable. 25736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const pe32_header *PE32Header; 25836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (error(Obj->getPE32Header(PE32Header))) 25936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 26036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!PE32Header) 26136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 26236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 26336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_file_header *Header; 26436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (error(Obj->getCOFFHeader(Header))) 26536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 26636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Currently only x86 is supported 26736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Header->Machine != COFF::IMAGE_FILE_MACHINE_I386) 26836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 26936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 27036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const data_directory *DataDir; 27136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (error(Obj->getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataDir))) 27236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 27336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uintptr_t IntPtr = 0; 27436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (DataDir->RelativeVirtualAddress == 0) 27536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 27636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (error(Obj->getRvaPtr(DataDir->RelativeVirtualAddress, IntPtr))) 27736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 27836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 27936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines auto *LoadConf = reinterpret_cast<const coff_load_configuration32 *>(IntPtr); 28036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << "Load configuration:" 28136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n Timestamp: " << LoadConf->TimeDateStamp 28236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n Major Version: " << LoadConf->MajorVersion 28336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n Minor Version: " << LoadConf->MinorVersion 28436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n GlobalFlags Clear: " << LoadConf->GlobalFlagsClear 28536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n GlobalFlags Set: " << LoadConf->GlobalFlagsSet 28636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n Critical Section Default Timeout: " << LoadConf->CriticalSectionDefaultTimeout 28736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n Decommit Free Block Threshold: " << LoadConf->DeCommitFreeBlockThreshold 28836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n Decommit Total Free Threshold: " << LoadConf->DeCommitTotalFreeThreshold 28936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n Lock Prefix Table: " << LoadConf->LockPrefixTable 29036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n Maximum Allocation Size: " << LoadConf->MaximumAllocationSize 29136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n Virtual Memory Threshold: " << LoadConf->VirtualMemoryThreshold 29236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n Process Affinity Mask: " << LoadConf->ProcessAffinityMask 29336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n Process Heap Flags: " << LoadConf->ProcessHeapFlags 29436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n CSD Version: " << LoadConf->CSDVersion 29536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n Security Cookie: " << LoadConf->SecurityCookie 29636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n SEH Table: " << LoadConf->SEHandlerTable 29736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n SEH Count: " << LoadConf->SEHandlerCount 29836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << "\n\n"; 29936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines printSEHTable(Obj, LoadConf->SEHandlerTable, LoadConf->SEHandlerCount); 30036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << "\n"; 301eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer} 302eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 303a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama// Prints import tables. The import table is a table containing the list of 304a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama// DLL name and symbol names which will be linked by the loader. 305a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyamastatic void printImportTables(const COFFObjectFile *Obj) { 30636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines import_directory_iterator I = Obj->import_directory_begin(); 30736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines import_directory_iterator E = Obj->import_directory_end(); 30836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (I == E) 30936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 310a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama outs() << "The Import Tables:\n"; 31136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (; I != E; I = ++I) { 312a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama const import_directory_table_entry *Dir; 313a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama StringRef Name; 31436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (I->getImportTableEntry(Dir)) return; 31536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (I->getName(Name)) return; 316a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 317a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama outs() << format(" lookup %08x time %08x fwd %08x name %08x addr %08x\n\n", 318a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama static_cast<uint32_t>(Dir->ImportLookupTableRVA), 319a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama static_cast<uint32_t>(Dir->TimeDateStamp), 320a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama static_cast<uint32_t>(Dir->ForwarderChain), 321a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama static_cast<uint32_t>(Dir->NameRVA), 322a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama static_cast<uint32_t>(Dir->ImportAddressTableRVA)); 323a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama outs() << " DLL Name: " << Name << "\n"; 324a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama outs() << " Hint/Ord Name\n"; 325a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama const import_lookup_table_entry32 *entry; 32636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (I->getImportLookupEntry(entry)) 327a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama return; 328a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama for (; entry->data; ++entry) { 329a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama if (entry->isOrdinal()) { 330a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama outs() << format(" % 6d\n", entry->getOrdinal()); 331a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama continue; 332a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama } 333a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama uint16_t Hint; 334a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama StringRef Name; 335a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama if (Obj->getHintName(entry->getHintNameRVA(), Hint, Name)) 336a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama return; 337a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama outs() << format(" % 6d ", Hint) << Name << "\n"; 338a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama } 339a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama outs() << "\n"; 340a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama } 341a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 342a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 34336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Prints export tables. The export table is a table containing the list of 34436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// exported symbol from the DLL. 34536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic void printExportTable(const COFFObjectFile *Obj) { 34636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << "Export Table:\n"; 34736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines export_directory_iterator I = Obj->export_directory_begin(); 34836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines export_directory_iterator E = Obj->export_directory_end(); 34936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (I == E) 350eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer return; 35136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StringRef DllName; 35236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t OrdinalBase; 35336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (I->getDllName(DllName)) 35436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 35536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (I->getOrdinalBase(OrdinalBase)) 35636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 35736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " DLL name: " << DllName << "\n"; 35836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " Ordinal base: " << OrdinalBase << "\n"; 35936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " Ordinal RVA Name\n"; 36036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (; I != E; I = ++I) { 36136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t Ordinal; 36236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (I->getOrdinal(Ordinal)) 36336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 36436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t RVA; 36536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (I->getExportRVA(RVA)) 36636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 36736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << format(" % 4d %# 8x", Ordinal, RVA); 368eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 369eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer StringRef Name; 37036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (I->getSymbolName(Name)) 37136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines continue; 37236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!Name.empty()) 37336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " " << Name; 37436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << "\n"; 37536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 37636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 377eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 37836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Given the COFF object file, this function returns the relocations for .pdata 37936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// and the pointer to "runtime function" structs. 38036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic bool getPDataSection(const COFFObjectFile *Obj, 38136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::vector<RelocationRef> &Rels, 38236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const RuntimeFunction *&RFStart, int &NumRFs) { 38336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (const SectionRef &Section : Obj->sections()) { 38436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StringRef Name; 38536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (error(Section.getName(Name))) 38636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines continue; 38736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Name != ".pdata") 38836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines continue; 389eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 39036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Pdata = Obj->getCOFFSection(Section); 39136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (const RelocationRef &Reloc : Section.relocations()) 39236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Rels.push_back(Reloc); 393eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 394eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer // Sort relocations by address. 395eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer std::sort(Rels.begin(), Rels.end(), RelocAddressLess); 396eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 397eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer ArrayRef<uint8_t> Contents; 39836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (error(Obj->getSectionContents(Pdata, Contents))) 39936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines continue; 40036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Contents.empty()) 40136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines continue; 40236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 40336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines RFStart = reinterpret_cast<const RuntimeFunction *>(Contents.data()); 40436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines NumRFs = Contents.size() / sizeof(RuntimeFunction); 40536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return true; 40636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 40736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return false; 40836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 409eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 41036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic void printWin64EHUnwindInfo(const Win64EH::UnwindInfo *UI) { 41136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // The casts to int are required in order to output the value as number. 41236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Without the casts the value would be interpreted as char data (which 41336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // results in garbage output). 41436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " Version: " << static_cast<int>(UI->getVersion()) << "\n"; 41536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " Flags: " << static_cast<int>(UI->getFlags()); 41636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (UI->getFlags()) { 41736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (UI->getFlags() & UNW_ExceptionHandler) 41836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " UNW_ExceptionHandler"; 41936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (UI->getFlags() & UNW_TerminateHandler) 42036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " UNW_TerminateHandler"; 42136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (UI->getFlags() & UNW_ChainInfo) 42236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " UNW_ChainInfo"; 42336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 42436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << "\n"; 42536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " Size of prolog: " << static_cast<int>(UI->PrologSize) << "\n"; 42636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " Number of Codes: " << static_cast<int>(UI->NumCodes) << "\n"; 42736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Maybe this should move to output of UOP_SetFPReg? 42836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (UI->getFrameRegister()) { 42936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " Frame register: " 43036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << getUnwindRegisterName(UI->getFrameRegister()) << "\n"; 43136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " Frame offset: " << 16 * UI->getFrameOffset() << "\n"; 43236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 43336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " No frame pointer used\n"; 43436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 43536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (UI->getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) { 43636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // FIXME: Output exception handler data 43736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else if (UI->getFlags() & UNW_ChainInfo) { 43836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // FIXME: Output chained unwind info 43936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 440eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 44136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (UI->NumCodes) 44236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " Unwind Codes:\n"; 443eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 44436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines printAllUnwindCodes(ArrayRef<UnwindCode>(&UI->UnwindCodes[0], UI->NumCodes)); 44536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 44636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << "\n"; 44736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs().flush(); 44836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 44936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 45036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// Prints out the given RuntimeFunction struct for x64, assuming that Obj is 45136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// pointing to an executable file. 45236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic void printRuntimeFunction(const COFFObjectFile *Obj, 45336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const RuntimeFunction &RF) { 45436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!RF.StartAddress) 45536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 45636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << "Function Table:\n" 45736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << format(" Start Address: 0x%04x\n", 45836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines static_cast<uint32_t>(RF.StartAddress)) 45936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << format(" End Address: 0x%04x\n", 46036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines static_cast<uint32_t>(RF.EndAddress)) 46136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << format(" Unwind Info Address: 0x%04x\n", 46236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines static_cast<uint32_t>(RF.UnwindInfoOffset)); 46336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uintptr_t addr; 46436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Obj->getRvaPtr(RF.UnwindInfoOffset, addr)) 46536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 46636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines printWin64EHUnwindInfo(reinterpret_cast<const Win64EH::UnwindInfo *>(addr)); 46736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 46836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 46936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// Prints out the given RuntimeFunction struct for x64, assuming that Obj is 47036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// pointing to an object file. Unlike executable, fields in RuntimeFunction 47136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// struct are filled with zeros, but instead there are relocations pointing to 47236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// them so that the linker will fill targets' RVAs to the fields at link 47336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// time. This function interprets the relocations to find the data to be used 47436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// in the resulting executable. 47536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic void printRuntimeFunctionRels(const COFFObjectFile *Obj, 47636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const RuntimeFunction &RF, 47736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t SectionOffset, 47836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const std::vector<RelocationRef> &Rels) { 47936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << "Function Table:\n"; 48036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " Start Address: "; 48136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines printCOFFSymbolAddress(outs(), Rels, 48236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SectionOffset + 4831246700d1b5eb5aea5826b6ceed01e3a67ca9a28Michael J. Spencer /*offsetof(RuntimeFunction, StartAddress)*/ 0, 48436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines RF.StartAddress); 48536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << "\n"; 486eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 48736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " End Address: "; 48836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines printCOFFSymbolAddress(outs(), Rels, 48936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SectionOffset + 4901246700d1b5eb5aea5826b6ceed01e3a67ca9a28Michael J. Spencer /*offsetof(RuntimeFunction, EndAddress)*/ 4, 49136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines RF.EndAddress); 49236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << "\n"; 493eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 49436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << " Unwind Info Address: "; 49536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines printCOFFSymbolAddress(outs(), Rels, 49636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SectionOffset + 4971246700d1b5eb5aea5826b6ceed01e3a67ca9a28Michael J. Spencer /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8, 49836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines RF.UnwindInfoOffset); 49936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines outs() << "\n"; 500eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 50136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ArrayRef<uint8_t> XContents; 50236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t UnwindInfoOffset = 0; 50336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (error(getSectionContents( 50436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Obj, Rels, SectionOffset + 50536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8, 50636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines XContents, UnwindInfoOffset))) 50736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 50836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (XContents.empty()) 50936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 510eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 51136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines UnwindInfoOffset += RF.UnwindInfoOffset; 51236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (UnwindInfoOffset > XContents.size()) 51336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 514eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer 51536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines auto *UI = reinterpret_cast<const Win64EH::UnwindInfo *>(XContents.data() + 51636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines UnwindInfoOffset); 51736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines printWin64EHUnwindInfo(UI); 51836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 51936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 52036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) { 52136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_file_header *Header; 52236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (error(Obj->getCOFFHeader(Header))) 52336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 52436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 52536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Header->Machine != COFF::IMAGE_FILE_MACHINE_AMD64) { 52636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines errs() << "Unsupported image machine type " 52736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "(currently only AMD64 is supported).\n"; 52836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 52936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 53036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 53136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::vector<RelocationRef> Rels; 53236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const RuntimeFunction *RFStart; 53336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int NumRFs; 53436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!getPDataSection(Obj, Rels, RFStart, NumRFs)) 53536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 53636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ArrayRef<RuntimeFunction> RFs(RFStart, NumRFs); 53736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 53836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool IsExecutable = Rels.empty(); 53936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (IsExecutable) { 54036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (const RuntimeFunction &RF : RFs) 54136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines printRuntimeFunction(Obj, RF); 54236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 54336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 54436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 54536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (const RuntimeFunction &RF : RFs) { 54636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t SectionOffset = 54736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::distance(RFs.begin(), &RF) * sizeof(RuntimeFunction); 54836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines printRuntimeFunctionRels(Obj, RF, SectionOffset, Rels); 549eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer } 550eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer} 551a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 552a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyamavoid llvm::printCOFFFileHeader(const object::ObjectFile *Obj) { 55336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const COFFObjectFile *file = dyn_cast<const COFFObjectFile>(Obj); 55436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines printLoadConfiguration(file); 55536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines printImportTables(file); 55636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines printExportTable(file); 557a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 558