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