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(Record, 1, 7, 1, IsContinued);
39     return IsContinued;
40   }
41 
42   static bool isContinuation(const uint8_t *Record) {
43     uint8_t IsContinuation;
44     getBits(Record, 1, 6, 1, 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, support::big, support::unaligned>(
73         &Bytes[ByteIndex]);
74   }
75 };
76 
77 class HDRRecord : public Record {
78 public:
79   static Error getData(const uint8_t *Record, SmallString<256> &CompleteData);
80 
81   static uint16_t getPropertyModuleLength(const uint8_t *Record) {
82     uint16_t Length;
83     get<uint16_t>(Record, 52, Length);
84     return Length;
85   }
86 };
87 
88 class ESDRecord : public Record {
89 public:
90   /// \brief Number of bytes for name; any more must go in continuation.
91   /// This is the number of bytes that can fit into the data field of an ESD
92   /// record.
93   static const uint8_t ESDMaxUncontinuedNameLength = 8;
94 
95   /// \brief Maximum name length for ESD records and continuations.
96   /// This is the number of bytes that can fit into the data field of an ESD
97   /// record AND following continuations. This is limited fundamentally by the
98   /// 16 bit SIGNED length field.
99   static const uint16_t MaxNameLength = 32 * 1024;
100 
101 public:
102   static Error getData(const uint8_t *Record, SmallString<256> &CompleteData);
103 
104   // ESD Get routines.
105   static void getSymbolType(const uint8_t *Record,
106                             GOFF::ESDSymbolType &SymbolType) {
107     uint8_t Value;
108     get<uint8_t>(Record, 3, Value);
109     SymbolType = (GOFF::ESDSymbolType)Value;
110   }
111 
112   static void getEsdId(const uint8_t *Record, uint32_t &EsdId) {
113     get<uint32_t>(Record, 4, EsdId);
114   }
115 
116   static void getParentEsdId(const uint8_t *Record, uint32_t &EsdId) {
117     get<uint32_t>(Record, 8, EsdId);
118   }
119 
120   static void getOffset(const uint8_t *Record, uint32_t &Offset) {
121     get<uint32_t>(Record, 16, Offset);
122   }
123 
124   static void getLength(const uint8_t *Record, uint32_t &Length) {
125     get<uint32_t>(Record, 24, Length);
126   }
127 
128   static void getNameSpaceId(const uint8_t *Record, GOFF::ESDNameSpaceId &Id) {
129     uint8_t Value;
130     get<uint8_t>(Record, 40, Value);
131     Id = (GOFF::ESDNameSpaceId)Value;
132   }
133 
134   static void getFillBytePresent(const uint8_t *Record, bool &Present) {
135     uint8_t Value;
136     getBits(Record, 41, 0, 1, Value);
137     Present = (bool)Value;
138   }
139 
140   static void getNameMangled(const uint8_t *Record, bool &Mangled) {
141     uint8_t Value;
142     getBits(Record, 41, 1, 1, Value);
143     Mangled = (bool)Value;
144   }
145 
146   static void getRenamable(const uint8_t *Record, bool &Renamable) {
147     uint8_t Value;
148     getBits(Record, 41, 2, 1, Value);
149     Renamable = (bool)Value;
150   }
151 
152   static void getRemovable(const uint8_t *Record, bool &Removable) {
153     uint8_t Value;
154     getBits(Record, 41, 3, 1, Value);
155     Removable = (bool)Value;
156   }
157 
158   static void getFillByteValue(const uint8_t *Record, uint8_t &Fill) {
159     get<uint8_t>(Record, 42, Fill);
160   }
161 
162   static void getAdaEsdId(const uint8_t *Record, uint32_t &EsdId) {
163     get<uint32_t>(Record, 44, EsdId);
164   }
165 
166   static void getSortPriority(const uint8_t *Record, uint32_t &Priority) {
167     get<uint32_t>(Record, 48, Priority);
168   }
169 
170   static void getAmode(const uint8_t *Record, GOFF::ESDAmode &Amode) {
171     uint8_t Value;
172     get<uint8_t>(Record, 60, Value);
173     Amode = (GOFF::ESDAmode)Value;
174   }
175 
176   static void getRmode(const uint8_t *Record, GOFF::ESDRmode &Rmode) {
177     uint8_t Value;
178     get<uint8_t>(Record, 61, Value);
179     Rmode = (GOFF::ESDRmode)Value;
180   }
181 
182   static void getTextStyle(const uint8_t *Record, GOFF::ESDTextStyle &Style) {
183     uint8_t Value;
184     getBits(Record, 62, 0, 4, Value);
185     Style = (GOFF::ESDTextStyle)Value;
186   }
187 
188   static void getBindingAlgorithm(const uint8_t *Record,
189                                   GOFF::ESDBindingAlgorithm &Algorithm) {
190     uint8_t Value;
191     getBits(Record, 62, 4, 4, Value);
192     Algorithm = (GOFF::ESDBindingAlgorithm)Value;
193   }
194 
195   static void getTaskingBehavior(const uint8_t *Record,
196                                  GOFF::ESDTaskingBehavior &TaskingBehavior) {
197     uint8_t Value;
198     getBits(Record, 63, 0, 3, Value);
199     TaskingBehavior = (GOFF::ESDTaskingBehavior)Value;
200   }
201 
202   static void getReadOnly(const uint8_t *Record, bool &ReadOnly) {
203     uint8_t Value;
204     getBits(Record, 63, 4, 1, Value);
205     ReadOnly = (bool)Value;
206   }
207 
208   static void getExecutable(const uint8_t *Record,
209                             GOFF::ESDExecutable &Executable) {
210     uint8_t Value;
211     getBits(Record, 63, 5, 3, Value);
212     Executable = (GOFF::ESDExecutable)Value;
213   }
214 
215   static void getDuplicateSeverity(const uint8_t *Record,
216                                    GOFF::ESDDuplicateSymbolSeverity &DSS) {
217     uint8_t Value;
218     getBits(Record, 64, 2, 2, Value);
219     DSS = (GOFF::ESDDuplicateSymbolSeverity)Value;
220   }
221 
222   static void getBindingStrength(const uint8_t *Record,
223                                  GOFF::ESDBindingStrength &Strength) {
224     uint8_t Value;
225     getBits(Record, 64, 4, 4, Value);
226     Strength = (GOFF::ESDBindingStrength)Value;
227   }
228 
229   static void getLoadingBehavior(const uint8_t *Record,
230                                  GOFF::ESDLoadingBehavior &Behavior) {
231     uint8_t Value;
232     getBits(Record, 65, 0, 2, Value);
233     Behavior = (GOFF::ESDLoadingBehavior)Value;
234   }
235 
236   static void getIndirectReference(const uint8_t *Record, bool &Indirect) {
237     uint8_t Value;
238     getBits(Record, 65, 3, 1, Value);
239     Indirect = (bool)Value;
240   }
241 
242   static void getBindingScope(const uint8_t *Record,
243                               GOFF::ESDBindingScope &Scope) {
244     uint8_t Value;
245     getBits(Record, 65, 4, 4, Value);
246     Scope = (GOFF::ESDBindingScope)Value;
247   }
248 
249   static void getLinkageType(const uint8_t *Record,
250                              GOFF::ESDLinkageType &Type) {
251     uint8_t Value;
252     getBits(Record, 66, 2, 1, Value);
253     Type = (GOFF::ESDLinkageType)Value;
254   }
255 
256   static void getAlignment(const uint8_t *Record,
257                            GOFF::ESDAlignment &Alignment) {
258     uint8_t Value;
259     getBits(Record, 66, 3, 5, Value);
260     Alignment = (GOFF::ESDAlignment)Value;
261   }
262 
263   static uint16_t getNameLength(const uint8_t *Record) {
264     uint16_t Length;
265     get<uint16_t>(Record, 70, Length);
266     return Length;
267   }
268 };
269 
270 class ENDRecord : public Record {
271 public:
272   static Error getData(const uint8_t *Record, SmallString<256> &CompleteData);
273 
274   static uint16_t getNameLength(const uint8_t *Record) {
275     uint16_t Length;
276     get<uint16_t>(Record, 24, Length);
277     return Length;
278   }
279 };
280 
281 } // end namespace object
282 } // end namespace llvm
283 
284 #endif
285