1f754f88fSGreg Clayton //===-- ObjectFilePECOFF.h --------------------------------------*- C++ -*-===// 2f754f88fSGreg Clayton // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6f754f88fSGreg Clayton // 7f754f88fSGreg Clayton //===----------------------------------------------------------------------===// 8f754f88fSGreg Clayton 9cdc514e4SJonas Devlieghere #ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_PECOFF_OBJECTFILEPECOFF_H 10cdc514e4SJonas Devlieghere #define LLDB_SOURCE_PLUGINS_OBJECTFILE_PECOFF_OBJECTFILEPECOFF_H 11f754f88fSGreg Clayton 12f754f88fSGreg Clayton #include <vector> 13f754f88fSGreg Clayton 14f754f88fSGreg Clayton #include "lldb/Symbol/ObjectFile.h" 15d372a8e8SPavel Labath #include "llvm/Object/COFF.h" 16f754f88fSGreg Clayton 17b9c1b51eSKate Stone class ObjectFilePECOFF : public lldb_private::ObjectFile { 18f754f88fSGreg Clayton public: 19efe8e7e3SFangrui Song enum MachineType { 20ad587ae4SZachary Turner MachineUnknown = 0x0, 21ad587ae4SZachary Turner MachineAm33 = 0x1d3, 22ad587ae4SZachary Turner MachineAmd64 = 0x8664, 23ad587ae4SZachary Turner MachineArm = 0x1c0, 24ad587ae4SZachary Turner MachineArmNt = 0x1c4, 25ad587ae4SZachary Turner MachineArm64 = 0xaa64, 26ad587ae4SZachary Turner MachineEbc = 0xebc, 27ad587ae4SZachary Turner MachineX86 = 0x14c, 28ad587ae4SZachary Turner MachineIA64 = 0x200, 29ad587ae4SZachary Turner MachineM32R = 0x9041, 30ad587ae4SZachary Turner MachineMips16 = 0x266, 31ad587ae4SZachary Turner MachineMipsFpu = 0x366, 32ad587ae4SZachary Turner MachineMipsFpu16 = 0x466, 33ad587ae4SZachary Turner MachinePowerPc = 0x1f0, 34ad587ae4SZachary Turner MachinePowerPcfp = 0x1f1, 35ad587ae4SZachary Turner MachineR4000 = 0x166, 36ad587ae4SZachary Turner MachineSh3 = 0x1a2, 37ad587ae4SZachary Turner MachineSh3dsp = 0x1a3, 38ad587ae4SZachary Turner MachineSh4 = 0x1a6, 39ad587ae4SZachary Turner MachineSh5 = 0x1a8, 40ad587ae4SZachary Turner MachineThumb = 0x1c2, 41ad587ae4SZachary Turner MachineWcemIpsv2 = 0x169 42efe8e7e3SFangrui Song }; 43f754f88fSGreg Clayton 44f2ea125eSJonas Devlieghere ObjectFilePECOFF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp, 458157a887SEugene Zelenko lldb::offset_t data_offset, 468157a887SEugene Zelenko const lldb_private::FileSpec *file, 47b9c1b51eSKate Stone lldb::offset_t file_offset, lldb::offset_t length); 488157a887SEugene Zelenko 49344546bdSWalter Erquinigo ObjectFilePECOFF(const lldb::ModuleSP &module_sp, 50f2ea125eSJonas Devlieghere lldb::WritableDataBufferSP header_data_sp, 51344546bdSWalter Erquinigo const lldb::ProcessSP &process_sp, lldb::addr_t header_addr); 52344546bdSWalter Erquinigo 538157a887SEugene Zelenko ~ObjectFilePECOFF() override; 548157a887SEugene Zelenko 55f754f88fSGreg Clayton // Static Functions 56b9c1b51eSKate Stone static void Initialize(); 57f754f88fSGreg Clayton 5825c8a061SAlvin Wong static void DebuggerInitialize(lldb_private::Debugger &debugger); 5925c8a061SAlvin Wong 60b9c1b51eSKate Stone static void Terminate(); 61f754f88fSGreg Clayton GetPluginNameStatic()622ace1e57SPavel Labath static llvm::StringRef GetPluginNameStatic() { return "pe-coff"; } 63f754f88fSGreg Clayton 642ace1e57SPavel Labath static llvm::StringRef GetPluginDescriptionStatic(); 65f754f88fSGreg Clayton 66f754f88fSGreg Clayton static ObjectFile * 67c69307e5SJonas Devlieghere CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp, 68b9c1b51eSKate Stone lldb::offset_t data_offset, const lldb_private::FileSpec *file, 69b9c1b51eSKate Stone lldb::offset_t offset, lldb::offset_t length); 70f754f88fSGreg Clayton 71b9c1b51eSKate Stone static lldb_private::ObjectFile *CreateMemoryInstance( 72f2ea125eSJonas Devlieghere const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp, 73b9c1b51eSKate Stone const lldb::ProcessSP &process_sp, lldb::addr_t header_addr); 74f4d6de6aSGreg Clayton 75b9c1b51eSKate Stone static size_t GetModuleSpecifications(const lldb_private::FileSpec &file, 76f4d6de6aSGreg Clayton lldb::DataBufferSP &data_sp, 77f4d6de6aSGreg Clayton lldb::offset_t data_offset, 78f4d6de6aSGreg Clayton lldb::offset_t file_offset, 79f4d6de6aSGreg Clayton lldb::offset_t length, 80f4d6de6aSGreg Clayton lldb_private::ModuleSpecList &specs); 81f4d6de6aSGreg Clayton 82b9c1b51eSKate Stone static bool SaveCore(const lldb::ProcessSP &process_sp, 83f7d1893fSAdrian McCarthy const lldb_private::FileSpec &outfile, 849ea6dd5cSJason Molenda lldb::SaveCoreStyle &core_style, 8597206d57SZachary Turner lldb_private::Status &error); 86f7d1893fSAdrian McCarthy 87f2ea125eSJonas Devlieghere static bool MagicBytesMatch(lldb::DataBufferSP data_sp); 88f754f88fSGreg Clayton 89b9c1b51eSKate Stone static lldb::SymbolType MapSymbolType(uint16_t coff_symbol_type); 90c35b91ceSAdrian McCarthy 91e84f7841SPavel Labath // LLVM RTTI support 92e84f7841SPavel Labath static char ID; isA(const void * ClassID)93e84f7841SPavel Labath bool isA(const void *ClassID) const override { 94e84f7841SPavel Labath return ClassID == &ID || ObjectFile::isA(ClassID); 95e84f7841SPavel Labath } classof(const ObjectFile * obj)96e84f7841SPavel Labath static bool classof(const ObjectFile *obj) { return obj->isA(&ID); } 97e84f7841SPavel Labath 98b9c1b51eSKate Stone bool ParseHeader() override; 99f754f88fSGreg Clayton 100b9c1b51eSKate Stone bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value, 101b9c1b51eSKate Stone bool value_is_offset) override; 102f754f88fSGreg Clayton 103b9c1b51eSKate Stone lldb::ByteOrder GetByteOrder() const override; 104f754f88fSGreg Clayton 105b9c1b51eSKate Stone bool IsExecutable() const override; 106f754f88fSGreg Clayton 107b9c1b51eSKate Stone uint32_t GetAddressByteSize() const override; 108f754f88fSGreg Clayton 109f754f88fSGreg Clayton // virtual lldb_private::AddressClass 110f754f88fSGreg Clayton // GetAddressClass (lldb::addr_t file_addr); 111f754f88fSGreg Clayton 1127e6df41fSGreg Clayton void ParseSymtab(lldb_private::Symtab &symtab) override; 1133046e668SGreg Clayton 114b9c1b51eSKate Stone bool IsStripped() override; 115f754f88fSGreg Clayton 116b9c1b51eSKate Stone void CreateSections(lldb_private::SectionList &unified_section_list) override; 117f754f88fSGreg Clayton 118b9c1b51eSKate Stone void Dump(lldb_private::Stream *s) override; 119f754f88fSGreg Clayton 120f760f5aeSPavel Labath lldb_private::ArchSpec GetArchitecture() override; 121f754f88fSGreg Clayton 122bd334efdSPavel Labath lldb_private::UUID GetUUID() override; 1238157a887SEugene Zelenko 124c8daf4a7SAlvin Wong /// Return the contents of the .gnu_debuglink section, if the object file 125c8daf4a7SAlvin Wong /// contains it. 126c8daf4a7SAlvin Wong llvm::Optional<lldb_private::FileSpec> GetDebugLink(); 127c8daf4a7SAlvin Wong 128b9c1b51eSKate Stone uint32_t GetDependentModules(lldb_private::FileSpecList &files) override; 1298157a887SEugene Zelenko 1301756630dSRaphael Isemann lldb_private::Address GetEntryPointAddress() override; 1318157a887SEugene Zelenko 132d1304bbaSPavel Labath lldb_private::Address GetBaseAddress() override; 133d1304bbaSPavel Labath 134b9c1b51eSKate Stone ObjectFile::Type CalculateType() override; 1358157a887SEugene Zelenko 136b9c1b51eSKate Stone ObjectFile::Strata CalculateStrata() override; 137f754f88fSGreg Clayton 138f754f88fSGreg Clayton // PluginInterface protocol GetPluginName()1392ace1e57SPavel Labath llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } 140f754f88fSGreg Clayton 141fb3b3bd1SZachary Turner bool IsWindowsSubsystem(); 142fb3b3bd1SZachary Turner 14330c2441aSAleksandr Urakov uint32_t GetRVA(const lldb_private::Address &addr) const; 14430c2441aSAleksandr Urakov lldb_private::Address GetAddress(uint32_t rva); 14530c2441aSAleksandr Urakov lldb::addr_t GetFileAddress(uint32_t rva) const; 14630c2441aSAleksandr Urakov 147344546bdSWalter Erquinigo lldb_private::DataExtractor ReadImageData(uint32_t offset, size_t size); 14830c2441aSAleksandr Urakov lldb_private::DataExtractor ReadImageDataByRVA(uint32_t rva, size_t size); 14930c2441aSAleksandr Urakov 15030c2441aSAleksandr Urakov std::unique_ptr<lldb_private::CallFrameInfo> CreateCallFrameInfo() override; 151344546bdSWalter Erquinigo 152f754f88fSGreg Clayton protected: 153f754f88fSGreg Clayton bool NeedsEndianSwap() const; 154f754f88fSGreg Clayton 155f754f88fSGreg Clayton typedef struct dos_header { // DOS .EXE header 156*459cfa5eSSlava Gurevich uint16_t e_magic = 0; // Magic number 157*459cfa5eSSlava Gurevich uint16_t e_cblp = 0; // Bytes on last page of file 158*459cfa5eSSlava Gurevich uint16_t e_cp = 0; // Pages in file 159*459cfa5eSSlava Gurevich uint16_t e_crlc = 0; // Relocations 160*459cfa5eSSlava Gurevich uint16_t e_cparhdr = 0; // Size of header in paragraphs 161*459cfa5eSSlava Gurevich uint16_t e_minalloc = 0; // Minimum extra paragraphs needed 162*459cfa5eSSlava Gurevich uint16_t e_maxalloc = 0; // Maximum extra paragraphs needed 163*459cfa5eSSlava Gurevich uint16_t e_ss = 0; // Initial (relative) SS value 164*459cfa5eSSlava Gurevich uint16_t e_sp = 0; // Initial SP value 165*459cfa5eSSlava Gurevich uint16_t e_csum = 0; // Checksum 166*459cfa5eSSlava Gurevich uint16_t e_ip = 0; // Initial IP value 167*459cfa5eSSlava Gurevich uint16_t e_cs = 0; // Initial (relative) CS value 168*459cfa5eSSlava Gurevich uint16_t e_lfarlc = 0; // File address of relocation table 169*459cfa5eSSlava Gurevich uint16_t e_ovno = 0; // Overlay number 170f754f88fSGreg Clayton uint16_t e_res[4]; // Reserved words 171*459cfa5eSSlava Gurevich uint16_t e_oemid = 0; // OEM identifier (for e_oeminfo) 172*459cfa5eSSlava Gurevich uint16_t e_oeminfo = 0; // OEM information; e_oemid specific 173*459cfa5eSSlava Gurevich uint16_t e_res2[10] = {}; // Reserved words 174*459cfa5eSSlava Gurevich uint32_t e_lfanew = 0; // File address of new exe header 175f754f88fSGreg Clayton } dos_header_t; 176f754f88fSGreg Clayton 177f754f88fSGreg Clayton typedef struct coff_header { 178*459cfa5eSSlava Gurevich uint16_t machine = 0; 179*459cfa5eSSlava Gurevich uint16_t nsects = 0; 180*459cfa5eSSlava Gurevich uint32_t modtime = 0; 181*459cfa5eSSlava Gurevich uint32_t symoff = 0; 182*459cfa5eSSlava Gurevich uint32_t nsyms = 0; 183*459cfa5eSSlava Gurevich uint16_t hdrsize = 0; 184*459cfa5eSSlava Gurevich uint16_t flags = 0; 185f754f88fSGreg Clayton } coff_header_t; 186f754f88fSGreg Clayton 187f754f88fSGreg Clayton typedef struct data_directory { 188*459cfa5eSSlava Gurevich uint32_t vmaddr = 0; 189*459cfa5eSSlava Gurevich uint32_t vmsize = 0; 190f754f88fSGreg Clayton } data_directory_t; 191f754f88fSGreg Clayton 192b9c1b51eSKate Stone typedef struct coff_opt_header { 1935c43ffd6SPavel Labath uint16_t magic = 0; 1945c43ffd6SPavel Labath uint8_t major_linker_version = 0; 1955c43ffd6SPavel Labath uint8_t minor_linker_version = 0; 1965c43ffd6SPavel Labath uint32_t code_size = 0; 1975c43ffd6SPavel Labath uint32_t data_size = 0; 1985c43ffd6SPavel Labath uint32_t bss_size = 0; 1995c43ffd6SPavel Labath uint32_t entry = 0; 2005c43ffd6SPavel Labath uint32_t code_offset = 0; 2015c43ffd6SPavel Labath uint32_t data_offset = 0; 202f754f88fSGreg Clayton 2035c43ffd6SPavel Labath uint64_t image_base = 0; 2045c43ffd6SPavel Labath uint32_t sect_alignment = 0; 2055c43ffd6SPavel Labath uint32_t file_alignment = 0; 2065c43ffd6SPavel Labath uint16_t major_os_system_version = 0; 2075c43ffd6SPavel Labath uint16_t minor_os_system_version = 0; 2085c43ffd6SPavel Labath uint16_t major_image_version = 0; 2095c43ffd6SPavel Labath uint16_t minor_image_version = 0; 2105c43ffd6SPavel Labath uint16_t major_subsystem_version = 0; 2115c43ffd6SPavel Labath uint16_t minor_subsystem_version = 0; 2125c43ffd6SPavel Labath uint32_t reserved1 = 0; 2135c43ffd6SPavel Labath uint32_t image_size = 0; 2145c43ffd6SPavel Labath uint32_t header_size = 0; 2155c43ffd6SPavel Labath uint32_t checksum = 0; 2165c43ffd6SPavel Labath uint16_t subsystem = 0; 2175c43ffd6SPavel Labath uint16_t dll_flags = 0; 2185c43ffd6SPavel Labath uint64_t stack_reserve_size = 0; 2195c43ffd6SPavel Labath uint64_t stack_commit_size = 0; 2205c43ffd6SPavel Labath uint64_t heap_reserve_size = 0; 2215c43ffd6SPavel Labath uint64_t heap_commit_size = 0; 2225c43ffd6SPavel Labath uint32_t loader_flags = 0; 223f754f88fSGreg Clayton // uint32_t num_data_dir_entries; 224b9c1b51eSKate Stone std::vector<data_directory> 225b9c1b51eSKate Stone data_dirs; // will contain num_data_dir_entries entries 226f754f88fSGreg Clayton } coff_opt_header_t; 227f754f88fSGreg Clayton 228efe8e7e3SFangrui Song enum coff_data_dir_type { 229a4fe3a12SVirgile Bello coff_data_dir_export_table = 0, 230a4fe3a12SVirgile Bello coff_data_dir_import_table = 1, 23130c2441aSAleksandr Urakov coff_data_dir_exception_table = 3 232efe8e7e3SFangrui Song }; 233a4fe3a12SVirgile Bello 234f754f88fSGreg Clayton typedef struct section_header { 235*459cfa5eSSlava Gurevich char name[8] = {}; 236*459cfa5eSSlava Gurevich uint32_t vmsize = 0; // Virtual Size 237*459cfa5eSSlava Gurevich uint32_t vmaddr = 0; // Virtual Addr 238*459cfa5eSSlava Gurevich uint32_t size = 0; // File size 239*459cfa5eSSlava Gurevich uint32_t offset = 0; // File offset 240*459cfa5eSSlava Gurevich uint32_t reloff = 0; // Offset to relocations 241*459cfa5eSSlava Gurevich uint32_t lineoff = 0; // Offset to line table entries 242*459cfa5eSSlava Gurevich uint16_t nreloc = 0; // Number of relocation entries 243*459cfa5eSSlava Gurevich uint16_t nline = 0; // Number of line table entries 244*459cfa5eSSlava Gurevich uint32_t flags = 0; 245f754f88fSGreg Clayton } section_header_t; 246f754f88fSGreg Clayton 247f754f88fSGreg Clayton typedef struct coff_symbol { 248*459cfa5eSSlava Gurevich char name[8] = {}; 249*459cfa5eSSlava Gurevich uint32_t value = 0; 250*459cfa5eSSlava Gurevich uint16_t sect = 0; 251*459cfa5eSSlava Gurevich uint16_t type = 0; 252*459cfa5eSSlava Gurevich uint8_t storage = 0; 253*459cfa5eSSlava Gurevich uint8_t naux = 0; 254f754f88fSGreg Clayton } coff_symbol_t; 255f754f88fSGreg Clayton 256a4fe3a12SVirgile Bello typedef struct export_directory_entry { 257*459cfa5eSSlava Gurevich uint32_t characteristics = 0; 258*459cfa5eSSlava Gurevich uint32_t time_date_stamp = 0; 259*459cfa5eSSlava Gurevich uint16_t major_version = 0; 260*459cfa5eSSlava Gurevich uint16_t minor_version = 0; 261*459cfa5eSSlava Gurevich uint32_t name = 0; 262*459cfa5eSSlava Gurevich uint32_t base = 0; 263*459cfa5eSSlava Gurevich uint32_t number_of_functions = 0; 264*459cfa5eSSlava Gurevich uint32_t number_of_names = 0; 265*459cfa5eSSlava Gurevich uint32_t address_of_functions = 0; 266*459cfa5eSSlava Gurevich uint32_t address_of_names = 0; 267*459cfa5eSSlava Gurevich uint32_t address_of_name_ordinals = 0; 2680b5e5f43SMichael Sartain } export_directory_entry; 269a4fe3a12SVirgile Bello 270b9c1b51eSKate Stone static bool ParseDOSHeader(lldb_private::DataExtractor &data, 271b9c1b51eSKate Stone dos_header_t &dos_header); 272b9c1b51eSKate Stone static bool ParseCOFFHeader(lldb_private::DataExtractor &data, 273b9c1b51eSKate Stone lldb::offset_t *offset_ptr, 274b9c1b51eSKate Stone coff_header_t &coff_header); 275c7bece56SGreg Clayton bool ParseCOFFOptionalHeader(lldb::offset_t *offset_ptr); 276f754f88fSGreg Clayton bool ParseSectionHeaders(uint32_t offset); 277f754f88fSGreg Clayton 278037ed1beSAaron Smith uint32_t ParseDependentModules(); 279037ed1beSAaron Smith 280b9c1b51eSKate Stone static void DumpDOSHeader(lldb_private::Stream *s, 281b9c1b51eSKate Stone const dos_header_t &header); 282b9c1b51eSKate Stone static void DumpCOFFHeader(lldb_private::Stream *s, 283b9c1b51eSKate Stone const coff_header_t &header); 284b9c1b51eSKate Stone static void DumpOptCOFFHeader(lldb_private::Stream *s, 285b9c1b51eSKate Stone const coff_opt_header_t &header); 286f754f88fSGreg Clayton void DumpSectionHeaders(lldb_private::Stream *s); 287f754f88fSGreg Clayton void DumpSectionHeader(lldb_private::Stream *s, const section_header_t &sh); 288037ed1beSAaron Smith void DumpDependentModules(lldb_private::Stream *s); 289037ed1beSAaron Smith 2902886e4a0SPavel Labath llvm::StringRef GetSectionName(const section_header_t §); 2912e5bb6d8SMartin Storsjö static lldb::SectionType GetSectionType(llvm::StringRef sect_name, 2922e5bb6d8SMartin Storsjö const section_header_t §); 293f754f88fSGreg Clayton 294f754f88fSGreg Clayton typedef std::vector<section_header_t> SectionHeaderColl; 295f754f88fSGreg Clayton typedef SectionHeaderColl::iterator SectionHeaderCollIter; 296f754f88fSGreg Clayton typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter; 297b9c1b51eSKate Stone 298f754f88fSGreg Clayton private: 299037ed1beSAaron Smith bool CreateBinary(); 300037ed1beSAaron Smith 301f754f88fSGreg Clayton dos_header_t m_dos_header; 302f754f88fSGreg Clayton coff_header_t m_coff_header; 303f754f88fSGreg Clayton coff_opt_header_t m_coff_header_opt; 304f754f88fSGreg Clayton SectionHeaderColl m_sect_headers; 3052756adf3SVirgile Bello lldb::addr_t m_image_base; 3068e38c666SStephane Sezer lldb_private::Address m_entry_point_address; 307037ed1beSAaron Smith llvm::Optional<lldb_private::FileSpecList> m_deps_filespec; 308d372a8e8SPavel Labath std::unique_ptr<llvm::object::COFFObjectFile> m_binary; 309b8d03935SAaron Smith lldb_private::UUID m_uuid; 310f754f88fSGreg Clayton }; 311f754f88fSGreg Clayton 312cdc514e4SJonas Devlieghere #endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_PECOFF_OBJECTFILEPECOFF_H 313