#pragma once #include #include #include #include #include #include #include #include "../Emulators/MemoryContext.hh" namespace ResourceDASM { using namespace phosg; // The file begins with an ELFIdentifier immediately followed by an ELFHeader. // The ELFHeader may have different endianness or widths for some fields, hence // the split structs here. struct ELFIdentifier { be_uint32_t magic; // '\x7FELF' (0x7F454C46) uint8_t width; // 1 = 32-bit, 2 = 64-bit uint8_t endianness; // 1 = little-endian, 2 = big-endian uint8_t format_version; // 1 uint8_t os_abi; uint8_t version_args[8]; } __attribute__((packed)); template struct ELFHeader { U16T type; U16T architecture; U32T format_version; // 1 LongT entrypoint_addr; LongT program_header_offset; LongT section_header_offset; U32T flags; U16T header_size; // Size of this struct + the preceding ELFIdentifier U16T program_header_entry_size; U16T program_header_entry_count; U16T section_header_entry_size; U16T section_header_entry_count; U16T names_section_index; } __attribute__((packed)); struct ELFHeader32BE : ELFHeader {}; struct ELFHeader32LE : ELFHeader {}; struct ELFHeader64BE : ELFHeader {}; struct ELFHeader64LE : ELFHeader {}; template struct ELFProgramHeaderEntry32 { U32T type; U32T offset; U32T virtual_addr; U32T physical_addr; U32T physical_size; U32T loaded_size; U32T flags; U32T alignment; } __attribute__((packed)); struct ELFProgramHeaderEntry32BE : ELFProgramHeaderEntry32 {}; struct ELFProgramHeaderEntry32LE : ELFProgramHeaderEntry32 {}; template struct ELFProgramHeaderEntry64 { U32T type; U32T flags; U64T offset; U64T virtual_addr; U64T physical_addr; U64T physical_size; U64T loaded_size; U64T alignment; } __attribute__((packed)); struct ELFProgramHeaderEntry64BE : ELFProgramHeaderEntry64 {}; struct ELFProgramHeaderEntry64LE : ELFProgramHeaderEntry64 {}; template struct ELFSectionHeaderEntry { U32T name_offset; // Offset into .shstrtab section U32T type; LongT flags; LongT virtual_addr; LongT offset; LongT physical_size; U32T linked_section_num; U32T info; LongT alignment; LongT entry_size; // Zero if section doesn't contain fixed-size entries } __attribute__((packed)); class ELFFile { public: explicit ELFFile(const char* filename); ELFFile(const char* filename, const std::string& data); ELFFile(const char* filename, const void* data, size_t size); ~ELFFile() = default; void print( FILE* stream, const std::multimap* labels = nullptr, bool print_hex_view_for_code = false, bool all_sections_as_code = false) const; private: void parse(const void* data, size_t size); template void parse_t(StringReader& r); const std::string filename; ELFIdentifier identifier; uint16_t type; uint16_t architecture; uint64_t entrypoint_addr; uint32_t flags; struct Section { std::string name; uint32_t type; uint64_t flags; uint64_t virtual_addr; uint64_t offset; uint64_t physical_size; uint32_t linked_section_num; uint32_t info; uint64_t alignment; uint64_t entry_size; std::string data; }; std::vector
sections; // TODO: parse program headers too }; } // namespace ResourceDASM