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 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 getElementEsdId(const uint8_t * Record,uint32_t & EsdId)83 static void getElementEsdId(const uint8_t *Record, uint32_t &EsdId) { 84 get<uint32_t>(Record, 4, EsdId); 85 } 86 getOffset(const uint8_t * Record,uint32_t & Offset)87 static void getOffset(const uint8_t *Record, uint32_t &Offset) { 88 get<uint32_t>(Record, 12, Offset); 89 } 90 getDataLength(const uint8_t * Record,uint16_t & Length)91 static void getDataLength(const uint8_t *Record, uint16_t &Length) { 92 get<uint16_t>(Record, 22, Length); 93 } 94 }; 95 96 class HDRRecord : public Record { 97 public: 98 static Error getData(const uint8_t *Record, SmallString<256> &CompleteData); 99 getPropertyModuleLength(const uint8_t * Record)100 static uint16_t getPropertyModuleLength(const uint8_t *Record) { 101 uint16_t Length; 102 get<uint16_t>(Record, 52, 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. getSymbolType(const uint8_t * Record,GOFF::ESDSymbolType & SymbolType)124 static void getSymbolType(const uint8_t *Record, 125 GOFF::ESDSymbolType &SymbolType) { 126 uint8_t Value; 127 get<uint8_t>(Record, 3, Value); 128 SymbolType = (GOFF::ESDSymbolType)Value; 129 } 130 getEsdId(const uint8_t * Record,uint32_t & EsdId)131 static void getEsdId(const uint8_t *Record, uint32_t &EsdId) { 132 get<uint32_t>(Record, 4, EsdId); 133 } 134 getParentEsdId(const uint8_t * Record,uint32_t & EsdId)135 static void getParentEsdId(const uint8_t *Record, uint32_t &EsdId) { 136 get<uint32_t>(Record, 8, EsdId); 137 } 138 getOffset(const uint8_t * Record,uint32_t & Offset)139 static void getOffset(const uint8_t *Record, uint32_t &Offset) { 140 get<uint32_t>(Record, 16, Offset); 141 } 142 getLength(const uint8_t * Record,uint32_t & Length)143 static void getLength(const uint8_t *Record, uint32_t &Length) { 144 get<uint32_t>(Record, 24, Length); 145 } 146 getNameSpaceId(const uint8_t * Record,GOFF::ESDNameSpaceId & Id)147 static void getNameSpaceId(const uint8_t *Record, GOFF::ESDNameSpaceId &Id) { 148 uint8_t Value; 149 get<uint8_t>(Record, 40, Value); 150 Id = (GOFF::ESDNameSpaceId)Value; 151 } 152 getFillBytePresent(const uint8_t * Record,bool & Present)153 static void getFillBytePresent(const uint8_t *Record, bool &Present) { 154 uint8_t Value; 155 getBits(Record, 41, 0, 1, Value); 156 Present = (bool)Value; 157 } 158 getNameMangled(const uint8_t * Record,bool & Mangled)159 static void getNameMangled(const uint8_t *Record, bool &Mangled) { 160 uint8_t Value; 161 getBits(Record, 41, 1, 1, Value); 162 Mangled = (bool)Value; 163 } 164 getRenamable(const uint8_t * Record,bool & Renamable)165 static void getRenamable(const uint8_t *Record, bool &Renamable) { 166 uint8_t Value; 167 getBits(Record, 41, 2, 1, Value); 168 Renamable = (bool)Value; 169 } 170 getRemovable(const uint8_t * Record,bool & Removable)171 static void getRemovable(const uint8_t *Record, bool &Removable) { 172 uint8_t Value; 173 getBits(Record, 41, 3, 1, Value); 174 Removable = (bool)Value; 175 } 176 getFillByteValue(const uint8_t * Record,uint8_t & Fill)177 static void getFillByteValue(const uint8_t *Record, uint8_t &Fill) { 178 get<uint8_t>(Record, 42, Fill); 179 } 180 getAdaEsdId(const uint8_t * Record,uint32_t & EsdId)181 static void getAdaEsdId(const uint8_t *Record, uint32_t &EsdId) { 182 get<uint32_t>(Record, 44, EsdId); 183 } 184 getSortPriority(const uint8_t * Record,uint32_t & Priority)185 static void getSortPriority(const uint8_t *Record, uint32_t &Priority) { 186 get<uint32_t>(Record, 48, Priority); 187 } 188 getAmode(const uint8_t * Record,GOFF::ESDAmode & Amode)189 static void getAmode(const uint8_t *Record, GOFF::ESDAmode &Amode) { 190 uint8_t Value; 191 get<uint8_t>(Record, 60, Value); 192 Amode = (GOFF::ESDAmode)Value; 193 } 194 getRmode(const uint8_t * Record,GOFF::ESDRmode & Rmode)195 static void getRmode(const uint8_t *Record, GOFF::ESDRmode &Rmode) { 196 uint8_t Value; 197 get<uint8_t>(Record, 61, Value); 198 Rmode = (GOFF::ESDRmode)Value; 199 } 200 getTextStyle(const uint8_t * Record,GOFF::ESDTextStyle & Style)201 static void getTextStyle(const uint8_t *Record, GOFF::ESDTextStyle &Style) { 202 uint8_t Value; 203 getBits(Record, 62, 0, 4, Value); 204 Style = (GOFF::ESDTextStyle)Value; 205 } 206 getBindingAlgorithm(const uint8_t * Record,GOFF::ESDBindingAlgorithm & Algorithm)207 static void getBindingAlgorithm(const uint8_t *Record, 208 GOFF::ESDBindingAlgorithm &Algorithm) { 209 uint8_t Value; 210 getBits(Record, 62, 4, 4, Value); 211 Algorithm = (GOFF::ESDBindingAlgorithm)Value; 212 } 213 getTaskingBehavior(const uint8_t * Record,GOFF::ESDTaskingBehavior & TaskingBehavior)214 static void getTaskingBehavior(const uint8_t *Record, 215 GOFF::ESDTaskingBehavior &TaskingBehavior) { 216 uint8_t Value; 217 getBits(Record, 63, 0, 3, Value); 218 TaskingBehavior = (GOFF::ESDTaskingBehavior)Value; 219 } 220 getReadOnly(const uint8_t * Record,bool & ReadOnly)221 static void getReadOnly(const uint8_t *Record, bool &ReadOnly) { 222 uint8_t Value; 223 getBits(Record, 63, 4, 1, Value); 224 ReadOnly = (bool)Value; 225 } 226 getExecutable(const uint8_t * Record,GOFF::ESDExecutable & Executable)227 static void getExecutable(const uint8_t *Record, 228 GOFF::ESDExecutable &Executable) { 229 uint8_t Value; 230 getBits(Record, 63, 5, 3, Value); 231 Executable = (GOFF::ESDExecutable)Value; 232 } 233 getDuplicateSeverity(const uint8_t * Record,GOFF::ESDDuplicateSymbolSeverity & DSS)234 static void getDuplicateSeverity(const uint8_t *Record, 235 GOFF::ESDDuplicateSymbolSeverity &DSS) { 236 uint8_t Value; 237 getBits(Record, 64, 2, 2, Value); 238 DSS = (GOFF::ESDDuplicateSymbolSeverity)Value; 239 } 240 getBindingStrength(const uint8_t * Record,GOFF::ESDBindingStrength & Strength)241 static void getBindingStrength(const uint8_t *Record, 242 GOFF::ESDBindingStrength &Strength) { 243 uint8_t Value; 244 getBits(Record, 64, 4, 4, Value); 245 Strength = (GOFF::ESDBindingStrength)Value; 246 } 247 getLoadingBehavior(const uint8_t * Record,GOFF::ESDLoadingBehavior & Behavior)248 static void getLoadingBehavior(const uint8_t *Record, 249 GOFF::ESDLoadingBehavior &Behavior) { 250 uint8_t Value; 251 getBits(Record, 65, 0, 2, Value); 252 Behavior = (GOFF::ESDLoadingBehavior)Value; 253 } 254 getIndirectReference(const uint8_t * Record,bool & Indirect)255 static void getIndirectReference(const uint8_t *Record, bool &Indirect) { 256 uint8_t Value; 257 getBits(Record, 65, 3, 1, Value); 258 Indirect = (bool)Value; 259 } 260 getBindingScope(const uint8_t * Record,GOFF::ESDBindingScope & Scope)261 static void getBindingScope(const uint8_t *Record, 262 GOFF::ESDBindingScope &Scope) { 263 uint8_t Value; 264 getBits(Record, 65, 4, 4, Value); 265 Scope = (GOFF::ESDBindingScope)Value; 266 } 267 getLinkageType(const uint8_t * Record,GOFF::ESDLinkageType & Type)268 static void getLinkageType(const uint8_t *Record, 269 GOFF::ESDLinkageType &Type) { 270 uint8_t Value; 271 getBits(Record, 66, 2, 1, Value); 272 Type = (GOFF::ESDLinkageType)Value; 273 } 274 getAlignment(const uint8_t * Record,GOFF::ESDAlignment & Alignment)275 static void getAlignment(const uint8_t *Record, 276 GOFF::ESDAlignment &Alignment) { 277 uint8_t Value; 278 getBits(Record, 66, 3, 5, Value); 279 Alignment = (GOFF::ESDAlignment)Value; 280 } 281 getNameLength(const uint8_t * Record)282 static uint16_t getNameLength(const uint8_t *Record) { 283 uint16_t Length; 284 get<uint16_t>(Record, 70, 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 getNameLength(const uint8_t * Record)293 static uint16_t getNameLength(const uint8_t *Record) { 294 uint16_t Length; 295 get<uint16_t>(Record, 24, Length); 296 return Length; 297 } 298 }; 299 300 } // end namespace object 301 } // end namespace llvm 302 303 #endif 304