text: //===-- ObjectFilePECOFF.h --------------------------------------*- C++ -*-===//
  //
  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  // See https://llvm.org/LICENSE.txt for license information.
  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  //
  //===----------------------------------------------------------------------===//
  
  #ifndef liblldb_ObjectFilePECOFF_h_
  #define liblldb_ObjectFilePECOFF_h_
  
  #include <vector>
  
  #include "lldb/Symbol/ObjectFile.h"
  #include "llvm/Object/Binary.h"
  
  class ObjectFilePECOFF : public lldb_private::ObjectFile {
  public:
    enum MachineType {
      MachineUnknown = 0x0,
      MachineAm33 = 0x1d3,
      MachineAmd64 = 0x8664,
      MachineArm = 0x1c0,
      MachineArmNt = 0x1c4,
      MachineArm64 = 0xaa64,
      MachineEbc = 0xebc,
      MachineX86 = 0x14c,
      MachineIA64 = 0x200,
      MachineM32R = 0x9041,
      MachineMips16 = 0x266,
      MachineMipsFpu = 0x366,
      MachineMipsFpu16 = 0x466,
      MachinePowerPc = 0x1f0,
      MachinePowerPcfp = 0x1f1,
      MachineR4000 = 0x166,
      MachineSh3 = 0x1a2,
      MachineSh3dsp = 0x1a3,
      MachineSh4 = 0x1a6,
      MachineSh5 = 0x1a8,
      MachineThumb = 0x1c2,
      MachineWcemIpsv2 = 0x169
    };
  
    ObjectFilePECOFF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
                     lldb::offset_t data_offset,
                     const lldb_private::FileSpec *file,
                     lldb::offset_t file_offset, lldb::offset_t length);
  
    ObjectFilePECOFF(const lldb::ModuleSP &module_sp,
                     lldb::DataBufferSP &header_data_sp,
                     const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
  
    ~ObjectFilePECOFF() override;
  
    // Static Functions
    static void Initialize();
  
    static void Terminate();
  
    static lldb_private::ConstString GetPluginNameStatic();
  
    static const char *GetPluginDescriptionStatic();
  
    static ObjectFile *
    CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
                   lldb::offset_t data_offset, const lldb_private::FileSpec *file,
                   lldb::offset_t offset, lldb::offset_t length);
  
    static lldb_private::ObjectFile *CreateMemoryInstance(
        const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
        const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
  
    static size_t GetModuleSpecifications(const lldb_private::FileSpec &file,
                                          lldb::DataBufferSP &data_sp,
                                          lldb::offset_t data_offset,
                                          lldb::offset_t file_offset,
                                          lldb::offset_t length,
                                          lldb_private::ModuleSpecList &specs);
  
    static bool SaveCore(const lldb::ProcessSP &process_sp,
                         const lldb_private::FileSpec &outfile,
                         lldb_private::Status &error);
  
    static bool MagicBytesMatch(lldb::DataBufferSP &data_sp);
  
    static lldb::SymbolType MapSymbolType(uint16_t coff_symbol_type);
  
    // LLVM RTTI support
    static char ID;
    bool isA(const void *ClassID) const override {
      return ClassID == &ID || ObjectFile::isA(ClassID);
    }
    static bool classof(const ObjectFile *obj) { return obj->isA(&ID); }
  
    bool ParseHeader() override;
  
    bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value,
                        bool value_is_offset) override;
  
    lldb::ByteOrder GetByteOrder() const override;
  
    bool IsExecutable() const override;
  
    uint32_t GetAddressByteSize() const override;
  
    //    virtual lldb_private::AddressClass
    //    GetAddressClass (lldb::addr_t file_addr);
  
    lldb_private::Symtab *GetSymtab() override;
  
    bool IsStripped() override;
  
    void CreateSections(lldb_private::SectionList &unified_section_list) override;
  
    void Dump(lldb_private::Stream *s) override;
  
    lldb_private::ArchSpec GetArchitecture() override;
  
    lldb_private::UUID GetUUID() override;
  
    uint32_t GetDependentModules(lldb_private::FileSpecList &files) override;
  
    lldb_private::Address GetEntryPointAddress() override;
  
    lldb_private::Address GetBaseAddress() override;
  
    ObjectFile::Type CalculateType() override;
  
    ObjectFile::Strata CalculateStrata() override;
  
    // PluginInterface protocol
    lldb_private::ConstString GetPluginName() override;
  
    uint32_t GetPluginVersion() override;
  
    bool IsWindowsSubsystem();
  
    uint32_t GetRVA(const lldb_private::Address &addr) const;
    lldb_private::Address GetAddress(uint32_t rva);
    lldb::addr_t GetFileAddress(uint32_t rva) const;
  
    lldb_private::DataExtractor ReadImageData(uint32_t offset, size_t size);
    lldb_private::DataExtractor ReadImageDataByRVA(uint32_t rva, size_t size);
  
    std::unique_ptr<lldb_private::CallFrameInfo> CreateCallFrameInfo() override;
  
  protected:
    bool NeedsEndianSwap() const;
  
    typedef struct dos_header { // DOS .EXE header
      uint16_t e_magic;         // Magic number
      uint16_t e_cblp;          // Bytes on last page of file
      uint16_t e_cp;            // Pages in file
      uint16_t e_crlc;          // Relocations
      uint16_t e_cparhdr;       // Size of header in paragraphs
      uint16_t e_minalloc;      // Minimum extra paragraphs needed
      uint16_t e_maxalloc;      // Maximum extra paragraphs needed
      uint16_t e_ss;            // Initial (relative) SS value
      uint16_t e_sp;            // Initial SP value
      uint16_t e_csum;          // Checksum
      uint16_t e_ip;            // Initial IP value
      uint16_t e_cs;            // Initial (relative) CS value
      uint16_t e_lfarlc;        // File address of relocation table
      uint16_t e_ovno;          // Overlay number
      uint16_t e_res[4];        // Reserved words
      uint16_t e_oemid;         // OEM identifier (for e_oeminfo)
      uint16_t e_oeminfo;       // OEM information; e_oemid specific
      uint16_t e_res2[10];      // Reserved words
      uint32_t e_lfanew;        // File address of new exe header
    } dos_header_t;
  
    typedef struct coff_header {
      uint16_t machine;
      uint16_t nsects;
      uint32_t modtime;
      uint32_t symoff;
      uint32_t nsyms;
      uint16_t hdrsize;
      uint16_t flags;
    } coff_header_t;
  
    typedef struct data_directory {
      uint32_t vmaddr;
      uint32_t vmsize;
    } data_directory_t;
  
    typedef struct coff_opt_header {
      uint16_t magic = 0;
      uint8_t major_linker_version = 0;
      uint8_t minor_linker_version = 0;
      uint32_t code_size = 0;
      uint32_t data_size = 0;
      uint32_t bss_size = 0;
      uint32_t entry = 0;
      uint32_t code_offset = 0;
      uint32_t data_offset = 0;
  
      uint64_t image_base = 0;
      uint32_t sect_alignment = 0;
      uint32_t file_alignment = 0;
      uint16_t major_os_system_version = 0;
      uint16_t minor_os_system_version = 0;
      uint16_t major_image_version = 0;
      uint16_t minor_image_version = 0;
      uint16_t major_subsystem_version = 0;
      uint16_t minor_subsystem_version = 0;
      uint32_t reserved1 = 0;
      uint32_t image_size = 0;
      uint32_t header_size = 0;
      uint32_t checksum = 0;
      uint16_t subsystem = 0;
      uint16_t dll_flags = 0;
      uint64_t stack_reserve_size = 0;
      uint64_t stack_commit_size = 0;
      uint64_t heap_reserve_size = 0;
      uint64_t heap_commit_size = 0;
      uint32_t loader_flags = 0;
      //    uint32_t	num_data_dir_entries;
      std::vector<data_directory>
          data_dirs; // will contain num_data_dir_entries entries
    } coff_opt_header_t;
  
    enum coff_data_dir_type {
      coff_data_dir_export_table = 0,
      coff_data_dir_import_table = 1,
      coff_data_dir_exception_table = 3
    };
  
    typedef struct section_header {
      char name[8];
      uint32_t vmsize;  // Virtual Size
      uint32_t vmaddr;  // Virtual Addr
      uint32_t size;    // File size
      uint32_t offset;  // File offset
      uint32_t reloff;  // Offset to relocations
      uint32_t lineoff; // Offset to line table entries
      uint16_t nreloc;  // Number of relocation entries
      uint16_t nline;   // Number of line table entries
      uint32_t flags;
    } section_header_t;
  
    typedef struct coff_symbol {
      char name[8];
      uint32_t value;
      uint16_t sect;
      uint16_t type;
      uint8_t storage;
      uint8_t naux;
    } coff_symbol_t;
  
    typedef struct export_directory_entry {
      uint32_t characteristics;
      uint32_t time_date_stamp;
      uint16_t major_version;
      uint16_t minor_version;
      uint32_t name;
      uint32_t base;
      uint32_t number_of_functions;
      uint32_t number_of_names;
      uint32_t address_of_functions;
      uint32_t address_of_names;
      uint32_t address_of_name_ordinals;
    } export_directory_entry;
  
    static bool ParseDOSHeader(lldb_private::DataExtractor &data,
                               dos_header_t &dos_header);
    static bool ParseCOFFHeader(lldb_private::DataExtractor &data,
                                lldb::offset_t *offset_ptr,
                                coff_header_t &coff_header);
    bool ParseCOFFOptionalHeader(lldb::offset_t *offset_ptr);
    bool ParseSectionHeaders(uint32_t offset);
  
    uint32_t ParseDependentModules();
  
    static void DumpDOSHeader(lldb_private::Stream *s,
                              const dos_header_t &header);
    static void DumpCOFFHeader(lldb_private::Stream *s,
                               const coff_header_t &header);
    static void DumpOptCOFFHeader(lldb_private::Stream *s,
                                  const coff_opt_header_t &header);
    void DumpSectionHeaders(lldb_private::Stream *s);
    void DumpSectionHeader(lldb_private::Stream *s, const section_header_t &sh);
    void DumpDependentModules(lldb_private::Stream *s);
  
    llvm::StringRef GetSectionName(const section_header_t &sect);
  
    typedef std::vector<section_header_t> SectionHeaderColl;
    typedef SectionHeaderColl::iterator SectionHeaderCollIter;
    typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter;
  
  private:
    bool CreateBinary();
  
  private:
    dos_header_t m_dos_header;
    coff_header_t m_coff_header;
    coff_opt_header_t m_coff_header_opt;
    SectionHeaderColl m_sect_headers;
    lldb::addr_t m_image_base;
    lldb_private::Address m_entry_point_address;
    llvm::Optional<lldb_private::FileSpecList> m_deps_filespec;
    typedef llvm::object::OwningBinary<llvm::object::Binary> OWNBINType;
    llvm::Optional<OWNBINType> m_owningbin;
    lldb_private::UUID m_uuid;
  };
  
  #endif // liblldb_ObjectFilePECOFF_h_
  