1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
/*
* ========================================================
*
* LibCompiler
* Copyright (C) 2024-2025 Amlal EL Mahrouss, all rights reserved.
*
* ========================================================
*/
#pragma once
#include <LibCompiler/Defines.h>
#define kAEMag0 'A'
#define kAEMag1 'E'
#define kAESymbolLen (255)
#define kAEPad (8)
#define kAEMagLen (2)
#define kAENullType (0x00)
// Advanced Executable File Format for MetroLink.
// Reloctable by offset is the default strategy.
// You can also relocate at runtime but that's up to the operating system
// loader.
namespace LibCompiler
{
// @brief Advanced Executable Header
// One thing to keep in mind.
// This object format, is reloctable.
typedef struct AEHeader final
{
CharType fMagic[kAEMagLen];
CharType fArch;
CharType fSubArch;
SizeType fCount;
CharType fSize;
SizeType fStartCode;
SizeType fCodeSize;
CharType 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
{
CharType fName[kAESymbolLen];
SizeType fKind;
SizeType fSize;
SizeType fFlags;
UIntPtr fOffset;
CharType fPad[kAEPad];
} PACKED AERecordHeader, *AERecordHeaderPtr;
enum
{
kKindRelocationByOffset = 0x23f,
kKindRelocationAtRuntime = 0x34f,
};
} // namespace LibCompiler
// provide operator<< for AE
inline std::ofstream& operator<<(std::ofstream& fp, LibCompiler::AEHeader& container)
{
fp.write((char*)&container, sizeof(LibCompiler::AEHeader));
return fp;
}
inline std::ofstream& operator<<(std::ofstream& fp,
LibCompiler::AERecordHeader& container)
{
fp.write((char*)&container, sizeof(LibCompiler::AERecordHeader));
return fp;
}
inline std::ifstream& operator>>(std::ifstream& fp, LibCompiler::AEHeader& container)
{
fp.read((char*)&container, sizeof(LibCompiler::AEHeader));
return fp;
}
inline std::ifstream& operator>>(std::ifstream& fp,
LibCompiler::AERecordHeader& container)
{
fp.read((char*)&container, sizeof(LibCompiler::AERecordHeader));
return fp;
}
namespace LibCompiler::Utils
{
/**
* @brief AE Reader protocol
*
*/
class AEReadableProtocol final
{
public:
std::ifstream FP;
public:
explicit AEReadableProtocol() = default;
~AEReadableProtocol() = default;
LIBCOMPILER_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<AERecordHeader>(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 <typename TypeClass>
TypeClass* _Read(char* raw, std::size_t sz)
{
FP.read(raw, std::streamsize(sz));
return reinterpret_cast<TypeClass*>(raw);
}
};
} // namespace LibCompiler::Utils
|