| 1 | //===-- ObjectFilePECOFF.h --------------------------------------*- C++ -*-===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_PECOFF_OBJECTFILEPECOFF_H |
| 10 | #define LLDB_SOURCE_PLUGINS_OBJECTFILE_PECOFF_OBJECTFILEPECOFF_H |
| 11 | |
| 12 | #include <optional> |
| 13 | #include <vector> |
| 14 | |
| 15 | #include "lldb/Symbol/ObjectFile.h" |
| 16 | #include "lldb/Symbol/SaveCoreOptions.h" |
| 17 | #include "llvm/Object/COFF.h" |
| 18 | |
| 19 | class ObjectFilePECOFF : public lldb_private::ObjectFile { |
| 20 | public: |
| 21 | enum MachineType { |
| 22 | MachineUnknown = 0x0, |
| 23 | MachineAm33 = 0x1d3, |
| 24 | MachineAmd64 = 0x8664, |
| 25 | MachineArm = 0x1c0, |
| 26 | MachineArmNt = 0x1c4, |
| 27 | MachineArm64 = 0xaa64, |
| 28 | MachineArm64X = 0xa64e, |
| 29 | MachineEbc = 0xebc, |
| 30 | MachineX86 = 0x14c, |
| 31 | MachineIA64 = 0x200, |
| 32 | MachineM32R = 0x9041, |
| 33 | MachineMips16 = 0x266, |
| 34 | MachineMipsFpu = 0x366, |
| 35 | MachineMipsFpu16 = 0x466, |
| 36 | MachinePowerPc = 0x1f0, |
| 37 | MachinePowerPcfp = 0x1f1, |
| 38 | MachineR4000 = 0x166, |
| 39 | MachineSh3 = 0x1a2, |
| 40 | MachineSh3dsp = 0x1a3, |
| 41 | MachineSh4 = 0x1a6, |
| 42 | MachineSh5 = 0x1a8, |
| 43 | MachineThumb = 0x1c2, |
| 44 | MachineWcemIpsv2 = 0x169 |
| 45 | }; |
| 46 | |
| 47 | ObjectFilePECOFF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp, |
| 48 | lldb::offset_t data_offset, |
| 49 | const lldb_private::FileSpec *file, |
| 50 | lldb::offset_t file_offset, lldb::offset_t length); |
| 51 | |
| 52 | ObjectFilePECOFF(const lldb::ModuleSP &module_sp, |
| 53 | lldb::WritableDataBufferSP , |
| 54 | const lldb::ProcessSP &process_sp, lldb::addr_t ); |
| 55 | |
| 56 | ~ObjectFilePECOFF() override; |
| 57 | |
| 58 | // Static Functions |
| 59 | static void Initialize(); |
| 60 | |
| 61 | static void DebuggerInitialize(lldb_private::Debugger &debugger); |
| 62 | |
| 63 | static void Terminate(); |
| 64 | |
| 65 | static llvm::StringRef GetPluginNameStatic() { return "pe-coff" ; } |
| 66 | |
| 67 | static llvm::StringRef GetPluginDescriptionStatic(); |
| 68 | |
| 69 | static ObjectFile * |
| 70 | CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp, |
| 71 | lldb::offset_t data_offset, const lldb_private::FileSpec *file, |
| 72 | lldb::offset_t offset, lldb::offset_t length); |
| 73 | |
| 74 | static lldb_private::ObjectFile *CreateMemoryInstance( |
| 75 | const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp, |
| 76 | const lldb::ProcessSP &process_sp, lldb::addr_t ); |
| 77 | |
| 78 | static size_t GetModuleSpecifications(const lldb_private::FileSpec &file, |
| 79 | lldb::DataBufferSP &data_sp, |
| 80 | lldb::offset_t data_offset, |
| 81 | lldb::offset_t file_offset, |
| 82 | lldb::offset_t length, |
| 83 | lldb_private::ModuleSpecList &specs); |
| 84 | |
| 85 | static bool SaveCore(const lldb::ProcessSP &process_sp, |
| 86 | lldb_private::SaveCoreOptions &options, |
| 87 | lldb_private::Status &error); |
| 88 | |
| 89 | static bool MagicBytesMatch(lldb::DataBufferSP data_sp); |
| 90 | |
| 91 | static lldb::SymbolType MapSymbolType(uint16_t coff_symbol_type); |
| 92 | |
| 93 | // LLVM RTTI support |
| 94 | static char ID; |
| 95 | bool isA(const void *ClassID) const override { |
| 96 | return ClassID == &ID || ObjectFile::isA(ClassID); |
| 97 | } |
| 98 | static bool classof(const ObjectFile *obj) { return obj->isA(ClassID: &ID); } |
| 99 | |
| 100 | bool () override; |
| 101 | |
| 102 | bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value, |
| 103 | bool value_is_offset) override; |
| 104 | |
| 105 | lldb::ByteOrder GetByteOrder() const override; |
| 106 | |
| 107 | bool IsExecutable() const override; |
| 108 | |
| 109 | uint32_t GetAddressByteSize() const override; |
| 110 | |
| 111 | // virtual lldb_private::AddressClass |
| 112 | // GetAddressClass (lldb::addr_t file_addr); |
| 113 | |
| 114 | void ParseSymtab(lldb_private::Symtab &symtab) override; |
| 115 | |
| 116 | bool IsStripped() override; |
| 117 | |
| 118 | void CreateSections(lldb_private::SectionList &unified_section_list) override; |
| 119 | |
| 120 | void Dump(lldb_private::Stream *s) override; |
| 121 | |
| 122 | lldb_private::ArchSpec GetArchitecture() override; |
| 123 | |
| 124 | lldb_private::UUID GetUUID() override; |
| 125 | |
| 126 | /// Return the contents of the .gnu_debuglink section, if the object file |
| 127 | /// contains it. |
| 128 | std::optional<lldb_private::FileSpec> GetDebugLink(); |
| 129 | |
| 130 | uint32_t GetDependentModules(lldb_private::FileSpecList &files) override; |
| 131 | |
| 132 | lldb_private::Address GetEntryPointAddress() override; |
| 133 | |
| 134 | lldb_private::Address GetBaseAddress() override; |
| 135 | |
| 136 | ObjectFile::Type CalculateType() override; |
| 137 | |
| 138 | ObjectFile::Strata CalculateStrata() override; |
| 139 | |
| 140 | // PluginInterface protocol |
| 141 | llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } |
| 142 | |
| 143 | bool IsWindowsSubsystem(); |
| 144 | |
| 145 | uint32_t GetRVA(const lldb_private::Address &addr) const; |
| 146 | lldb_private::Address GetAddress(uint32_t rva); |
| 147 | lldb::addr_t GetFileAddress(uint32_t rva) const; |
| 148 | |
| 149 | lldb_private::DataExtractor ReadImageData(uint32_t offset, size_t size); |
| 150 | lldb_private::DataExtractor ReadImageDataByRVA(uint32_t rva, size_t size); |
| 151 | |
| 152 | std::unique_ptr<lldb_private::CallFrameInfo> CreateCallFrameInfo() override; |
| 153 | |
| 154 | protected: |
| 155 | bool NeedsEndianSwap() const; |
| 156 | |
| 157 | typedef struct { // DOS .EXE header |
| 158 | uint16_t = 0; // Magic number |
| 159 | uint16_t = 0; // Bytes on last page of file |
| 160 | uint16_t = 0; // Pages in file |
| 161 | uint16_t = 0; // Relocations |
| 162 | uint16_t = 0; // Size of header in paragraphs |
| 163 | uint16_t = 0; // Minimum extra paragraphs needed |
| 164 | uint16_t = 0; // Maximum extra paragraphs needed |
| 165 | uint16_t = 0; // Initial (relative) SS value |
| 166 | uint16_t = 0; // Initial SP value |
| 167 | uint16_t = 0; // Checksum |
| 168 | uint16_t = 0; // Initial IP value |
| 169 | uint16_t = 0; // Initial (relative) CS value |
| 170 | uint16_t = 0; // File address of relocation table |
| 171 | uint16_t = 0; // Overlay number |
| 172 | uint16_t [4]; // Reserved words |
| 173 | uint16_t = 0; // OEM identifier (for e_oeminfo) |
| 174 | uint16_t = 0; // OEM information; e_oemid specific |
| 175 | uint16_t [10] = {}; // Reserved words |
| 176 | uint32_t = 0; // File address of new exe header |
| 177 | } ; |
| 178 | |
| 179 | typedef struct { |
| 180 | uint16_t = 0; |
| 181 | uint16_t = 0; |
| 182 | uint32_t = 0; |
| 183 | uint32_t = 0; |
| 184 | uint32_t = 0; |
| 185 | uint16_t = 0; |
| 186 | uint16_t = 0; |
| 187 | } ; |
| 188 | |
| 189 | typedef struct data_directory { |
| 190 | uint32_t vmaddr = 0; |
| 191 | uint32_t vmsize = 0; |
| 192 | } data_directory_t; |
| 193 | |
| 194 | typedef struct { |
| 195 | uint16_t = 0; |
| 196 | uint8_t = 0; |
| 197 | uint8_t = 0; |
| 198 | uint32_t = 0; |
| 199 | uint32_t = 0; |
| 200 | uint32_t = 0; |
| 201 | uint32_t = 0; |
| 202 | uint32_t = 0; |
| 203 | uint32_t = 0; |
| 204 | |
| 205 | uint64_t = 0; |
| 206 | uint32_t = 0; |
| 207 | uint32_t = 0; |
| 208 | uint16_t = 0; |
| 209 | uint16_t = 0; |
| 210 | uint16_t = 0; |
| 211 | uint16_t = 0; |
| 212 | uint16_t = 0; |
| 213 | uint16_t = 0; |
| 214 | uint32_t = 0; |
| 215 | uint32_t = 0; |
| 216 | uint32_t = 0; |
| 217 | uint32_t = 0; |
| 218 | uint16_t = 0; |
| 219 | uint16_t = 0; |
| 220 | uint64_t = 0; |
| 221 | uint64_t = 0; |
| 222 | uint64_t = 0; |
| 223 | uint64_t = 0; |
| 224 | uint32_t = 0; |
| 225 | // uint32_t num_data_dir_entries; |
| 226 | std::vector<data_directory> |
| 227 | ; // will contain num_data_dir_entries entries |
| 228 | } ; |
| 229 | |
| 230 | typedef struct { |
| 231 | char [8] = {}; |
| 232 | uint32_t = 0; // Virtual Size |
| 233 | uint32_t = 0; // Virtual Addr |
| 234 | uint32_t = 0; // File size |
| 235 | uint32_t = 0; // File offset |
| 236 | uint32_t = 0; // Offset to relocations |
| 237 | uint32_t = 0; // Offset to line table entries |
| 238 | uint16_t = 0; // Number of relocation entries |
| 239 | uint16_t = 0; // Number of line table entries |
| 240 | uint32_t = 0; |
| 241 | } ; |
| 242 | |
| 243 | static bool (lldb_private::DataExtractor &data, |
| 244 | dos_header_t &); |
| 245 | static bool (lldb_private::DataExtractor &data, |
| 246 | lldb::offset_t *offset_ptr, |
| 247 | coff_header_t &); |
| 248 | bool (lldb::offset_t *offset_ptr); |
| 249 | bool (uint32_t offset); |
| 250 | |
| 251 | uint32_t ParseDependentModules(); |
| 252 | |
| 253 | static void (lldb_private::Stream *s, |
| 254 | const dos_header_t &); |
| 255 | static void (lldb_private::Stream *s, |
| 256 | const coff_header_t &); |
| 257 | static void (lldb_private::Stream *s, |
| 258 | const coff_opt_header_t &); |
| 259 | void (lldb_private::Stream *s); |
| 260 | void (lldb_private::Stream *s, const section_header_t &sh); |
| 261 | void DumpDependentModules(lldb_private::Stream *s); |
| 262 | |
| 263 | llvm::StringRef (const section_header_t §); |
| 264 | static lldb::SectionType (llvm::StringRef sect_name, |
| 265 | const section_header_t §); |
| 266 | size_t GetSectionDataSize(lldb_private::Section *section) override; |
| 267 | |
| 268 | typedef std::vector<section_header_t> ; |
| 269 | typedef SectionHeaderColl::iterator ; |
| 270 | typedef SectionHeaderColl::const_iterator ; |
| 271 | |
| 272 | private: |
| 273 | bool CreateBinary(); |
| 274 | typedef std::vector<std::pair<uint32_t, uint32_t>> rva_symbol_list_t; |
| 275 | void AppendFromCOFFSymbolTable(lldb_private::SectionList *sect_list, |
| 276 | lldb_private::Symtab &symtab, |
| 277 | const rva_symbol_list_t &sorted_exports); |
| 278 | rva_symbol_list_t AppendFromExportTable(lldb_private::SectionList *sect_list, |
| 279 | lldb_private::Symtab &symtab); |
| 280 | |
| 281 | dos_header_t ; |
| 282 | coff_header_t ; |
| 283 | coff_opt_header_t ; |
| 284 | SectionHeaderColl ; |
| 285 | lldb::addr_t m_image_base; |
| 286 | lldb_private::Address m_entry_point_address; |
| 287 | std::optional<lldb_private::FileSpecList> m_deps_filespec; |
| 288 | std::unique_ptr<llvm::object::COFFObjectFile> m_binary; |
| 289 | lldb_private::UUID m_uuid; |
| 290 | }; |
| 291 | |
| 292 | #endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_PECOFF_OBJECTFILEPECOFF_H |
| 293 | |