summaryrefslogtreecommitdiffhomepage
path: root/dev/LibCompiler/AE.h
blob: 8c05c3a5f6a2d61cce1662f0d56da8ce1090c360 (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
/*
 * ========================================================
 *
 *      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 ld64.
// 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 {
  Char fMagic[kAEMagLen];
  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 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