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