summaryrefslogtreecommitdiffhomepage
path: root/src/CompilerKit/AE.h
blob: a85668940cc90840385735daae846f156314eed8 (plain)
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
/*
 * ========================================================
 *
 *      CompilerKit
 *      Copyright (C) 2024-2025 Amlal El Mahrouss, Licensed under the Apache 2.0 license.
 *
 * ========================================================
 */

#ifndef _NECTI_AE_H_
#define _NECTI_AE_H_

#include <CompilerKit/Config.h>
#include <fstream>

#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 file_pointer_;

 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_<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) {
    file_pointer_.read(raw, std::streamsize(sz));
    return reinterpret_cast<TypeClass*>(raw);
  }
};
}  // namespace CompilerKit::Utils

#endif /* ifndef _NECTI_AE_H_ */