1 | //===- GOFF.h - GOFF object file implementation -----------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file declares the GOFFObjectFile class. |
10 | // Record classes and derivatives are also declared and implemented. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_OBJECT_GOFF_H |
15 | #define LLVM_OBJECT_GOFF_H |
16 | |
17 | #include "llvm/ADT/SmallString.h" |
18 | #include "llvm/ADT/SmallVector.h" |
19 | #include "llvm/BinaryFormat/GOFF.h" |
20 | #include "llvm/Support/Debug.h" |
21 | #include "llvm/Support/Endian.h" |
22 | #include "llvm/Support/raw_ostream.h" |
23 | |
24 | namespace llvm { |
25 | namespace object { |
26 | |
27 | /// \brief Represents a GOFF physical record. |
28 | /// |
29 | /// Specifies protected member functions to manipulate the record. These should |
30 | /// be called from deriving classes to change values as that record specifies. |
31 | class Record { |
32 | public: |
33 | static Error getContinuousData(const uint8_t *Record, uint16_t DataLength, |
34 | int DataIndex, SmallString<256> &CompleteData); |
35 | |
36 | static bool isContinued(const uint8_t *Record) { |
37 | uint8_t IsContinued; |
38 | getBits(Bytes: Record, ByteIndex: 1, BitIndex: 7, Length: 1, Value&: IsContinued); |
39 | return IsContinued; |
40 | } |
41 | |
42 | static bool isContinuation(const uint8_t *Record) { |
43 | uint8_t IsContinuation; |
44 | getBits(Bytes: Record, ByteIndex: 1, BitIndex: 6, Length: 1, Value&: IsContinuation); |
45 | return IsContinuation; |
46 | } |
47 | |
48 | protected: |
49 | /// \brief Get bit field of specified byte. |
50 | /// |
51 | /// Used to pack bit fields into one byte. Fields are packed left to right. |
52 | /// Bit index zero is the most significant bit of the byte. |
53 | /// |
54 | /// \param ByteIndex index of byte the field is in. |
55 | /// \param BitIndex index of first bit of field. |
56 | /// \param Length length of bit field. |
57 | /// \param Value value of bit field. |
58 | static void getBits(const uint8_t *Bytes, uint8_t ByteIndex, uint8_t BitIndex, |
59 | uint8_t Length, uint8_t &Value) { |
60 | assert(ByteIndex < GOFF::RecordLength && "Byte index out of bounds!" ); |
61 | assert(BitIndex < 8 && "Bit index out of bounds!" ); |
62 | assert(Length + BitIndex <= 8 && "Bit length too long!" ); |
63 | |
64 | get<uint8_t>(Bytes, ByteIndex, Value); |
65 | Value = (Value >> (8 - BitIndex - Length)) & ((1 << Length) - 1); |
66 | } |
67 | |
68 | template <class T> |
69 | static void get(const uint8_t *Bytes, uint8_t ByteIndex, T &Value) { |
70 | assert(ByteIndex + sizeof(T) <= GOFF::RecordLength && |
71 | "Byte index out of bounds!" ); |
72 | Value = support::endian::read<T, llvm::endianness::big>(&Bytes[ByteIndex]); |
73 | } |
74 | }; |
75 | |
76 | class TXTRecord : public Record { |
77 | public: |
78 | /// \brief Maximum length of data; any more must go in continuation. |
79 | static const uint8_t TXTMaxDataLength = 56; |
80 | |
81 | static Error getData(const uint8_t *Record, SmallString<256> &CompleteData); |
82 | |
83 | static void getElementEsdId(const uint8_t *Record, uint32_t &EsdId) { |
84 | get<uint32_t>(Bytes: Record, ByteIndex: 4, Value&: EsdId); |
85 | } |
86 | |
87 | static void getOffset(const uint8_t *Record, uint32_t &Offset) { |
88 | get<uint32_t>(Bytes: Record, ByteIndex: 12, Value&: Offset); |
89 | } |
90 | |
91 | static void getDataLength(const uint8_t *Record, uint16_t &Length) { |
92 | get<uint16_t>(Bytes: Record, ByteIndex: 22, Value&: Length); |
93 | } |
94 | }; |
95 | |
96 | class HDRRecord : public Record { |
97 | public: |
98 | static Error getData(const uint8_t *Record, SmallString<256> &CompleteData); |
99 | |
100 | static uint16_t getPropertyModuleLength(const uint8_t *Record) { |
101 | uint16_t Length; |
102 | get<uint16_t>(Bytes: Record, ByteIndex: 52, Value&: Length); |
103 | return Length; |
104 | } |
105 | }; |
106 | |
107 | class ESDRecord : public Record { |
108 | public: |
109 | /// \brief Number of bytes for name; any more must go in continuation. |
110 | /// This is the number of bytes that can fit into the data field of an ESD |
111 | /// record. |
112 | static const uint8_t ESDMaxUncontinuedNameLength = 8; |
113 | |
114 | /// \brief Maximum name length for ESD records and continuations. |
115 | /// This is the number of bytes that can fit into the data field of an ESD |
116 | /// record AND following continuations. This is limited fundamentally by the |
117 | /// 16 bit SIGNED length field. |
118 | static const uint16_t MaxNameLength = 32 * 1024; |
119 | |
120 | public: |
121 | static Error getData(const uint8_t *Record, SmallString<256> &CompleteData); |
122 | |
123 | // ESD Get routines. |
124 | static void getSymbolType(const uint8_t *Record, |
125 | GOFF::ESDSymbolType &SymbolType) { |
126 | uint8_t Value; |
127 | get<uint8_t>(Bytes: Record, ByteIndex: 3, Value); |
128 | SymbolType = (GOFF::ESDSymbolType)Value; |
129 | } |
130 | |
131 | static void getEsdId(const uint8_t *Record, uint32_t &EsdId) { |
132 | get<uint32_t>(Bytes: Record, ByteIndex: 4, Value&: EsdId); |
133 | } |
134 | |
135 | static void getParentEsdId(const uint8_t *Record, uint32_t &EsdId) { |
136 | get<uint32_t>(Bytes: Record, ByteIndex: 8, Value&: EsdId); |
137 | } |
138 | |
139 | static void getOffset(const uint8_t *Record, uint32_t &Offset) { |
140 | get<uint32_t>(Bytes: Record, ByteIndex: 16, Value&: Offset); |
141 | } |
142 | |
143 | static void getLength(const uint8_t *Record, uint32_t &Length) { |
144 | get<uint32_t>(Bytes: Record, ByteIndex: 24, Value&: Length); |
145 | } |
146 | |
147 | static void getNameSpaceId(const uint8_t *Record, GOFF::ESDNameSpaceId &Id) { |
148 | uint8_t Value; |
149 | get<uint8_t>(Bytes: Record, ByteIndex: 40, Value); |
150 | Id = (GOFF::ESDNameSpaceId)Value; |
151 | } |
152 | |
153 | static void getFillBytePresent(const uint8_t *Record, bool &Present) { |
154 | uint8_t Value; |
155 | getBits(Bytes: Record, ByteIndex: 41, BitIndex: 0, Length: 1, Value); |
156 | Present = (bool)Value; |
157 | } |
158 | |
159 | static void getNameMangled(const uint8_t *Record, bool &Mangled) { |
160 | uint8_t Value; |
161 | getBits(Bytes: Record, ByteIndex: 41, BitIndex: 1, Length: 1, Value); |
162 | Mangled = (bool)Value; |
163 | } |
164 | |
165 | static void getRenamable(const uint8_t *Record, bool &Renamable) { |
166 | uint8_t Value; |
167 | getBits(Bytes: Record, ByteIndex: 41, BitIndex: 2, Length: 1, Value); |
168 | Renamable = (bool)Value; |
169 | } |
170 | |
171 | static void getRemovable(const uint8_t *Record, bool &Removable) { |
172 | uint8_t Value; |
173 | getBits(Bytes: Record, ByteIndex: 41, BitIndex: 3, Length: 1, Value); |
174 | Removable = (bool)Value; |
175 | } |
176 | |
177 | static void getFillByteValue(const uint8_t *Record, uint8_t &Fill) { |
178 | get<uint8_t>(Bytes: Record, ByteIndex: 42, Value&: Fill); |
179 | } |
180 | |
181 | static void getAdaEsdId(const uint8_t *Record, uint32_t &EsdId) { |
182 | get<uint32_t>(Bytes: Record, ByteIndex: 44, Value&: EsdId); |
183 | } |
184 | |
185 | static void getSortPriority(const uint8_t *Record, uint32_t &Priority) { |
186 | get<uint32_t>(Bytes: Record, ByteIndex: 48, Value&: Priority); |
187 | } |
188 | |
189 | static void getAmode(const uint8_t *Record, GOFF::ESDAmode &Amode) { |
190 | uint8_t Value; |
191 | get<uint8_t>(Bytes: Record, ByteIndex: 60, Value); |
192 | Amode = (GOFF::ESDAmode)Value; |
193 | } |
194 | |
195 | static void getRmode(const uint8_t *Record, GOFF::ESDRmode &Rmode) { |
196 | uint8_t Value; |
197 | get<uint8_t>(Bytes: Record, ByteIndex: 61, Value); |
198 | Rmode = (GOFF::ESDRmode)Value; |
199 | } |
200 | |
201 | static void getTextStyle(const uint8_t *Record, GOFF::ESDTextStyle &Style) { |
202 | uint8_t Value; |
203 | getBits(Bytes: Record, ByteIndex: 62, BitIndex: 0, Length: 4, Value); |
204 | Style = (GOFF::ESDTextStyle)Value; |
205 | } |
206 | |
207 | static void getBindingAlgorithm(const uint8_t *Record, |
208 | GOFF::ESDBindingAlgorithm &Algorithm) { |
209 | uint8_t Value; |
210 | getBits(Bytes: Record, ByteIndex: 62, BitIndex: 4, Length: 4, Value); |
211 | Algorithm = (GOFF::ESDBindingAlgorithm)Value; |
212 | } |
213 | |
214 | static void getTaskingBehavior(const uint8_t *Record, |
215 | GOFF::ESDTaskingBehavior &TaskingBehavior) { |
216 | uint8_t Value; |
217 | getBits(Bytes: Record, ByteIndex: 63, BitIndex: 0, Length: 3, Value); |
218 | TaskingBehavior = (GOFF::ESDTaskingBehavior)Value; |
219 | } |
220 | |
221 | static void getReadOnly(const uint8_t *Record, bool &ReadOnly) { |
222 | uint8_t Value; |
223 | getBits(Bytes: Record, ByteIndex: 63, BitIndex: 4, Length: 1, Value); |
224 | ReadOnly = (bool)Value; |
225 | } |
226 | |
227 | static void getExecutable(const uint8_t *Record, |
228 | GOFF::ESDExecutable &Executable) { |
229 | uint8_t Value; |
230 | getBits(Bytes: Record, ByteIndex: 63, BitIndex: 5, Length: 3, Value); |
231 | Executable = (GOFF::ESDExecutable)Value; |
232 | } |
233 | |
234 | static void getDuplicateSeverity(const uint8_t *Record, |
235 | GOFF::ESDDuplicateSymbolSeverity &DSS) { |
236 | uint8_t Value; |
237 | getBits(Bytes: Record, ByteIndex: 64, BitIndex: 2, Length: 2, Value); |
238 | DSS = (GOFF::ESDDuplicateSymbolSeverity)Value; |
239 | } |
240 | |
241 | static void getBindingStrength(const uint8_t *Record, |
242 | GOFF::ESDBindingStrength &Strength) { |
243 | uint8_t Value; |
244 | getBits(Bytes: Record, ByteIndex: 64, BitIndex: 4, Length: 4, Value); |
245 | Strength = (GOFF::ESDBindingStrength)Value; |
246 | } |
247 | |
248 | static void getLoadingBehavior(const uint8_t *Record, |
249 | GOFF::ESDLoadingBehavior &Behavior) { |
250 | uint8_t Value; |
251 | getBits(Bytes: Record, ByteIndex: 65, BitIndex: 0, Length: 2, Value); |
252 | Behavior = (GOFF::ESDLoadingBehavior)Value; |
253 | } |
254 | |
255 | static void getIndirectReference(const uint8_t *Record, bool &Indirect) { |
256 | uint8_t Value; |
257 | getBits(Bytes: Record, ByteIndex: 65, BitIndex: 3, Length: 1, Value); |
258 | Indirect = (bool)Value; |
259 | } |
260 | |
261 | static void getBindingScope(const uint8_t *Record, |
262 | GOFF::ESDBindingScope &Scope) { |
263 | uint8_t Value; |
264 | getBits(Bytes: Record, ByteIndex: 65, BitIndex: 4, Length: 4, Value); |
265 | Scope = (GOFF::ESDBindingScope)Value; |
266 | } |
267 | |
268 | static void getLinkageType(const uint8_t *Record, |
269 | GOFF::ESDLinkageType &Type) { |
270 | uint8_t Value; |
271 | getBits(Bytes: Record, ByteIndex: 66, BitIndex: 2, Length: 1, Value); |
272 | Type = (GOFF::ESDLinkageType)Value; |
273 | } |
274 | |
275 | static void getAlignment(const uint8_t *Record, |
276 | GOFF::ESDAlignment &Alignment) { |
277 | uint8_t Value; |
278 | getBits(Bytes: Record, ByteIndex: 66, BitIndex: 3, Length: 5, Value); |
279 | Alignment = (GOFF::ESDAlignment)Value; |
280 | } |
281 | |
282 | static uint16_t getNameLength(const uint8_t *Record) { |
283 | uint16_t Length; |
284 | get<uint16_t>(Bytes: Record, ByteIndex: 70, Value&: Length); |
285 | return Length; |
286 | } |
287 | }; |
288 | |
289 | class ENDRecord : public Record { |
290 | public: |
291 | static Error getData(const uint8_t *Record, SmallString<256> &CompleteData); |
292 | |
293 | static uint16_t getNameLength(const uint8_t *Record) { |
294 | uint16_t Length; |
295 | get<uint16_t>(Bytes: Record, ByteIndex: 24, Value&: Length); |
296 | return Length; |
297 | } |
298 | }; |
299 | |
300 | } // end namespace object |
301 | } // end namespace llvm |
302 | |
303 | #endif |
304 | |