1 //===-- COFFDumper.cpp - COFF-specific dumper -------------------*- C++ -*-===// 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 /// \file 11 /// \brief This file implements the COFF-specific dumper for llvm-readobj. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm-readobj.h" 16 #include "ARMWinEHPrinter.h" 17 #include "Error.h" 18 #include "ObjDumper.h" 19 #include "StreamWriter.h" 20 #include "Win64EHDumper.h" 21 #include "llvm/ADT/DenseMap.h" 22 #include "llvm/ADT/SmallString.h" 23 #include "llvm/Object/COFF.h" 24 #include "llvm/Object/ObjectFile.h" 25 #include "llvm/Support/COFF.h" 26 #include "llvm/Support/Casting.h" 27 #include "llvm/Support/Compiler.h" 28 #include "llvm/Support/DataExtractor.h" 29 #include "llvm/Support/Format.h" 30 #include "llvm/Support/SourceMgr.h" 31 #include "llvm/Support/Win64EH.h" 32 #include "llvm/Support/raw_ostream.h" 33 #include <algorithm> 34 #include <cstring> 35 #include <system_error> 36 #include <time.h> 37 38 using namespace llvm; 39 using namespace llvm::object; 40 using namespace llvm::Win64EH; 41 42 namespace { 43 44 class COFFDumper : public ObjDumper { 45 public: 46 COFFDumper(const llvm::object::COFFObjectFile *Obj, StreamWriter& Writer) 47 : ObjDumper(Writer) 48 , Obj(Obj) { 49 cacheRelocations(); 50 } 51 52 virtual void printFileHeaders() override; 53 virtual void printSections() override; 54 virtual void printRelocations() override; 55 virtual void printSymbols() override; 56 virtual void printDynamicSymbols() override; 57 virtual void printUnwindInfo() override; 58 59 private: 60 void printSymbol(const SymbolRef &Sym); 61 void printRelocation(const SectionRef &Section, const RelocationRef &Reloc); 62 void printDataDirectory(uint32_t Index, const std::string &FieldName); 63 64 template <class PEHeader> void printPEHeader(const PEHeader *Hdr); 65 void printBaseOfDataField(const pe32_header *Hdr); 66 void printBaseOfDataField(const pe32plus_header *Hdr); 67 68 void printCodeViewLineTables(const SectionRef &Section); 69 70 void cacheRelocations(); 71 72 std::error_code resolveSymbol(const coff_section *Section, uint64_t Offset, 73 SymbolRef &Sym); 74 std::error_code resolveSymbolName(const coff_section *Section, 75 uint64_t Offset, StringRef &Name); 76 77 typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy; 78 79 const llvm::object::COFFObjectFile *Obj; 80 RelocMapTy RelocMap; 81 }; 82 83 } // namespace 84 85 86 namespace llvm { 87 88 std::error_code createCOFFDumper(const object::ObjectFile *Obj, 89 StreamWriter &Writer, 90 std::unique_ptr<ObjDumper> &Result) { 91 const COFFObjectFile *COFFObj = dyn_cast<COFFObjectFile>(Obj); 92 if (!COFFObj) 93 return readobj_error::unsupported_obj_file_format; 94 95 Result.reset(new COFFDumper(COFFObj, Writer)); 96 return readobj_error::success; 97 } 98 99 } // namespace llvm 100 101 // Given a a section and an offset into this section the function returns the 102 // symbol used for the relocation at the offset. 103 std::error_code COFFDumper::resolveSymbol(const coff_section *Section, 104 uint64_t Offset, SymbolRef &Sym) { 105 const auto &Relocations = RelocMap[Section]; 106 for (const auto &Relocation : Relocations) { 107 uint64_t RelocationOffset; 108 if (std::error_code EC = Relocation.getOffset(RelocationOffset)) 109 return EC; 110 111 if (RelocationOffset == Offset) { 112 Sym = *Relocation.getSymbol(); 113 return readobj_error::success; 114 } 115 } 116 return readobj_error::unknown_symbol; 117 } 118 119 // Given a section and an offset into this section the function returns the name 120 // of the symbol used for the relocation at the offset. 121 std::error_code COFFDumper::resolveSymbolName(const coff_section *Section, 122 uint64_t Offset, 123 StringRef &Name) { 124 SymbolRef Symbol; 125 if (std::error_code EC = resolveSymbol(Section, Offset, Symbol)) 126 return EC; 127 if (std::error_code EC = Symbol.getName(Name)) 128 return EC; 129 return object_error::success; 130 } 131 132 static const EnumEntry<COFF::MachineTypes> ImageFileMachineType[] = { 133 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_UNKNOWN ), 134 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AM33 ), 135 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AMD64 ), 136 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM ), 137 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARMNT ), 138 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_EBC ), 139 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_I386 ), 140 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_IA64 ), 141 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_M32R ), 142 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPS16 ), 143 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU ), 144 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU16), 145 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPC ), 146 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPCFP), 147 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_R4000 ), 148 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3 ), 149 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3DSP ), 150 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH4 ), 151 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH5 ), 152 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_THUMB ), 153 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_WCEMIPSV2) 154 }; 155 156 static const EnumEntry<COFF::Characteristics> ImageFileCharacteristics[] = { 157 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_RELOCS_STRIPPED ), 158 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_EXECUTABLE_IMAGE ), 159 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LINE_NUMS_STRIPPED ), 160 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LOCAL_SYMS_STRIPPED ), 161 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_AGGRESSIVE_WS_TRIM ), 162 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LARGE_ADDRESS_AWARE ), 163 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_BYTES_REVERSED_LO ), 164 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_32BIT_MACHINE ), 165 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_DEBUG_STRIPPED ), 166 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP), 167 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_NET_RUN_FROM_SWAP ), 168 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_SYSTEM ), 169 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_DLL ), 170 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_UP_SYSTEM_ONLY ), 171 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_BYTES_REVERSED_HI ) 172 }; 173 174 static const EnumEntry<COFF::WindowsSubsystem> PEWindowsSubsystem[] = { 175 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_UNKNOWN ), 176 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_NATIVE ), 177 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_GUI ), 178 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CUI ), 179 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_POSIX_CUI ), 180 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI ), 181 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_APPLICATION ), 182 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER), 183 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER ), 184 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_ROM ), 185 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_XBOX ), 186 }; 187 188 static const EnumEntry<COFF::DLLCharacteristics> PEDLLCharacteristics[] = { 189 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA ), 190 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE ), 191 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY ), 192 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT ), 193 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION ), 194 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_SEH ), 195 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_BIND ), 196 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_APPCONTAINER ), 197 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER ), 198 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_GUARD_CF ), 199 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE), 200 }; 201 202 static const EnumEntry<COFF::SectionCharacteristics> 203 ImageSectionCharacteristics[] = { 204 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NO_PAD ), 205 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_CODE ), 206 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_INITIALIZED_DATA ), 207 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_UNINITIALIZED_DATA), 208 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_OTHER ), 209 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_INFO ), 210 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_REMOVE ), 211 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_COMDAT ), 212 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_GPREL ), 213 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_PURGEABLE ), 214 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_16BIT ), 215 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_LOCKED ), 216 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_PRELOAD ), 217 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1BYTES ), 218 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2BYTES ), 219 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4BYTES ), 220 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8BYTES ), 221 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_16BYTES ), 222 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_32BYTES ), 223 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_64BYTES ), 224 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_128BYTES ), 225 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_256BYTES ), 226 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_512BYTES ), 227 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1024BYTES ), 228 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2048BYTES ), 229 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4096BYTES ), 230 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8192BYTES ), 231 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_NRELOC_OVFL ), 232 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_DISCARDABLE ), 233 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_CACHED ), 234 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_PAGED ), 235 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_SHARED ), 236 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_EXECUTE ), 237 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_READ ), 238 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_WRITE ) 239 }; 240 241 static const EnumEntry<COFF::SymbolBaseType> ImageSymType[] = { 242 { "Null" , COFF::IMAGE_SYM_TYPE_NULL }, 243 { "Void" , COFF::IMAGE_SYM_TYPE_VOID }, 244 { "Char" , COFF::IMAGE_SYM_TYPE_CHAR }, 245 { "Short" , COFF::IMAGE_SYM_TYPE_SHORT }, 246 { "Int" , COFF::IMAGE_SYM_TYPE_INT }, 247 { "Long" , COFF::IMAGE_SYM_TYPE_LONG }, 248 { "Float" , COFF::IMAGE_SYM_TYPE_FLOAT }, 249 { "Double", COFF::IMAGE_SYM_TYPE_DOUBLE }, 250 { "Struct", COFF::IMAGE_SYM_TYPE_STRUCT }, 251 { "Union" , COFF::IMAGE_SYM_TYPE_UNION }, 252 { "Enum" , COFF::IMAGE_SYM_TYPE_ENUM }, 253 { "MOE" , COFF::IMAGE_SYM_TYPE_MOE }, 254 { "Byte" , COFF::IMAGE_SYM_TYPE_BYTE }, 255 { "Word" , COFF::IMAGE_SYM_TYPE_WORD }, 256 { "UInt" , COFF::IMAGE_SYM_TYPE_UINT }, 257 { "DWord" , COFF::IMAGE_SYM_TYPE_DWORD } 258 }; 259 260 static const EnumEntry<COFF::SymbolComplexType> ImageSymDType[] = { 261 { "Null" , COFF::IMAGE_SYM_DTYPE_NULL }, 262 { "Pointer" , COFF::IMAGE_SYM_DTYPE_POINTER }, 263 { "Function", COFF::IMAGE_SYM_DTYPE_FUNCTION }, 264 { "Array" , COFF::IMAGE_SYM_DTYPE_ARRAY } 265 }; 266 267 static const EnumEntry<COFF::SymbolStorageClass> ImageSymClass[] = { 268 { "EndOfFunction" , COFF::IMAGE_SYM_CLASS_END_OF_FUNCTION }, 269 { "Null" , COFF::IMAGE_SYM_CLASS_NULL }, 270 { "Automatic" , COFF::IMAGE_SYM_CLASS_AUTOMATIC }, 271 { "External" , COFF::IMAGE_SYM_CLASS_EXTERNAL }, 272 { "Static" , COFF::IMAGE_SYM_CLASS_STATIC }, 273 { "Register" , COFF::IMAGE_SYM_CLASS_REGISTER }, 274 { "ExternalDef" , COFF::IMAGE_SYM_CLASS_EXTERNAL_DEF }, 275 { "Label" , COFF::IMAGE_SYM_CLASS_LABEL }, 276 { "UndefinedLabel" , COFF::IMAGE_SYM_CLASS_UNDEFINED_LABEL }, 277 { "MemberOfStruct" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_STRUCT }, 278 { "Argument" , COFF::IMAGE_SYM_CLASS_ARGUMENT }, 279 { "StructTag" , COFF::IMAGE_SYM_CLASS_STRUCT_TAG }, 280 { "MemberOfUnion" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_UNION }, 281 { "UnionTag" , COFF::IMAGE_SYM_CLASS_UNION_TAG }, 282 { "TypeDefinition" , COFF::IMAGE_SYM_CLASS_TYPE_DEFINITION }, 283 { "UndefinedStatic", COFF::IMAGE_SYM_CLASS_UNDEFINED_STATIC }, 284 { "EnumTag" , COFF::IMAGE_SYM_CLASS_ENUM_TAG }, 285 { "MemberOfEnum" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_ENUM }, 286 { "RegisterParam" , COFF::IMAGE_SYM_CLASS_REGISTER_PARAM }, 287 { "BitField" , COFF::IMAGE_SYM_CLASS_BIT_FIELD }, 288 { "Block" , COFF::IMAGE_SYM_CLASS_BLOCK }, 289 { "Function" , COFF::IMAGE_SYM_CLASS_FUNCTION }, 290 { "EndOfStruct" , COFF::IMAGE_SYM_CLASS_END_OF_STRUCT }, 291 { "File" , COFF::IMAGE_SYM_CLASS_FILE }, 292 { "Section" , COFF::IMAGE_SYM_CLASS_SECTION }, 293 { "WeakExternal" , COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL }, 294 { "CLRToken" , COFF::IMAGE_SYM_CLASS_CLR_TOKEN } 295 }; 296 297 static const EnumEntry<COFF::COMDATType> ImageCOMDATSelect[] = { 298 { "NoDuplicates", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES }, 299 { "Any" , COFF::IMAGE_COMDAT_SELECT_ANY }, 300 { "SameSize" , COFF::IMAGE_COMDAT_SELECT_SAME_SIZE }, 301 { "ExactMatch" , COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH }, 302 { "Associative" , COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE }, 303 { "Largest" , COFF::IMAGE_COMDAT_SELECT_LARGEST }, 304 { "Newest" , COFF::IMAGE_COMDAT_SELECT_NEWEST } 305 }; 306 307 static const EnumEntry<COFF::WeakExternalCharacteristics> 308 WeakExternalCharacteristics[] = { 309 { "NoLibrary", COFF::IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY }, 310 { "Library" , COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY }, 311 { "Alias" , COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS } 312 }; 313 314 template <typename T> 315 static std::error_code getSymbolAuxData(const COFFObjectFile *Obj, 316 const coff_symbol *Symbol, 317 const T *&Aux) { 318 ArrayRef<uint8_t> AuxData = Obj->getSymbolAuxData(Symbol); 319 Aux = reinterpret_cast<const T*>(AuxData.data()); 320 return readobj_error::success; 321 } 322 323 void COFFDumper::cacheRelocations() { 324 for (const SectionRef &S : Obj->sections()) { 325 const coff_section *Section = Obj->getCOFFSection(S); 326 327 for (const RelocationRef &Reloc : S.relocations()) 328 RelocMap[Section].push_back(Reloc); 329 330 // Sort relocations by address. 331 std::sort(RelocMap[Section].begin(), RelocMap[Section].end(), 332 relocAddressLess); 333 } 334 } 335 336 void COFFDumper::printDataDirectory(uint32_t Index, const std::string &FieldName) { 337 const data_directory *Data; 338 if (Obj->getDataDirectory(Index, Data)) 339 return; 340 W.printHex(FieldName + "RVA", Data->RelativeVirtualAddress); 341 W.printHex(FieldName + "Size", Data->Size); 342 } 343 344 void COFFDumper::printFileHeaders() { 345 // Print COFF header 346 const coff_file_header *COFFHeader = nullptr; 347 if (error(Obj->getCOFFHeader(COFFHeader))) 348 return; 349 350 time_t TDS = COFFHeader->TimeDateStamp; 351 char FormattedTime[20] = { }; 352 strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS)); 353 354 { 355 DictScope D(W, "ImageFileHeader"); 356 W.printEnum ("Machine", COFFHeader->Machine, 357 makeArrayRef(ImageFileMachineType)); 358 W.printNumber("SectionCount", COFFHeader->NumberOfSections); 359 W.printHex ("TimeDateStamp", FormattedTime, COFFHeader->TimeDateStamp); 360 W.printHex ("PointerToSymbolTable", COFFHeader->PointerToSymbolTable); 361 W.printNumber("SymbolCount", COFFHeader->NumberOfSymbols); 362 W.printNumber("OptionalHeaderSize", COFFHeader->SizeOfOptionalHeader); 363 W.printFlags ("Characteristics", COFFHeader->Characteristics, 364 makeArrayRef(ImageFileCharacteristics)); 365 } 366 367 // Print PE header. This header does not exist if this is an object file and 368 // not an executable. 369 const pe32_header *PEHeader = nullptr; 370 if (error(Obj->getPE32Header(PEHeader))) 371 return; 372 if (PEHeader) 373 printPEHeader<pe32_header>(PEHeader); 374 375 const pe32plus_header *PEPlusHeader = nullptr; 376 if (error(Obj->getPE32PlusHeader(PEPlusHeader))) 377 return; 378 if (PEPlusHeader) 379 printPEHeader<pe32plus_header>(PEPlusHeader); 380 } 381 382 template <class PEHeader> 383 void COFFDumper::printPEHeader(const PEHeader *Hdr) { 384 DictScope D(W, "ImageOptionalHeader"); 385 W.printNumber("MajorLinkerVersion", Hdr->MajorLinkerVersion); 386 W.printNumber("MinorLinkerVersion", Hdr->MinorLinkerVersion); 387 W.printNumber("SizeOfCode", Hdr->SizeOfCode); 388 W.printNumber("SizeOfInitializedData", Hdr->SizeOfInitializedData); 389 W.printNumber("SizeOfUninitializedData", Hdr->SizeOfUninitializedData); 390 W.printHex ("AddressOfEntryPoint", Hdr->AddressOfEntryPoint); 391 W.printHex ("BaseOfCode", Hdr->BaseOfCode); 392 printBaseOfDataField(Hdr); 393 W.printHex ("ImageBase", Hdr->ImageBase); 394 W.printNumber("SectionAlignment", Hdr->SectionAlignment); 395 W.printNumber("FileAlignment", Hdr->FileAlignment); 396 W.printNumber("MajorOperatingSystemVersion", 397 Hdr->MajorOperatingSystemVersion); 398 W.printNumber("MinorOperatingSystemVersion", 399 Hdr->MinorOperatingSystemVersion); 400 W.printNumber("MajorImageVersion", Hdr->MajorImageVersion); 401 W.printNumber("MinorImageVersion", Hdr->MinorImageVersion); 402 W.printNumber("MajorSubsystemVersion", Hdr->MajorSubsystemVersion); 403 W.printNumber("MinorSubsystemVersion", Hdr->MinorSubsystemVersion); 404 W.printNumber("SizeOfImage", Hdr->SizeOfImage); 405 W.printNumber("SizeOfHeaders", Hdr->SizeOfHeaders); 406 W.printEnum ("Subsystem", Hdr->Subsystem, makeArrayRef(PEWindowsSubsystem)); 407 W.printFlags ("Subsystem", Hdr->DLLCharacteristics, 408 makeArrayRef(PEDLLCharacteristics)); 409 W.printNumber("SizeOfStackReserve", Hdr->SizeOfStackReserve); 410 W.printNumber("SizeOfStackCommit", Hdr->SizeOfStackCommit); 411 W.printNumber("SizeOfHeapReserve", Hdr->SizeOfHeapReserve); 412 W.printNumber("SizeOfHeapCommit", Hdr->SizeOfHeapCommit); 413 W.printNumber("NumberOfRvaAndSize", Hdr->NumberOfRvaAndSize); 414 415 if (Hdr->NumberOfRvaAndSize > 0) { 416 DictScope D(W, "DataDirectory"); 417 static const char * const directory[] = { 418 "ExportTable", "ImportTable", "ResourceTable", "ExceptionTable", 419 "CertificateTable", "BaseRelocationTable", "Debug", "Architecture", 420 "GlobalPtr", "TLSTable", "LoadConfigTable", "BoundImport", "IAT", 421 "DelayImportDescriptor", "CLRRuntimeHeader", "Reserved" 422 }; 423 424 for (uint32_t i = 0; i < Hdr->NumberOfRvaAndSize; ++i) { 425 printDataDirectory(i, directory[i]); 426 } 427 } 428 } 429 430 void COFFDumper::printBaseOfDataField(const pe32_header *Hdr) { 431 W.printHex("BaseOfData", Hdr->BaseOfData); 432 } 433 434 void COFFDumper::printBaseOfDataField(const pe32plus_header *) {} 435 436 void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { 437 StringRef Data; 438 if (error(Section.getContents(Data))) 439 return; 440 441 SmallVector<StringRef, 10> FunctionNames; 442 StringMap<StringRef> FunctionLineTables; 443 StringRef FileIndexToStringOffsetTable; 444 StringRef StringTable; 445 446 ListScope D(W, "CodeViewLineTables"); 447 { 448 DataExtractor DE(Data, true, 4); 449 uint32_t Offset = 0, 450 Magic = DE.getU32(&Offset); 451 W.printHex("Magic", Magic); 452 if (Magic != COFF::DEBUG_SECTION_MAGIC) { 453 error(object_error::parse_failed); 454 return; 455 } 456 457 bool Finished = false; 458 while (DE.isValidOffset(Offset) && !Finished) { 459 // The section consists of a number of subsection in the following format: 460 // |Type|PayloadSize|Payload...| 461 uint32_t SubSectionType = DE.getU32(&Offset), 462 PayloadSize = DE.getU32(&Offset); 463 ListScope S(W, "Subsection"); 464 W.printHex("Type", SubSectionType); 465 W.printHex("PayloadSize", PayloadSize); 466 if (PayloadSize > Data.size() - Offset) { 467 error(object_error::parse_failed); 468 return; 469 } 470 471 // Print the raw contents to simplify debugging if anything goes wrong 472 // afterwards. 473 StringRef Contents = Data.substr(Offset, PayloadSize); 474 W.printBinaryBlock("Contents", Contents); 475 476 switch (SubSectionType) { 477 case COFF::DEBUG_LINE_TABLE_SUBSECTION: { 478 // Holds a PC to file:line table. Some data to parse this subsection is 479 // stored in the other subsections, so just check sanity and store the 480 // pointers for deferred processing. 481 482 if (PayloadSize < 12) { 483 // There should be at least three words to store two function 484 // relocations and size of the code. 485 error(object_error::parse_failed); 486 return; 487 } 488 489 StringRef FunctionName; 490 if (error(resolveSymbolName(Obj->getCOFFSection(Section), Offset, 491 FunctionName))) 492 return; 493 W.printString("FunctionName", FunctionName); 494 if (FunctionLineTables.count(FunctionName) != 0) { 495 // Saw debug info for this function already? 496 error(object_error::parse_failed); 497 return; 498 } 499 500 FunctionLineTables[FunctionName] = Contents; 501 FunctionNames.push_back(FunctionName); 502 break; 503 } 504 case COFF::DEBUG_STRING_TABLE_SUBSECTION: 505 if (PayloadSize == 0 || StringTable.data() != nullptr || 506 Contents.back() != '\0') { 507 // Empty or duplicate or non-null-terminated subsection. 508 error(object_error::parse_failed); 509 return; 510 } 511 StringTable = Contents; 512 break; 513 case COFF::DEBUG_INDEX_SUBSECTION: 514 // Holds the translation table from file indices 515 // to offsets in the string table. 516 517 if (PayloadSize == 0 || 518 FileIndexToStringOffsetTable.data() != nullptr) { 519 // Empty or duplicate subsection. 520 error(object_error::parse_failed); 521 return; 522 } 523 FileIndexToStringOffsetTable = Contents; 524 break; 525 } 526 Offset += PayloadSize; 527 528 // Align the reading pointer by 4. 529 Offset += (-Offset) % 4; 530 } 531 } 532 533 // Dump the line tables now that we've read all the subsections and know all 534 // the required information. 535 for (unsigned I = 0, E = FunctionNames.size(); I != E; ++I) { 536 StringRef Name = FunctionNames[I]; 537 ListScope S(W, "FunctionLineTable"); 538 W.printString("FunctionName", Name); 539 540 DataExtractor DE(FunctionLineTables[Name], true, 4); 541 uint32_t Offset = 8; // Skip relocations. 542 uint32_t FunctionSize = DE.getU32(&Offset); 543 W.printHex("CodeSize", FunctionSize); 544 while (DE.isValidOffset(Offset)) { 545 // For each range of lines with the same filename, we have a segment 546 // in the line table. The filename string is accessed using double 547 // indirection to the string table subsection using the index subsection. 548 uint32_t OffsetInIndex = DE.getU32(&Offset), 549 SegmentLength = DE.getU32(&Offset), 550 FullSegmentSize = DE.getU32(&Offset); 551 if (FullSegmentSize != 12 + 8 * SegmentLength) { 552 error(object_error::parse_failed); 553 return; 554 } 555 556 uint32_t FilenameOffset; 557 { 558 DataExtractor SDE(FileIndexToStringOffsetTable, true, 4); 559 uint32_t OffsetInSDE = OffsetInIndex; 560 if (!SDE.isValidOffset(OffsetInSDE)) { 561 error(object_error::parse_failed); 562 return; 563 } 564 FilenameOffset = SDE.getU32(&OffsetInSDE); 565 } 566 567 if (FilenameOffset == 0 || FilenameOffset + 1 >= StringTable.size() || 568 StringTable.data()[FilenameOffset - 1] != '\0') { 569 // Each string in an F3 subsection should be preceded by a null 570 // character. 571 error(object_error::parse_failed); 572 return; 573 } 574 575 StringRef Filename(StringTable.data() + FilenameOffset); 576 ListScope S(W, "FilenameSegment"); 577 W.printString("Filename", Filename); 578 for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset); 579 ++J) { 580 // Then go the (PC, LineNumber) pairs. The line number is stored in the 581 // least significant 31 bits of the respective word in the table. 582 uint32_t PC = DE.getU32(&Offset), 583 LineNumber = DE.getU32(&Offset) & 0x7fffffff; 584 if (PC >= FunctionSize) { 585 error(object_error::parse_failed); 586 return; 587 } 588 char Buffer[32]; 589 format("+0x%X", PC).snprint(Buffer, 32); 590 W.printNumber(Buffer, LineNumber); 591 } 592 } 593 } 594 } 595 596 void COFFDumper::printSections() { 597 ListScope SectionsD(W, "Sections"); 598 int SectionNumber = 0; 599 for (const SectionRef &Sec : Obj->sections()) { 600 ++SectionNumber; 601 const coff_section *Section = Obj->getCOFFSection(Sec); 602 603 StringRef Name; 604 if (error(Sec.getName(Name))) 605 Name = ""; 606 607 DictScope D(W, "Section"); 608 W.printNumber("Number", SectionNumber); 609 W.printBinary("Name", Name, Section->Name); 610 W.printHex ("VirtualSize", Section->VirtualSize); 611 W.printHex ("VirtualAddress", Section->VirtualAddress); 612 W.printNumber("RawDataSize", Section->SizeOfRawData); 613 W.printHex ("PointerToRawData", Section->PointerToRawData); 614 W.printHex ("PointerToRelocations", Section->PointerToRelocations); 615 W.printHex ("PointerToLineNumbers", Section->PointerToLinenumbers); 616 W.printNumber("RelocationCount", Section->NumberOfRelocations); 617 W.printNumber("LineNumberCount", Section->NumberOfLinenumbers); 618 W.printFlags ("Characteristics", Section->Characteristics, 619 makeArrayRef(ImageSectionCharacteristics), 620 COFF::SectionCharacteristics(0x00F00000)); 621 622 if (opts::SectionRelocations) { 623 ListScope D(W, "Relocations"); 624 for (const RelocationRef &Reloc : Sec.relocations()) 625 printRelocation(Sec, Reloc); 626 } 627 628 if (opts::SectionSymbols) { 629 ListScope D(W, "Symbols"); 630 for (const SymbolRef &Symbol : Obj->symbols()) { 631 bool Contained = false; 632 if (Sec.containsSymbol(Symbol, Contained) || !Contained) 633 continue; 634 635 printSymbol(Symbol); 636 } 637 } 638 639 if (Name == ".debug$S" && opts::CodeViewLineTables) 640 printCodeViewLineTables(Sec); 641 642 if (opts::SectionData) { 643 StringRef Data; 644 if (error(Sec.getContents(Data))) 645 break; 646 647 W.printBinaryBlock("SectionData", Data); 648 } 649 } 650 } 651 652 void COFFDumper::printRelocations() { 653 ListScope D(W, "Relocations"); 654 655 int SectionNumber = 0; 656 for (const SectionRef &Section : Obj->sections()) { 657 ++SectionNumber; 658 StringRef Name; 659 if (error(Section.getName(Name))) 660 continue; 661 662 bool PrintedGroup = false; 663 for (const RelocationRef &Reloc : Section.relocations()) { 664 if (!PrintedGroup) { 665 W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n"; 666 W.indent(); 667 PrintedGroup = true; 668 } 669 670 printRelocation(Section, Reloc); 671 } 672 673 if (PrintedGroup) { 674 W.unindent(); 675 W.startLine() << "}\n"; 676 } 677 } 678 } 679 680 void COFFDumper::printRelocation(const SectionRef &Section, 681 const RelocationRef &Reloc) { 682 uint64_t Offset; 683 uint64_t RelocType; 684 SmallString<32> RelocName; 685 StringRef SymbolName; 686 StringRef Contents; 687 if (error(Reloc.getOffset(Offset))) 688 return; 689 if (error(Reloc.getType(RelocType))) 690 return; 691 if (error(Reloc.getTypeName(RelocName))) 692 return; 693 symbol_iterator Symbol = Reloc.getSymbol(); 694 if (error(Symbol->getName(SymbolName))) 695 return; 696 if (error(Section.getContents(Contents))) 697 return; 698 699 if (opts::ExpandRelocs) { 700 DictScope Group(W, "Relocation"); 701 W.printHex("Offset", Offset); 702 W.printNumber("Type", RelocName, RelocType); 703 W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); 704 } else { 705 raw_ostream& OS = W.startLine(); 706 OS << W.hex(Offset) 707 << " " << RelocName 708 << " " << (SymbolName.size() > 0 ? SymbolName : "-") 709 << "\n"; 710 } 711 } 712 713 void COFFDumper::printSymbols() { 714 ListScope Group(W, "Symbols"); 715 716 for (const SymbolRef &Symbol : Obj->symbols()) 717 printSymbol(Symbol); 718 } 719 720 void COFFDumper::printDynamicSymbols() { ListScope Group(W, "DynamicSymbols"); } 721 722 void COFFDumper::printSymbol(const SymbolRef &Sym) { 723 DictScope D(W, "Symbol"); 724 725 const coff_symbol *Symbol = Obj->getCOFFSymbol(Sym); 726 const coff_section *Section; 727 if (std::error_code EC = Obj->getSection(Symbol->SectionNumber, Section)) { 728 W.startLine() << "Invalid section number: " << EC.message() << "\n"; 729 W.flush(); 730 return; 731 } 732 733 StringRef SymbolName; 734 if (Obj->getSymbolName(Symbol, SymbolName)) 735 SymbolName = ""; 736 737 StringRef SectionName = ""; 738 if (Section) 739 Obj->getSectionName(Section, SectionName); 740 741 W.printString("Name", SymbolName); 742 W.printNumber("Value", Symbol->Value); 743 W.printNumber("Section", SectionName, Symbol->SectionNumber); 744 W.printEnum ("BaseType", Symbol->getBaseType(), makeArrayRef(ImageSymType)); 745 W.printEnum ("ComplexType", Symbol->getComplexType(), 746 makeArrayRef(ImageSymDType)); 747 W.printEnum ("StorageClass", Symbol->StorageClass, 748 makeArrayRef(ImageSymClass)); 749 W.printNumber("AuxSymbolCount", Symbol->NumberOfAuxSymbols); 750 751 for (unsigned I = 0; I < Symbol->NumberOfAuxSymbols; ++I) { 752 if (Symbol->isFunctionDefinition()) { 753 const coff_aux_function_definition *Aux; 754 if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) 755 break; 756 757 DictScope AS(W, "AuxFunctionDef"); 758 W.printNumber("TagIndex", Aux->TagIndex); 759 W.printNumber("TotalSize", Aux->TotalSize); 760 W.printHex("PointerToLineNumber", Aux->PointerToLinenumber); 761 W.printHex("PointerToNextFunction", Aux->PointerToNextFunction); 762 W.printBinary("Unused", makeArrayRef(Aux->Unused)); 763 764 } else if (Symbol->isWeakExternal()) { 765 const coff_aux_weak_external *Aux; 766 if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) 767 break; 768 769 const coff_symbol *Linked; 770 StringRef LinkedName; 771 std::error_code EC; 772 if ((EC = Obj->getSymbol(Aux->TagIndex, Linked)) || 773 (EC = Obj->getSymbolName(Linked, LinkedName))) { 774 LinkedName = ""; 775 error(EC); 776 } 777 778 DictScope AS(W, "AuxWeakExternal"); 779 W.printNumber("Linked", LinkedName, Aux->TagIndex); 780 W.printEnum ("Search", Aux->Characteristics, 781 makeArrayRef(WeakExternalCharacteristics)); 782 W.printBinary("Unused", makeArrayRef(Aux->Unused)); 783 784 } else if (Symbol->isFileRecord()) { 785 const coff_aux_file *Aux; 786 if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) 787 break; 788 789 DictScope AS(W, "AuxFileRecord"); 790 791 StringRef Name(Aux->FileName, 792 Symbol->NumberOfAuxSymbols * COFF::SymbolSize); 793 W.printString("FileName", Name.rtrim(StringRef("\0", 1))); 794 break; 795 } else if (Symbol->isSectionDefinition()) { 796 const coff_aux_section_definition *Aux; 797 if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) 798 break; 799 800 DictScope AS(W, "AuxSectionDef"); 801 W.printNumber("Length", Aux->Length); 802 W.printNumber("RelocationCount", Aux->NumberOfRelocations); 803 W.printNumber("LineNumberCount", Aux->NumberOfLinenumbers); 804 W.printHex("Checksum", Aux->CheckSum); 805 W.printNumber("Number", Aux->Number); 806 W.printEnum("Selection", Aux->Selection, makeArrayRef(ImageCOMDATSelect)); 807 W.printBinary("Unused", makeArrayRef(Aux->Unused)); 808 809 if (Section && Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT 810 && Aux->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { 811 const coff_section *Assoc; 812 StringRef AssocName; 813 std::error_code EC; 814 if ((EC = Obj->getSection(Aux->Number, Assoc)) || 815 (EC = Obj->getSectionName(Assoc, AssocName))) { 816 AssocName = ""; 817 error(EC); 818 } 819 820 W.printNumber("AssocSection", AssocName, Aux->Number); 821 } 822 } else if (Symbol->isCLRToken()) { 823 const coff_aux_clr_token *Aux; 824 if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) 825 break; 826 827 const coff_symbol *ReferredSym; 828 StringRef ReferredName; 829 std::error_code EC; 830 if ((EC = Obj->getSymbol(Aux->SymbolTableIndex, ReferredSym)) || 831 (EC = Obj->getSymbolName(ReferredSym, ReferredName))) { 832 ReferredName = ""; 833 error(EC); 834 } 835 836 DictScope AS(W, "AuxCLRToken"); 837 W.printNumber("AuxType", Aux->AuxType); 838 W.printNumber("Reserved", Aux->Reserved); 839 W.printNumber("SymbolTableIndex", ReferredName, Aux->SymbolTableIndex); 840 W.printBinary("Unused", makeArrayRef(Aux->Unused)); 841 842 } else { 843 W.startLine() << "<unhandled auxiliary record>\n"; 844 } 845 } 846 } 847 848 void COFFDumper::printUnwindInfo() { 849 const coff_file_header *Header; 850 if (error(Obj->getCOFFHeader(Header))) 851 return; 852 853 ListScope D(W, "UnwindInformation"); 854 switch (Header->Machine) { 855 case COFF::IMAGE_FILE_MACHINE_AMD64: { 856 Win64EH::Dumper Dumper(W); 857 Win64EH::Dumper::SymbolResolver 858 Resolver = [](const object::coff_section *Section, uint64_t Offset, 859 SymbolRef &Symbol, void *user_data) -> std::error_code { 860 COFFDumper *Dumper = reinterpret_cast<COFFDumper *>(user_data); 861 return Dumper->resolveSymbol(Section, Offset, Symbol); 862 }; 863 Win64EH::Dumper::Context Ctx(*Obj, Resolver, this); 864 Dumper.printData(Ctx); 865 break; 866 } 867 case COFF::IMAGE_FILE_MACHINE_ARMNT: { 868 ARM::WinEH::Decoder Decoder(W); 869 Decoder.dumpProcedureData(*Obj); 870 break; 871 } 872 default: 873 W.printEnum("unsupported Image Machine", Header->Machine, 874 makeArrayRef(ImageFileMachineType)); 875 break; 876 } 877 } 878 879