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