/* * ======================================================== * * CompilerKit * Copyright (C) 2024-2025 Amlal El Mahrouss, licensed under the Apache 2.0 license. * * ======================================================== */ #ifndef _NECTAR_AE_H_ #define _NECTAR_AE_H_ #include #include #define kAEIdentVersion (0x0122) #define kAEMag0 'A' #define kAEMag1 'E' #define kAEMag2 'F' #define kAESymbolLen (256) #define kAEPad (8) #define kAEMagLen (3) #define kAENullType (0x00) /// @author Amlal El Mahrouss /// @brief // Advanced Executable File Format for ld64. // Reloctable by offset is the default strategy. // You can also relocate at runtime but that's up to the operating system loader. namespace CompilerKit { // @brief Advanced Executable Header // One thing to keep in mind. // This object format, is reloctable. typedef struct AEHeader final { Char fMagic[kAEMagLen] = {}; UInt16 fVersion{kAEIdentVersion}; Char fArch{}; Char fSubArch{}; SizeType fCount{}; Char fSize{}; SizeType fStartCode{}; SizeType fCodeSize{}; Char fPad[kAEPad] = {}; } PACKED AEHeader, *AEHeaderPtr; // @brief Advanced Executable Record. // Could be data, code or bss. // fKind must be filled with PEF fields. typedef struct AERecordHeader final { Char fName[kAESymbolLen]; SizeType fKind; SizeType fSize; SizeType fFlags; UIntPtr fOffset; Char fPad[kAEPad]; } PACKED AERecordHeader, *AERecordHeaderPtr; enum { kKindRelocationByOffset = 0x23f, kKindRelocationAtRuntime = 0x34f, }; } // namespace CompilerKit // provide operator<< for AE inline std::ofstream& operator<<(std::ofstream& fp, CompilerKit::AEHeader& container) { fp.write((char*) &container, sizeof(CompilerKit::AEHeader)); return fp; } inline std::ofstream& operator<<(std::ofstream& fp, CompilerKit::AERecordHeader& container) { fp.write((char*) &container, sizeof(CompilerKit::AERecordHeader)); return fp; } inline std::ifstream& operator>>(std::ifstream& fp, CompilerKit::AEHeader& container) { fp.read((char*) &container, sizeof(CompilerKit::AEHeader)); return fp; } inline std::ifstream& operator>>(std::ifstream& fp, CompilerKit::AERecordHeader& container) { fp.read((char*) &container, sizeof(CompilerKit::AERecordHeader)); return fp; } namespace CompilerKit::Utils { /** * @brief AE Reader protocol * */ class AEReadableProtocol final { public: std::ifstream fFilePtr; public: explicit AEReadableProtocol() = default; ~AEReadableProtocol() = default; NECTI_COPY_DELETE(AEReadableProtocol) /** * @brief Read AE Record headers. * * @param raw the containing buffer * @param sz it's size (1 = one AERecordHeader, 2 two AERecordHeader(s)) * @return AERecordHeaderPtr */ AERecordHeaderPtr Read(char* raw, std::size_t sz) { if (!raw) return nullptr; return this->Read_(raw, sz * sizeof(AERecordHeader)); } private: /** * @brief Implementation of Read for raw classes. * * @tparam TypeClass The class to read. * @param raw the buffer * @param sz the size * @return TypeClass* the returning class. */ template TypeClass* Read_(char* raw, std::size_t sz) { fFilePtr.read(raw, std::streamsize(sz)); return reinterpret_cast(raw); } }; } // namespace CompilerKit::Utils #endif /* ifndef _NECTAR_AE_H_ */