| File: | build/source/llvm/include/llvm/Object/XCOFFObjectFile.h |
| Warning: | line 790, column 45 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | //===--- XCOFFObjectFile.cpp - XCOFF object file implementation -----------===// | |||
| 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 defines the XCOFFObjectFile class. | |||
| 10 | // | |||
| 11 | //===----------------------------------------------------------------------===// | |||
| 12 | ||||
| 13 | #include "llvm/Object/XCOFFObjectFile.h" | |||
| 14 | #include "llvm/ADT/StringSwitch.h" | |||
| 15 | #include "llvm/MC/SubtargetFeature.h" | |||
| 16 | #include "llvm/Support/DataExtractor.h" | |||
| 17 | #include <cstddef> | |||
| 18 | #include <cstring> | |||
| 19 | ||||
| 20 | namespace llvm { | |||
| 21 | ||||
| 22 | using namespace XCOFF; | |||
| 23 | ||||
| 24 | namespace object { | |||
| 25 | ||||
| 26 | static const uint8_t FunctionSym = 0x20; | |||
| 27 | static const uint16_t NoRelMask = 0x0001; | |||
| 28 | static const size_t SymbolAuxTypeOffset = 17; | |||
| 29 | ||||
| 30 | // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer | |||
| 31 | // 'M'. Returns a pointer to the underlying object on success. | |||
| 32 | template <typename T> | |||
| 33 | static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr, | |||
| 34 | const uint64_t Size = sizeof(T)) { | |||
| 35 | uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr); | |||
| 36 | if (Error E = Binary::checkOffset(M, Addr, Size)) | |||
| 37 | return std::move(E); | |||
| 38 | return reinterpret_cast<const T *>(Addr); | |||
| 39 | } | |||
| 40 | ||||
| 41 | static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) { | |||
| 42 | return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) + | |||
| 43 | Offset); | |||
| 44 | } | |||
| 45 | ||||
| 46 | template <typename T> static const T *viewAs(uintptr_t in) { | |||
| 47 | return reinterpret_cast<const T *>(in); | |||
| 48 | } | |||
| 49 | ||||
| 50 | static StringRef generateXCOFFFixedNameStringRef(const char *Name) { | |||
| 51 | auto NulCharPtr = | |||
| 52 | static_cast<const char *>(memchr(Name, '\0', XCOFF::NameSize)); | |||
| 53 | return NulCharPtr ? StringRef(Name, NulCharPtr - Name) | |||
| 54 | : StringRef(Name, XCOFF::NameSize); | |||
| 55 | } | |||
| 56 | ||||
| 57 | template <typename T> StringRef XCOFFSectionHeader<T>::getName() const { | |||
| 58 | const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this); | |||
| 59 | return generateXCOFFFixedNameStringRef(DerivedXCOFFSectionHeader.Name); | |||
| 60 | } | |||
| 61 | ||||
| 62 | template <typename T> uint16_t XCOFFSectionHeader<T>::getSectionType() const { | |||
| 63 | const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this); | |||
| 64 | return DerivedXCOFFSectionHeader.Flags & SectionFlagsTypeMask; | |||
| 65 | } | |||
| 66 | ||||
| 67 | template <typename T> | |||
| 68 | bool XCOFFSectionHeader<T>::isReservedSectionType() const { | |||
| 69 | return getSectionType() & SectionFlagsReservedMask; | |||
| 70 | } | |||
| 71 | ||||
| 72 | template <typename AddressType> | |||
| 73 | bool XCOFFRelocation<AddressType>::isRelocationSigned() const { | |||
| 74 | return Info & XR_SIGN_INDICATOR_MASK; | |||
| 75 | } | |||
| 76 | ||||
| 77 | template <typename AddressType> | |||
| 78 | bool XCOFFRelocation<AddressType>::isFixupIndicated() const { | |||
| 79 | return Info & XR_FIXUP_INDICATOR_MASK; | |||
| 80 | } | |||
| 81 | ||||
| 82 | template <typename AddressType> | |||
| 83 | uint8_t XCOFFRelocation<AddressType>::getRelocatedLength() const { | |||
| 84 | // The relocation encodes the bit length being relocated minus 1. Add back | |||
| 85 | // the 1 to get the actual length being relocated. | |||
| 86 | return (Info & XR_BIASED_LENGTH_MASK) + 1; | |||
| 87 | } | |||
| 88 | ||||
| 89 | template struct ExceptionSectionEntry<support::ubig32_t>; | |||
| 90 | template struct ExceptionSectionEntry<support::ubig64_t>; | |||
| 91 | ||||
| 92 | template <typename T> | |||
| 93 | Expected<StringRef> getLoaderSecSymNameInStrTbl(const T *LoaderSecHeader, | |||
| 94 | uint64_t Offset) { | |||
| 95 | if (LoaderSecHeader->LengthOfStrTbl > Offset) | |||
| 96 | return (reinterpret_cast<const char *>(LoaderSecHeader) + | |||
| 97 | LoaderSecHeader->OffsetToStrTbl + Offset); | |||
| 98 | ||||
| 99 | return createError("entry with offset 0x" + Twine::utohexstr(Offset) + | |||
| 100 | " in the loader section's string table with size 0x" + | |||
| 101 | Twine::utohexstr(LoaderSecHeader->LengthOfStrTbl) + | |||
| 102 | " is invalid"); | |||
| 103 | } | |||
| 104 | ||||
| 105 | Expected<StringRef> LoaderSectionSymbolEntry32::getSymbolName( | |||
| 106 | const LoaderSectionHeader32 *LoaderSecHeader32) const { | |||
| 107 | const NameOffsetInStrTbl *NameInStrTbl = | |||
| 108 | reinterpret_cast<const NameOffsetInStrTbl *>(SymbolName); | |||
| 109 | if (NameInStrTbl->IsNameInStrTbl != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) | |||
| 110 | return generateXCOFFFixedNameStringRef(SymbolName); | |||
| 111 | ||||
| 112 | return getLoaderSecSymNameInStrTbl(LoaderSecHeader32, NameInStrTbl->Offset); | |||
| 113 | } | |||
| 114 | ||||
| 115 | Expected<StringRef> LoaderSectionSymbolEntry64::getSymbolName( | |||
| 116 | const LoaderSectionHeader64 *LoaderSecHeader64) const { | |||
| 117 | return getLoaderSecSymNameInStrTbl(LoaderSecHeader64, Offset); | |||
| 118 | } | |||
| 119 | ||||
| 120 | uintptr_t | |||
| 121 | XCOFFObjectFile::getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress, | |||
| 122 | uint32_t Distance) { | |||
| 123 | return getWithOffset(CurrentAddress, Distance * XCOFF::SymbolTableEntrySize); | |||
| 124 | } | |||
| 125 | ||||
| 126 | const XCOFF::SymbolAuxType * | |||
| 127 | XCOFFObjectFile::getSymbolAuxType(uintptr_t AuxEntryAddress) const { | |||
| 128 | assert(is64Bit() && "64-bit interface called on a 32-bit object file.")(static_cast <bool> (is64Bit() && "64-bit interface called on a 32-bit object file." ) ? void (0) : __assert_fail ("is64Bit() && \"64-bit interface called on a 32-bit object file.\"" , "llvm/lib/Object/XCOFFObjectFile.cpp", 128, __extension__ __PRETTY_FUNCTION__ )); | |||
| 129 | return viewAs<XCOFF::SymbolAuxType>( | |||
| 130 | getWithOffset(AuxEntryAddress, SymbolAuxTypeOffset)); | |||
| 131 | } | |||
| 132 | ||||
| 133 | void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr, | |||
| 134 | uintptr_t TableAddress) const { | |||
| 135 | if (Addr < TableAddress) | |||
| 136 | report_fatal_error("Section header outside of section header table."); | |||
| 137 | ||||
| 138 | uintptr_t Offset = Addr - TableAddress; | |||
| 139 | if (Offset >= getSectionHeaderSize() * getNumberOfSections()) | |||
| 140 | report_fatal_error("Section header outside of section header table."); | |||
| 141 | ||||
| 142 | if (Offset % getSectionHeaderSize() != 0) | |||
| 143 | report_fatal_error( | |||
| 144 | "Section header pointer does not point to a valid section header."); | |||
| 145 | } | |||
| 146 | ||||
| 147 | const XCOFFSectionHeader32 * | |||
| 148 | XCOFFObjectFile::toSection32(DataRefImpl Ref) const { | |||
| 149 | assert(!is64Bit() && "32-bit interface called on 64-bit object file.")(static_cast <bool> (!is64Bit() && "32-bit interface called on 64-bit object file." ) ? void (0) : __assert_fail ("!is64Bit() && \"32-bit interface called on 64-bit object file.\"" , "llvm/lib/Object/XCOFFObjectFile.cpp", 149, __extension__ __PRETTY_FUNCTION__ )); | |||
| 150 | #ifndef NDEBUG | |||
| 151 | checkSectionAddress(Ref.p, getSectionHeaderTableAddress()); | |||
| 152 | #endif | |||
| 153 | return viewAs<XCOFFSectionHeader32>(Ref.p); | |||
| 154 | } | |||
| 155 | ||||
| 156 | const XCOFFSectionHeader64 * | |||
| 157 | XCOFFObjectFile::toSection64(DataRefImpl Ref) const { | |||
| 158 | assert(is64Bit() && "64-bit interface called on a 32-bit object file.")(static_cast <bool> (is64Bit() && "64-bit interface called on a 32-bit object file." ) ? void (0) : __assert_fail ("is64Bit() && \"64-bit interface called on a 32-bit object file.\"" , "llvm/lib/Object/XCOFFObjectFile.cpp", 158, __extension__ __PRETTY_FUNCTION__ )); | |||
| 159 | #ifndef NDEBUG | |||
| 160 | checkSectionAddress(Ref.p, getSectionHeaderTableAddress()); | |||
| 161 | #endif | |||
| 162 | return viewAs<XCOFFSectionHeader64>(Ref.p); | |||
| 163 | } | |||
| 164 | ||||
| 165 | XCOFFSymbolRef XCOFFObjectFile::toSymbolRef(DataRefImpl Ref) const { | |||
| 166 | assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!")(static_cast <bool> (Ref.p != 0 && "Symbol table pointer can not be nullptr!" ) ? void (0) : __assert_fail ("Ref.p != 0 && \"Symbol table pointer can not be nullptr!\"" , "llvm/lib/Object/XCOFFObjectFile.cpp", 166, __extension__ __PRETTY_FUNCTION__ )); | |||
| 167 | #ifndef NDEBUG | |||
| 168 | checkSymbolEntryPointer(Ref.p); | |||
| 169 | #endif | |||
| 170 | return XCOFFSymbolRef(Ref, this); | |||
| 171 | } | |||
| 172 | ||||
| 173 | const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const { | |||
| 174 | assert(!is64Bit() && "32-bit interface called on 64-bit object file.")(static_cast <bool> (!is64Bit() && "32-bit interface called on 64-bit object file." ) ? void (0) : __assert_fail ("!is64Bit() && \"32-bit interface called on 64-bit object file.\"" , "llvm/lib/Object/XCOFFObjectFile.cpp", 174, __extension__ __PRETTY_FUNCTION__ )); | |||
| 175 | return static_cast<const XCOFFFileHeader32 *>(FileHeader); | |||
| 176 | } | |||
| 177 | ||||
| 178 | const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const { | |||
| 179 | assert(is64Bit() && "64-bit interface called on a 32-bit object file.")(static_cast <bool> (is64Bit() && "64-bit interface called on a 32-bit object file." ) ? void (0) : __assert_fail ("is64Bit() && \"64-bit interface called on a 32-bit object file.\"" , "llvm/lib/Object/XCOFFObjectFile.cpp", 179, __extension__ __PRETTY_FUNCTION__ )); | |||
| 180 | return static_cast<const XCOFFFileHeader64 *>(FileHeader); | |||
| 181 | } | |||
| 182 | ||||
| 183 | const XCOFFAuxiliaryHeader32 *XCOFFObjectFile::auxiliaryHeader32() const { | |||
| 184 | assert(!is64Bit() && "32-bit interface called on 64-bit object file.")(static_cast <bool> (!is64Bit() && "32-bit interface called on 64-bit object file." ) ? void (0) : __assert_fail ("!is64Bit() && \"32-bit interface called on 64-bit object file.\"" , "llvm/lib/Object/XCOFFObjectFile.cpp", 184, __extension__ __PRETTY_FUNCTION__ )); | |||
| 185 | return static_cast<const XCOFFAuxiliaryHeader32 *>(AuxiliaryHeader); | |||
| 186 | } | |||
| 187 | ||||
| 188 | const XCOFFAuxiliaryHeader64 *XCOFFObjectFile::auxiliaryHeader64() const { | |||
| 189 | assert(is64Bit() && "64-bit interface called on a 32-bit object file.")(static_cast <bool> (is64Bit() && "64-bit interface called on a 32-bit object file." ) ? void (0) : __assert_fail ("is64Bit() && \"64-bit interface called on a 32-bit object file.\"" , "llvm/lib/Object/XCOFFObjectFile.cpp", 189, __extension__ __PRETTY_FUNCTION__ )); | |||
| 190 | return static_cast<const XCOFFAuxiliaryHeader64 *>(AuxiliaryHeader); | |||
| 191 | } | |||
| 192 | ||||
| 193 | template <typename T> const T *XCOFFObjectFile::sectionHeaderTable() const { | |||
| 194 | return static_cast<const T *>(SectionHeaderTable); | |||
| 195 | } | |||
| 196 | ||||
| 197 | const XCOFFSectionHeader32 * | |||
| 198 | XCOFFObjectFile::sectionHeaderTable32() const { | |||
| 199 | assert(!is64Bit() && "32-bit interface called on 64-bit object file.")(static_cast <bool> (!is64Bit() && "32-bit interface called on 64-bit object file." ) ? void (0) : __assert_fail ("!is64Bit() && \"32-bit interface called on 64-bit object file.\"" , "llvm/lib/Object/XCOFFObjectFile.cpp", 199, __extension__ __PRETTY_FUNCTION__ )); | |||
| 200 | return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable); | |||
| 201 | } | |||
| 202 | ||||
| 203 | const XCOFFSectionHeader64 * | |||
| 204 | XCOFFObjectFile::sectionHeaderTable64() const { | |||
| 205 | assert(is64Bit() && "64-bit interface called on a 32-bit object file.")(static_cast <bool> (is64Bit() && "64-bit interface called on a 32-bit object file." ) ? void (0) : __assert_fail ("is64Bit() && \"64-bit interface called on a 32-bit object file.\"" , "llvm/lib/Object/XCOFFObjectFile.cpp", 205, __extension__ __PRETTY_FUNCTION__ )); | |||
| 206 | return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable); | |||
| 207 | } | |||
| 208 | ||||
| 209 | void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { | |||
| 210 | uintptr_t NextSymbolAddr = getAdvancedSymbolEntryAddress( | |||
| 211 | Symb.p, toSymbolRef(Symb).getNumberOfAuxEntries() + 1); | |||
| 212 | #ifndef NDEBUG | |||
| 213 | // This function is used by basic_symbol_iterator, which allows to | |||
| 214 | // point to the end-of-symbol-table address. | |||
| 215 | if (NextSymbolAddr != getEndOfSymbolTableAddress()) | |||
| 216 | checkSymbolEntryPointer(NextSymbolAddr); | |||
| 217 | #endif | |||
| 218 | Symb.p = NextSymbolAddr; | |||
| 219 | } | |||
| 220 | ||||
| 221 | Expected<StringRef> | |||
| 222 | XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const { | |||
| 223 | // The byte offset is relative to the start of the string table. | |||
| 224 | // A byte offset value of 0 is a null or zero-length symbol | |||
| 225 | // name. A byte offset in the range 1 to 3 (inclusive) points into the length | |||
| 226 | // field; as a soft-error recovery mechanism, we treat such cases as having an | |||
| 227 | // offset of 0. | |||
| 228 | if (Offset < 4) | |||
| 229 | return StringRef(nullptr, 0); | |||
| 230 | ||||
| 231 | if (StringTable.Data != nullptr && StringTable.Size > Offset) | |||
| 232 | return (StringTable.Data + Offset); | |||
| 233 | ||||
| 234 | return createError("entry with offset 0x" + Twine::utohexstr(Offset) + | |||
| 235 | " in a string table with size 0x" + | |||
| 236 | Twine::utohexstr(StringTable.Size) + " is invalid"); | |||
| 237 | } | |||
| 238 | ||||
| 239 | StringRef XCOFFObjectFile::getStringTable() const { | |||
| 240 | // If the size is less than or equal to 4, then the string table contains no | |||
| 241 | // string data. | |||
| 242 | return StringRef(StringTable.Data, | |||
| 243 | StringTable.Size <= 4 ? 0 : StringTable.Size); | |||
| 244 | } | |||
| 245 | ||||
| 246 | Expected<StringRef> | |||
| 247 | XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const { | |||
| 248 | if (CFileEntPtr->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) | |||
| 249 | return generateXCOFFFixedNameStringRef(CFileEntPtr->Name); | |||
| 250 | return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset); | |||
| 251 | } | |||
| 252 | ||||
| 253 | Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const { | |||
| 254 | return toSymbolRef(Symb).getName(); | |||
| 255 | } | |||
| 256 | ||||
| 257 | Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { | |||
| 258 | return toSymbolRef(Symb).getValue(); | |||
| 259 | } | |||
| 260 | ||||
| 261 | uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { | |||
| 262 | return toSymbolRef(Symb).getValue(); | |||
| 263 | } | |||
| 264 | ||||
| 265 | uint32_t XCOFFObjectFile::getSymbolAlignment(DataRefImpl Symb) const { | |||
| 266 | uint64_t Result = 0; | |||
| 267 | XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb); | |||
| 268 | if (XCOFFSym.isCsectSymbol()) { | |||
| 269 | Expected<XCOFFCsectAuxRef> CsectAuxRefOrError = | |||
| 270 | XCOFFSym.getXCOFFCsectAuxRef(); | |||
| 271 | if (!CsectAuxRefOrError) | |||
| 272 | // TODO: report the error up the stack. | |||
| 273 | consumeError(CsectAuxRefOrError.takeError()); | |||
| 274 | else | |||
| 275 | Result = 1ULL << CsectAuxRefOrError.get().getAlignmentLog2(); | |||
| 276 | } | |||
| 277 | return Result; | |||
| 278 | } | |||
| 279 | ||||
| 280 | uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { | |||
| 281 | uint64_t Result = 0; | |||
| 282 | XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb); | |||
| 283 | if (XCOFFSym.isCsectSymbol()) { | |||
| 284 | Expected<XCOFFCsectAuxRef> CsectAuxRefOrError = | |||
| 285 | XCOFFSym.getXCOFFCsectAuxRef(); | |||
| 286 | if (!CsectAuxRefOrError) | |||
| 287 | // TODO: report the error up the stack. | |||
| 288 | consumeError(CsectAuxRefOrError.takeError()); | |||
| 289 | else { | |||
| 290 | XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get(); | |||
| 291 | assert(CsectAuxRef.getSymbolType() == XCOFF::XTY_CM)(static_cast <bool> (CsectAuxRef.getSymbolType() == XCOFF ::XTY_CM) ? void (0) : __assert_fail ("CsectAuxRef.getSymbolType() == XCOFF::XTY_CM" , "llvm/lib/Object/XCOFFObjectFile.cpp", 291, __extension__ __PRETTY_FUNCTION__ )); | |||
| 292 | Result = CsectAuxRef.getSectionOrLength(); | |||
| 293 | } | |||
| 294 | } | |||
| 295 | return Result; | |||
| 296 | } | |||
| 297 | ||||
| 298 | Expected<SymbolRef::Type> | |||
| 299 | XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const { | |||
| 300 | XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb); | |||
| 301 | ||||
| 302 | if (XCOFFSym.isFunction()) | |||
| 303 | return SymbolRef::ST_Function; | |||
| 304 | ||||
| 305 | if (XCOFF::C_FILE == XCOFFSym.getStorageClass()) | |||
| 306 | return SymbolRef::ST_File; | |||
| 307 | ||||
| 308 | int16_t SecNum = XCOFFSym.getSectionNumber(); | |||
| 309 | if (SecNum <= 0) | |||
| 310 | return SymbolRef::ST_Other; | |||
| 311 | ||||
| 312 | Expected<DataRefImpl> SecDRIOrErr = | |||
| 313 | getSectionByNum(XCOFFSym.getSectionNumber()); | |||
| 314 | ||||
| 315 | if (!SecDRIOrErr) | |||
| 316 | return SecDRIOrErr.takeError(); | |||
| 317 | ||||
| 318 | DataRefImpl SecDRI = SecDRIOrErr.get(); | |||
| 319 | ||||
| 320 | Expected<StringRef> SymNameOrError = XCOFFSym.getName(); | |||
| 321 | if (SymNameOrError) { | |||
| 322 | // The "TOC" symbol is treated as SymbolRef::ST_Other. | |||
| 323 | if (SymNameOrError.get() == "TOC") | |||
| 324 | return SymbolRef::ST_Other; | |||
| 325 | ||||
| 326 | // The symbol for a section name is treated as SymbolRef::ST_Other. | |||
| 327 | StringRef SecName; | |||
| 328 | if (is64Bit()) | |||
| 329 | SecName = XCOFFObjectFile::toSection64(SecDRIOrErr.get())->getName(); | |||
| 330 | else | |||
| 331 | SecName = XCOFFObjectFile::toSection32(SecDRIOrErr.get())->getName(); | |||
| 332 | ||||
| 333 | if (SecName == SymNameOrError.get()) | |||
| 334 | return SymbolRef::ST_Other; | |||
| 335 | } else | |||
| 336 | return SymNameOrError.takeError(); | |||
| 337 | ||||
| 338 | if (isSectionData(SecDRI) || isSectionBSS(SecDRI)) | |||
| 339 | return SymbolRef::ST_Data; | |||
| 340 | ||||
| 341 | if (isDebugSection(SecDRI)) | |||
| 342 | return SymbolRef::ST_Debug; | |||
| 343 | ||||
| 344 | return SymbolRef::ST_Other; | |||
| 345 | } | |||
| 346 | ||||
| 347 | Expected<section_iterator> | |||
| 348 | XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { | |||
| 349 | const int16_t SectNum = toSymbolRef(Symb).getSectionNumber(); | |||
| ||||
| 350 | ||||
| 351 | if (isReservedSectionNumber(SectNum)) | |||
| 352 | return section_end(); | |||
| 353 | ||||
| 354 | Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum); | |||
| 355 | if (!ExpSec) | |||
| 356 | return ExpSec.takeError(); | |||
| 357 | ||||
| 358 | return section_iterator(SectionRef(ExpSec.get(), this)); | |||
| 359 | } | |||
| 360 | ||||
| 361 | void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const { | |||
| 362 | const char *Ptr = reinterpret_cast<const char *>(Sec.p); | |||
| 363 | Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize()); | |||
| 364 | } | |||
| 365 | ||||
| 366 | Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const { | |||
| 367 | return generateXCOFFFixedNameStringRef(getSectionNameInternal(Sec)); | |||
| 368 | } | |||
| 369 | ||||
| 370 | uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const { | |||
| 371 | // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t | |||
| 372 | // with MSVC. | |||
| 373 | if (is64Bit()) | |||
| 374 | return toSection64(Sec)->VirtualAddress; | |||
| 375 | ||||
| 376 | return toSection32(Sec)->VirtualAddress; | |||
| 377 | } | |||
| 378 | ||||
| 379 | uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const { | |||
| 380 | // Section numbers in XCOFF are numbered beginning at 1. A section number of | |||
| 381 | // zero is used to indicate that a symbol is being imported or is undefined. | |||
| 382 | if (is64Bit()) | |||
| 383 | return toSection64(Sec) - sectionHeaderTable64() + 1; | |||
| 384 | else | |||
| 385 | return toSection32(Sec) - sectionHeaderTable32() + 1; | |||
| 386 | } | |||
| 387 | ||||
| 388 | uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const { | |||
| 389 | // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t | |||
| 390 | // with MSVC. | |||
| 391 | if (is64Bit()) | |||
| 392 | return toSection64(Sec)->SectionSize; | |||
| 393 | ||||
| 394 | return toSection32(Sec)->SectionSize; | |||
| 395 | } | |||
| 396 | ||||
| 397 | Expected<ArrayRef<uint8_t>> | |||
| 398 | XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const { | |||
| 399 | if (isSectionVirtual(Sec)) | |||
| 400 | return ArrayRef<uint8_t>(); | |||
| 401 | ||||
| 402 | uint64_t OffsetToRaw; | |||
| 403 | if (is64Bit()) | |||
| 404 | OffsetToRaw = toSection64(Sec)->FileOffsetToRawData; | |||
| 405 | else | |||
| 406 | OffsetToRaw = toSection32(Sec)->FileOffsetToRawData; | |||
| 407 | ||||
| 408 | const uint8_t * ContentStart = base() + OffsetToRaw; | |||
| 409 | uint64_t SectionSize = getSectionSize(Sec); | |||
| 410 | if (Error E = Binary::checkOffset( | |||
| 411 | Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize)) | |||
| 412 | return createError( | |||
| 413 | toString(std::move(E)) + ": section data with offset 0x" + | |||
| 414 | Twine::utohexstr(OffsetToRaw) + " and size 0x" + | |||
| 415 | Twine::utohexstr(SectionSize) + " goes past the end of the file"); | |||
| 416 | ||||
| 417 | return ArrayRef(ContentStart, SectionSize); | |||
| 418 | } | |||
| 419 | ||||
| 420 | uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { | |||
| 421 | uint64_t Result = 0; | |||
| 422 | llvm_unreachable("Not yet implemented!")::llvm::llvm_unreachable_internal("Not yet implemented!", "llvm/lib/Object/XCOFFObjectFile.cpp" , 422); | |||
| 423 | return Result; | |||
| 424 | } | |||
| 425 | ||||
| 426 | uint64_t XCOFFObjectFile::getSectionFileOffsetToRawData(DataRefImpl Sec) const { | |||
| 427 | if (is64Bit()) | |||
| 428 | return toSection64(Sec)->FileOffsetToRawData; | |||
| 429 | ||||
| 430 | return toSection32(Sec)->FileOffsetToRawData; | |||
| 431 | } | |||
| 432 | ||||
| 433 | Expected<uintptr_t> XCOFFObjectFile::getSectionFileOffsetToRawData( | |||
| 434 | XCOFF::SectionTypeFlags SectType) const { | |||
| 435 | DataRefImpl DRI = getSectionByType(SectType); | |||
| 436 | ||||
| 437 | if (DRI.p == 0) // No section is not an error. | |||
| 438 | return 0; | |||
| 439 | ||||
| 440 | uint64_t SectionOffset = getSectionFileOffsetToRawData(DRI); | |||
| 441 | uint64_t SizeOfSection = getSectionSize(DRI); | |||
| 442 | ||||
| 443 | uintptr_t SectionStart = reinterpret_cast<uintptr_t>(base() + SectionOffset); | |||
| 444 | if (Error E = Binary::checkOffset(Data, SectionStart, SizeOfSection)) { | |||
| 445 | SmallString<32> UnknownType; | |||
| 446 | Twine(("<Unknown:") + Twine::utohexstr(SectType) + ">") | |||
| 447 | .toVector(UnknownType); | |||
| 448 | const char *SectionName = UnknownType.c_str(); | |||
| 449 | ||||
| 450 | switch (SectType) { | |||
| 451 | #define ECASE(Value, String) \ | |||
| 452 | case XCOFF::Value: \ | |||
| 453 | SectionName = String; \ | |||
| 454 | break | |||
| 455 | ||||
| 456 | ECASE(STYP_PAD, "pad"); | |||
| 457 | ECASE(STYP_DWARF, "dwarf"); | |||
| 458 | ECASE(STYP_TEXT, "text"); | |||
| 459 | ECASE(STYP_DATA, "data"); | |||
| 460 | ECASE(STYP_BSS, "bss"); | |||
| 461 | ECASE(STYP_EXCEPT, "expect"); | |||
| 462 | ECASE(STYP_INFO, "info"); | |||
| 463 | ECASE(STYP_TDATA, "tdata"); | |||
| 464 | ECASE(STYP_TBSS, "tbss"); | |||
| 465 | ECASE(STYP_LOADER, "loader"); | |||
| 466 | ECASE(STYP_DEBUG, "debug"); | |||
| 467 | ECASE(STYP_TYPCHK, "typchk"); | |||
| 468 | ECASE(STYP_OVRFLO, "ovrflo"); | |||
| 469 | #undef ECASE | |||
| 470 | } | |||
| 471 | return createError(toString(std::move(E)) + ": " + SectionName + | |||
| 472 | " section with offset 0x" + | |||
| 473 | Twine::utohexstr(SectionOffset) + " and size 0x" + | |||
| 474 | Twine::utohexstr(SizeOfSection) + | |||
| 475 | " goes past the end of the file"); | |||
| 476 | } | |||
| 477 | return SectionStart; | |||
| 478 | } | |||
| 479 | ||||
| 480 | bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { | |||
| 481 | return false; | |||
| 482 | } | |||
| 483 | ||||
| 484 | bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const { | |||
| 485 | return getSectionFlags(Sec) & XCOFF::STYP_TEXT; | |||
| 486 | } | |||
| 487 | ||||
| 488 | bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const { | |||
| 489 | uint32_t Flags = getSectionFlags(Sec); | |||
| 490 | return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA); | |||
| 491 | } | |||
| 492 | ||||
| 493 | bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const { | |||
| 494 | uint32_t Flags = getSectionFlags(Sec); | |||
| 495 | return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS); | |||
| 496 | } | |||
| 497 | ||||
| 498 | bool XCOFFObjectFile::isDebugSection(DataRefImpl Sec) const { | |||
| 499 | uint32_t Flags = getSectionFlags(Sec); | |||
| 500 | return Flags & (XCOFF::STYP_DEBUG | XCOFF::STYP_DWARF); | |||
| 501 | } | |||
| 502 | ||||
| 503 | bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const { | |||
| 504 | return is64Bit() ? toSection64(Sec)->FileOffsetToRawData == 0 | |||
| 505 | : toSection32(Sec)->FileOffsetToRawData == 0; | |||
| 506 | } | |||
| 507 | ||||
| 508 | relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const { | |||
| 509 | DataRefImpl Ret; | |||
| 510 | if (is64Bit()) { | |||
| 511 | const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec); | |||
| 512 | auto RelocationsOrErr = | |||
| 513 | relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr); | |||
| 514 | if (Error E = RelocationsOrErr.takeError()) { | |||
| 515 | // TODO: report the error up the stack. | |||
| 516 | consumeError(std::move(E)); | |||
| 517 | return relocation_iterator(RelocationRef()); | |||
| 518 | } | |||
| 519 | Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin()); | |||
| 520 | } else { | |||
| 521 | const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec); | |||
| 522 | auto RelocationsOrErr = | |||
| 523 | relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr); | |||
| 524 | if (Error E = RelocationsOrErr.takeError()) { | |||
| 525 | // TODO: report the error up the stack. | |||
| 526 | consumeError(std::move(E)); | |||
| 527 | return relocation_iterator(RelocationRef()); | |||
| 528 | } | |||
| 529 | Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin()); | |||
| 530 | } | |||
| 531 | return relocation_iterator(RelocationRef(Ret, this)); | |||
| 532 | } | |||
| 533 | ||||
| 534 | relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const { | |||
| 535 | DataRefImpl Ret; | |||
| 536 | if (is64Bit()) { | |||
| 537 | const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec); | |||
| 538 | auto RelocationsOrErr = | |||
| 539 | relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr); | |||
| 540 | if (Error E = RelocationsOrErr.takeError()) { | |||
| 541 | // TODO: report the error up the stack. | |||
| 542 | consumeError(std::move(E)); | |||
| 543 | return relocation_iterator(RelocationRef()); | |||
| 544 | } | |||
| 545 | Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end()); | |||
| 546 | } else { | |||
| 547 | const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec); | |||
| 548 | auto RelocationsOrErr = | |||
| 549 | relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr); | |||
| 550 | if (Error E = RelocationsOrErr.takeError()) { | |||
| 551 | // TODO: report the error up the stack. | |||
| 552 | consumeError(std::move(E)); | |||
| 553 | return relocation_iterator(RelocationRef()); | |||
| 554 | } | |||
| 555 | Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end()); | |||
| 556 | } | |||
| 557 | return relocation_iterator(RelocationRef(Ret, this)); | |||
| 558 | } | |||
| 559 | ||||
| 560 | void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { | |||
| 561 | if (is64Bit()) | |||
| 562 | Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation64>(Rel.p) + 1); | |||
| 563 | else | |||
| 564 | Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1); | |||
| 565 | } | |||
| 566 | ||||
| 567 | uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { | |||
| 568 | if (is64Bit()) { | |||
| 569 | const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p); | |||
| 570 | const XCOFFSectionHeader64 *Sec64 = sectionHeaderTable64(); | |||
| 571 | const uint64_t RelocAddress = Reloc->VirtualAddress; | |||
| 572 | const uint16_t NumberOfSections = getNumberOfSections(); | |||
| 573 | for (uint16_t I = 0; I < NumberOfSections; ++I) { | |||
| 574 | // Find which section this relocation belongs to, and get the | |||
| 575 | // relocation offset relative to the start of the section. | |||
| 576 | if (Sec64->VirtualAddress <= RelocAddress && | |||
| 577 | RelocAddress < Sec64->VirtualAddress + Sec64->SectionSize) { | |||
| 578 | return RelocAddress - Sec64->VirtualAddress; | |||
| 579 | } | |||
| 580 | ++Sec64; | |||
| 581 | } | |||
| 582 | } else { | |||
| 583 | const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); | |||
| 584 | const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32(); | |||
| 585 | const uint32_t RelocAddress = Reloc->VirtualAddress; | |||
| 586 | const uint16_t NumberOfSections = getNumberOfSections(); | |||
| 587 | for (uint16_t I = 0; I < NumberOfSections; ++I) { | |||
| 588 | // Find which section this relocation belongs to, and get the | |||
| 589 | // relocation offset relative to the start of the section. | |||
| 590 | if (Sec32->VirtualAddress <= RelocAddress && | |||
| 591 | RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) { | |||
| 592 | return RelocAddress - Sec32->VirtualAddress; | |||
| 593 | } | |||
| 594 | ++Sec32; | |||
| 595 | } | |||
| 596 | } | |||
| 597 | return InvalidRelocOffset; | |||
| 598 | } | |||
| 599 | ||||
| 600 | symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { | |||
| 601 | uint32_t Index; | |||
| 602 | if (is64Bit()) { | |||
| 603 | const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p); | |||
| 604 | Index = Reloc->SymbolIndex; | |||
| 605 | ||||
| 606 | if (Index >= getNumberOfSymbolTableEntries64()) | |||
| 607 | return symbol_end(); | |||
| 608 | } else { | |||
| 609 | const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); | |||
| 610 | Index = Reloc->SymbolIndex; | |||
| 611 | ||||
| 612 | if (Index >= getLogicalNumberOfSymbolTableEntries32()) | |||
| 613 | return symbol_end(); | |||
| 614 | } | |||
| 615 | DataRefImpl SymDRI; | |||
| 616 | SymDRI.p = getSymbolEntryAddressByIndex(Index); | |||
| 617 | return symbol_iterator(SymbolRef(SymDRI, this)); | |||
| 618 | } | |||
| 619 | ||||
| 620 | uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const { | |||
| 621 | if (is64Bit()) | |||
| 622 | return viewAs<XCOFFRelocation64>(Rel.p)->Type; | |||
| 623 | return viewAs<XCOFFRelocation32>(Rel.p)->Type; | |||
| 624 | } | |||
| 625 | ||||
| 626 | void XCOFFObjectFile::getRelocationTypeName( | |||
| 627 | DataRefImpl Rel, SmallVectorImpl<char> &Result) const { | |||
| 628 | StringRef Res; | |||
| 629 | if (is64Bit()) { | |||
| 630 | const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p); | |||
| 631 | Res = XCOFF::getRelocationTypeString(Reloc->Type); | |||
| 632 | } else { | |||
| 633 | const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); | |||
| 634 | Res = XCOFF::getRelocationTypeString(Reloc->Type); | |||
| 635 | } | |||
| 636 | Result.append(Res.begin(), Res.end()); | |||
| 637 | } | |||
| 638 | ||||
| 639 | Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { | |||
| 640 | XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb); | |||
| 641 | uint32_t Result = SymbolRef::SF_None; | |||
| 642 | ||||
| 643 | if (XCOFFSym.getSectionNumber() == XCOFF::N_ABS) | |||
| 644 | Result |= SymbolRef::SF_Absolute; | |||
| 645 | ||||
| 646 | XCOFF::StorageClass SC = XCOFFSym.getStorageClass(); | |||
| 647 | if (XCOFF::C_EXT == SC || XCOFF::C_WEAKEXT == SC) | |||
| 648 | Result |= SymbolRef::SF_Global; | |||
| 649 | ||||
| 650 | if (XCOFF::C_WEAKEXT == SC) | |||
| 651 | Result |= SymbolRef::SF_Weak; | |||
| 652 | ||||
| 653 | if (XCOFFSym.isCsectSymbol()) { | |||
| 654 | Expected<XCOFFCsectAuxRef> CsectAuxEntOrErr = | |||
| 655 | XCOFFSym.getXCOFFCsectAuxRef(); | |||
| 656 | if (CsectAuxEntOrErr) { | |||
| 657 | if (CsectAuxEntOrErr.get().getSymbolType() == XCOFF::XTY_CM) | |||
| 658 | Result |= SymbolRef::SF_Common; | |||
| 659 | } else | |||
| 660 | return CsectAuxEntOrErr.takeError(); | |||
| 661 | } | |||
| 662 | ||||
| 663 | if (XCOFFSym.getSectionNumber() == XCOFF::N_UNDEF) | |||
| 664 | Result |= SymbolRef::SF_Undefined; | |||
| 665 | ||||
| 666 | // There is no visibility in old 32 bit XCOFF object file interpret. | |||
| 667 | if (is64Bit() || (auxiliaryHeader32() && (auxiliaryHeader32()->getVersion() == | |||
| 668 | NEW_XCOFF_INTERPRET))) { | |||
| 669 | uint16_t SymType = XCOFFSym.getSymbolType(); | |||
| 670 | if ((SymType & VISIBILITY_MASK) == SYM_V_HIDDEN) | |||
| 671 | Result |= SymbolRef::SF_Hidden; | |||
| 672 | ||||
| 673 | if ((SymType & VISIBILITY_MASK) == SYM_V_EXPORTED) | |||
| 674 | Result |= SymbolRef::SF_Exported; | |||
| 675 | } | |||
| 676 | return Result; | |||
| 677 | } | |||
| 678 | ||||
| 679 | basic_symbol_iterator XCOFFObjectFile::symbol_begin() const { | |||
| 680 | DataRefImpl SymDRI; | |||
| 681 | SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr); | |||
| 682 | return basic_symbol_iterator(SymbolRef(SymDRI, this)); | |||
| 683 | } | |||
| 684 | ||||
| 685 | basic_symbol_iterator XCOFFObjectFile::symbol_end() const { | |||
| 686 | DataRefImpl SymDRI; | |||
| 687 | const uint32_t NumberOfSymbolTableEntries = getNumberOfSymbolTableEntries(); | |||
| 688 | SymDRI.p = getSymbolEntryAddressByIndex(NumberOfSymbolTableEntries); | |||
| 689 | return basic_symbol_iterator(SymbolRef(SymDRI, this)); | |||
| 690 | } | |||
| 691 | ||||
| 692 | section_iterator XCOFFObjectFile::section_begin() const { | |||
| 693 | DataRefImpl DRI; | |||
| 694 | DRI.p = getSectionHeaderTableAddress(); | |||
| 695 | return section_iterator(SectionRef(DRI, this)); | |||
| 696 | } | |||
| 697 | ||||
| 698 | section_iterator XCOFFObjectFile::section_end() const { | |||
| 699 | DataRefImpl DRI; | |||
| 700 | DRI.p = getWithOffset(getSectionHeaderTableAddress(), | |||
| 701 | getNumberOfSections() * getSectionHeaderSize()); | |||
| 702 | return section_iterator(SectionRef(DRI, this)); | |||
| 703 | } | |||
| 704 | ||||
| 705 | uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; } | |||
| 706 | ||||
| 707 | StringRef XCOFFObjectFile::getFileFormatName() const { | |||
| 708 | return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000"; | |||
| 709 | } | |||
| 710 | ||||
| 711 | Triple::ArchType XCOFFObjectFile::getArch() const { | |||
| 712 | return is64Bit() ? Triple::ppc64 : Triple::ppc; | |||
| 713 | } | |||
| 714 | ||||
| 715 | Expected<SubtargetFeatures> XCOFFObjectFile::getFeatures() const { | |||
| 716 | return SubtargetFeatures(); | |||
| 717 | } | |||
| 718 | ||||
| 719 | bool XCOFFObjectFile::isRelocatableObject() const { | |||
| 720 | if (is64Bit()) | |||
| 721 | return !(fileHeader64()->Flags & NoRelMask); | |||
| 722 | return !(fileHeader32()->Flags & NoRelMask); | |||
| 723 | } | |||
| 724 | ||||
| 725 | Expected<uint64_t> XCOFFObjectFile::getStartAddress() const { | |||
| 726 | // TODO FIXME Should get from auxiliary_header->o_entry when support for the | |||
| 727 | // auxiliary_header is added. | |||
| 728 | return 0; | |||
| 729 | } | |||
| 730 | ||||
| 731 | StringRef XCOFFObjectFile::mapDebugSectionName(StringRef Name) const { | |||
| 732 | return StringSwitch<StringRef>(Name) | |||
| 733 | .Case("dwinfo", "debug_info") | |||
| 734 | .Case("dwline", "debug_line") | |||
| 735 | .Case("dwpbnms", "debug_pubnames") | |||
| 736 | .Case("dwpbtyp", "debug_pubtypes") | |||
| 737 | .Case("dwarnge", "debug_aranges") | |||
| 738 | .Case("dwabrev", "debug_abbrev") | |||
| 739 | .Case("dwstr", "debug_str") | |||
| 740 | .Case("dwrnges", "debug_ranges") | |||
| 741 | .Case("dwloc", "debug_loc") | |||
| 742 | .Case("dwframe", "debug_frame") | |||
| 743 | .Case("dwmac", "debug_macinfo") | |||
| 744 | .Default(Name); | |||
| 745 | } | |||
| 746 | ||||
| 747 | size_t XCOFFObjectFile::getFileHeaderSize() const { | |||
| 748 | return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32); | |||
| 749 | } | |||
| 750 | ||||
| 751 | size_t XCOFFObjectFile::getSectionHeaderSize() const { | |||
| 752 | return is64Bit() ? sizeof(XCOFFSectionHeader64) : | |||
| 753 | sizeof(XCOFFSectionHeader32); | |||
| 754 | } | |||
| 755 | ||||
| 756 | bool XCOFFObjectFile::is64Bit() const { | |||
| 757 | return Binary::ID_XCOFF64 == getType(); | |||
| 758 | } | |||
| 759 | ||||
| 760 | Expected<StringRef> XCOFFObjectFile::getRawData(const char *Start, | |||
| 761 | uint64_t Size, | |||
| 762 | StringRef Name) const { | |||
| 763 | uintptr_t StartPtr = reinterpret_cast<uintptr_t>(Start); | |||
| 764 | // TODO: this path is untested. | |||
| 765 | if (Error E = Binary::checkOffset(Data, StartPtr, Size)) | |||
| 766 | return createError(toString(std::move(E)) + ": " + Name.data() + | |||
| 767 | " data with offset 0x" + Twine::utohexstr(StartPtr) + | |||
| 768 | " and size 0x" + Twine::utohexstr(Size) + | |||
| 769 | " goes past the end of the file"); | |||
| 770 | return StringRef(Start, Size); | |||
| 771 | } | |||
| 772 | ||||
| 773 | uint16_t XCOFFObjectFile::getMagic() const { | |||
| 774 | return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic; | |||
| 775 | } | |||
| 776 | ||||
| 777 | Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const { | |||
| 778 | if (Num <= 0 || Num > getNumberOfSections()) | |||
| 779 | return createStringError(object_error::invalid_section_index, | |||
| 780 | "the section index (" + Twine(Num) + | |||
| 781 | ") is invalid"); | |||
| 782 | ||||
| 783 | DataRefImpl DRI; | |||
| 784 | DRI.p = getWithOffset(getSectionHeaderTableAddress(), | |||
| 785 | getSectionHeaderSize() * (Num - 1)); | |||
| 786 | return DRI; | |||
| 787 | } | |||
| 788 | ||||
| 789 | DataRefImpl | |||
| 790 | XCOFFObjectFile::getSectionByType(XCOFF::SectionTypeFlags SectType) const { | |||
| 791 | DataRefImpl DRI; | |||
| 792 | auto GetSectionAddr = [&](const auto &Sections) -> uintptr_t { | |||
| 793 | for (const auto &Sec : Sections) | |||
| 794 | if (Sec.getSectionType() == SectType) | |||
| 795 | return reinterpret_cast<uintptr_t>(&Sec); | |||
| 796 | return uintptr_t(0); | |||
| 797 | }; | |||
| 798 | if (is64Bit()) | |||
| 799 | DRI.p = GetSectionAddr(sections64()); | |||
| 800 | else | |||
| 801 | DRI.p = GetSectionAddr(sections32()); | |||
| 802 | return DRI; | |||
| 803 | } | |||
| 804 | ||||
| 805 | Expected<StringRef> | |||
| 806 | XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const { | |||
| 807 | const int16_t SectionNum = SymEntPtr.getSectionNumber(); | |||
| 808 | ||||
| 809 | switch (SectionNum) { | |||
| 810 | case XCOFF::N_DEBUG: | |||
| 811 | return "N_DEBUG"; | |||
| 812 | case XCOFF::N_ABS: | |||
| 813 | return "N_ABS"; | |||
| 814 | case XCOFF::N_UNDEF: | |||
| 815 | return "N_UNDEF"; | |||
| 816 | default: | |||
| 817 | Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum); | |||
| 818 | if (SecRef) | |||
| 819 | return generateXCOFFFixedNameStringRef( | |||
| 820 | getSectionNameInternal(SecRef.get())); | |||
| 821 | return SecRef.takeError(); | |||
| 822 | } | |||
| 823 | } | |||
| 824 | ||||
| 825 | unsigned XCOFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { | |||
| 826 | XCOFFSymbolRef XCOFFSymRef(Sym.getRawDataRefImpl(), this); | |||
| 827 | return XCOFFSymRef.getSectionNumber(); | |||
| 828 | } | |||
| 829 | ||||
| 830 | bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) { | |||
| 831 | return (SectionNumber <= 0 && SectionNumber >= -2); | |||
| 832 | } | |||
| 833 | ||||
| 834 | uint16_t XCOFFObjectFile::getNumberOfSections() const { | |||
| 835 | return is64Bit() ? fileHeader64()->NumberOfSections | |||
| 836 | : fileHeader32()->NumberOfSections; | |||
| 837 | } | |||
| 838 | ||||
| 839 | int32_t XCOFFObjectFile::getTimeStamp() const { | |||
| 840 | return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp; | |||
| 841 | } | |||
| 842 | ||||
| 843 | uint16_t XCOFFObjectFile::getOptionalHeaderSize() const { | |||
| 844 | return is64Bit() ? fileHeader64()->AuxHeaderSize | |||
| 845 | : fileHeader32()->AuxHeaderSize; | |||
| 846 | } | |||
| 847 | ||||
| 848 | uint32_t XCOFFObjectFile::getSymbolTableOffset32() const { | |||
| 849 | return fileHeader32()->SymbolTableOffset; | |||
| 850 | } | |||
| 851 | ||||
| 852 | int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const { | |||
| 853 | // As far as symbol table size is concerned, if this field is negative it is | |||
| 854 | // to be treated as a 0. However since this field is also used for printing we | |||
| 855 | // don't want to truncate any negative values. | |||
| 856 | return fileHeader32()->NumberOfSymTableEntries; | |||
| 857 | } | |||
| 858 | ||||
| 859 | uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const { | |||
| 860 | return (fileHeader32()->NumberOfSymTableEntries >= 0 | |||
| 861 | ? fileHeader32()->NumberOfSymTableEntries | |||
| 862 | : 0); | |||
| 863 | } | |||
| 864 | ||||
| 865 | uint64_t XCOFFObjectFile::getSymbolTableOffset64() const { | |||
| 866 | return fileHeader64()->SymbolTableOffset; | |||
| 867 | } | |||
| 868 | ||||
| 869 | uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const { | |||
| 870 | return fileHeader64()->NumberOfSymTableEntries; | |||
| 871 | } | |||
| 872 | ||||
| 873 | uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const { | |||
| 874 | return is64Bit() ? getNumberOfSymbolTableEntries64() | |||
| 875 | : getLogicalNumberOfSymbolTableEntries32(); | |||
| 876 | } | |||
| 877 | ||||
| 878 | uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const { | |||
| 879 | const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries(); | |||
| 880 | return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr), | |||
| 881 | XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries); | |||
| 882 | } | |||
| 883 | ||||
| 884 | void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const { | |||
| 885 | if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr)) | |||
| 886 | report_fatal_error("Symbol table entry is outside of symbol table."); | |||
| 887 | ||||
| 888 | if (SymbolEntPtr >= getEndOfSymbolTableAddress()) | |||
| 889 | report_fatal_error("Symbol table entry is outside of symbol table."); | |||
| 890 | ||||
| 891 | ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) - | |||
| 892 | reinterpret_cast<const char *>(SymbolTblPtr); | |||
| 893 | ||||
| 894 | if (Offset % XCOFF::SymbolTableEntrySize != 0) | |||
| 895 | report_fatal_error( | |||
| 896 | "Symbol table entry position is not valid inside of symbol table."); | |||
| 897 | } | |||
| 898 | ||||
| 899 | uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const { | |||
| 900 | return (reinterpret_cast<const char *>(SymbolEntPtr) - | |||
| 901 | reinterpret_cast<const char *>(SymbolTblPtr)) / | |||
| 902 | XCOFF::SymbolTableEntrySize; | |||
| 903 | } | |||
| 904 | ||||
| 905 | uint64_t XCOFFObjectFile::getSymbolSize(DataRefImpl Symb) const { | |||
| 906 | uint64_t Result = 0; | |||
| 907 | XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb); | |||
| 908 | if (XCOFFSym.isCsectSymbol()) { | |||
| 909 | Expected<XCOFFCsectAuxRef> CsectAuxRefOrError = | |||
| 910 | XCOFFSym.getXCOFFCsectAuxRef(); | |||
| 911 | if (!CsectAuxRefOrError) | |||
| 912 | // TODO: report the error up the stack. | |||
| 913 | consumeError(CsectAuxRefOrError.takeError()); | |||
| 914 | else { | |||
| 915 | XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get(); | |||
| 916 | uint8_t SymType = CsectAuxRef.getSymbolType(); | |||
| 917 | if (SymType == XCOFF::XTY_SD || SymType == XCOFF::XTY_CM) | |||
| 918 | Result = CsectAuxRef.getSectionOrLength(); | |||
| 919 | } | |||
| 920 | } | |||
| 921 | return Result; | |||
| 922 | } | |||
| 923 | ||||
| 924 | uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const { | |||
| 925 | return getAdvancedSymbolEntryAddress( | |||
| 926 | reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index); | |||
| 927 | } | |||
| 928 | ||||
| 929 | Expected<StringRef> | |||
| 930 | XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const { | |||
| 931 | const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries(); | |||
| 932 | ||||
| 933 | if (Index >= NumberOfSymTableEntries) | |||
| 934 | return createError("symbol index " + Twine(Index) + | |||
| 935 | " exceeds symbol count " + | |||
| 936 | Twine(NumberOfSymTableEntries)); | |||
| 937 | ||||
| 938 | DataRefImpl SymDRI; | |||
| 939 | SymDRI.p = getSymbolEntryAddressByIndex(Index); | |||
| 940 | return getSymbolName(SymDRI); | |||
| 941 | } | |||
| 942 | ||||
| 943 | uint16_t XCOFFObjectFile::getFlags() const { | |||
| 944 | return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags; | |||
| 945 | } | |||
| 946 | ||||
| 947 | const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const { | |||
| 948 | return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name; | |||
| 949 | } | |||
| 950 | ||||
| 951 | uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const { | |||
| 952 | return reinterpret_cast<uintptr_t>(SectionHeaderTable); | |||
| 953 | } | |||
| 954 | ||||
| 955 | int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const { | |||
| 956 | return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags; | |||
| 957 | } | |||
| 958 | ||||
| 959 | XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object) | |||
| 960 | : ObjectFile(Type, Object) { | |||
| 961 | assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64)(static_cast <bool> (Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64) ? void (0) : __assert_fail ("Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64" , "llvm/lib/Object/XCOFFObjectFile.cpp", 961, __extension__ __PRETTY_FUNCTION__ )); | |||
| 962 | } | |||
| 963 | ||||
| 964 | ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const { | |||
| 965 | assert(is64Bit() && "64-bit interface called for non 64-bit file.")(static_cast <bool> (is64Bit() && "64-bit interface called for non 64-bit file." ) ? void (0) : __assert_fail ("is64Bit() && \"64-bit interface called for non 64-bit file.\"" , "llvm/lib/Object/XCOFFObjectFile.cpp", 965, __extension__ __PRETTY_FUNCTION__ )); | |||
| 966 | const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64(); | |||
| 967 | return ArrayRef<XCOFFSectionHeader64>(TablePtr, | |||
| 968 | TablePtr + getNumberOfSections()); | |||
| 969 | } | |||
| 970 | ||||
| 971 | ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const { | |||
| 972 | assert(!is64Bit() && "32-bit interface called for non 32-bit file.")(static_cast <bool> (!is64Bit() && "32-bit interface called for non 32-bit file." ) ? void (0) : __assert_fail ("!is64Bit() && \"32-bit interface called for non 32-bit file.\"" , "llvm/lib/Object/XCOFFObjectFile.cpp", 972, __extension__ __PRETTY_FUNCTION__ )); | |||
| 973 | const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32(); | |||
| 974 | return ArrayRef<XCOFFSectionHeader32>(TablePtr, | |||
| 975 | TablePtr + getNumberOfSections()); | |||
| 976 | } | |||
| 977 | ||||
| 978 | // In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO | |||
| 979 | // section header contains the actual count of relocation entries in the s_paddr | |||
| 980 | // field. STYP_OVRFLO headers contain the section index of their corresponding | |||
| 981 | // sections as their raw "NumberOfRelocations" field value. | |||
| 982 | template <typename T> | |||
| 983 | Expected<uint32_t> XCOFFObjectFile::getNumberOfRelocationEntries( | |||
| 984 | const XCOFFSectionHeader<T> &Sec) const { | |||
| 985 | const T &Section = static_cast<const T &>(Sec); | |||
| 986 | if (is64Bit()) | |||
| 987 | return Section.NumberOfRelocations; | |||
| 988 | ||||
| 989 | uint16_t SectionIndex = &Section - sectionHeaderTable<T>() + 1; | |||
| 990 | if (Section.NumberOfRelocations < XCOFF::RelocOverflow) | |||
| 991 | return Section.NumberOfRelocations; | |||
| 992 | for (const auto &Sec : sections32()) { | |||
| 993 | if (Sec.Flags == XCOFF::STYP_OVRFLO && | |||
| 994 | Sec.NumberOfRelocations == SectionIndex) | |||
| 995 | return Sec.PhysicalAddress; | |||
| 996 | } | |||
| 997 | return errorCodeToError(object_error::parse_failed); | |||
| 998 | } | |||
| 999 | ||||
| 1000 | template <typename Shdr, typename Reloc> | |||
| 1001 | Expected<ArrayRef<Reloc>> XCOFFObjectFile::relocations(const Shdr &Sec) const { | |||
| 1002 | uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader), | |||
| 1003 | Sec.FileOffsetToRelocationInfo); | |||
| 1004 | auto NumRelocEntriesOrErr = getNumberOfRelocationEntries(Sec); | |||
| 1005 | if (Error E = NumRelocEntriesOrErr.takeError()) | |||
| 1006 | return std::move(E); | |||
| 1007 | ||||
| 1008 | uint32_t NumRelocEntries = NumRelocEntriesOrErr.get(); | |||
| 1009 | static_assert((sizeof(Reloc) == XCOFF::RelocationSerializationSize64 || | |||
| 1010 | sizeof(Reloc) == XCOFF::RelocationSerializationSize32), | |||
| 1011 | "Relocation structure is incorrect"); | |||
| 1012 | auto RelocationOrErr = | |||
| 1013 | getObject<Reloc>(Data, reinterpret_cast<void *>(RelocAddr), | |||
| 1014 | NumRelocEntries * sizeof(Reloc)); | |||
| 1015 | if (!RelocationOrErr) | |||
| 1016 | return createError( | |||
| 1017 | toString(RelocationOrErr.takeError()) + ": relocations with offset 0x" + | |||
| 1018 | Twine::utohexstr(Sec.FileOffsetToRelocationInfo) + " and size 0x" + | |||
| 1019 | Twine::utohexstr(NumRelocEntries * sizeof(Reloc)) + | |||
| 1020 | " go past the end of the file"); | |||
| 1021 | ||||
| 1022 | const Reloc *StartReloc = RelocationOrErr.get(); | |||
| 1023 | ||||
| 1024 | return ArrayRef<Reloc>(StartReloc, StartReloc + NumRelocEntries); | |||
| 1025 | } | |||
| 1026 | ||||
| 1027 | template <typename ExceptEnt> | |||
| 1028 | Expected<ArrayRef<ExceptEnt>> XCOFFObjectFile::getExceptionEntries() const { | |||
| 1029 | assert((is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry64)) ||(static_cast <bool> ((is64Bit() && sizeof(ExceptEnt ) == sizeof(ExceptionSectionEntry64)) || (!is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry32))) ? void (0) : __assert_fail ("(is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry64)) || (!is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry32))" , "llvm/lib/Object/XCOFFObjectFile.cpp", 1030, __extension__ __PRETTY_FUNCTION__ )) | |||
| 1030 | (!is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry32)))(static_cast <bool> ((is64Bit() && sizeof(ExceptEnt ) == sizeof(ExceptionSectionEntry64)) || (!is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry32))) ? void (0) : __assert_fail ("(is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry64)) || (!is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry32))" , "llvm/lib/Object/XCOFFObjectFile.cpp", 1030, __extension__ __PRETTY_FUNCTION__ )); | |||
| 1031 | ||||
| 1032 | Expected<uintptr_t> ExceptionSectOrErr = | |||
| 1033 | getSectionFileOffsetToRawData(XCOFF::STYP_EXCEPT); | |||
| 1034 | if (!ExceptionSectOrErr) | |||
| 1035 | return ExceptionSectOrErr.takeError(); | |||
| 1036 | ||||
| 1037 | DataRefImpl DRI = getSectionByType(XCOFF::STYP_EXCEPT); | |||
| 1038 | if (DRI.p == 0) | |||
| 1039 | return ArrayRef<ExceptEnt>(); | |||
| 1040 | ||||
| 1041 | ExceptEnt *ExceptEntStart = | |||
| 1042 | reinterpret_cast<ExceptEnt *>(*ExceptionSectOrErr); | |||
| 1043 | return ArrayRef<ExceptEnt>( | |||
| 1044 | ExceptEntStart, ExceptEntStart + getSectionSize(DRI) / sizeof(ExceptEnt)); | |||
| 1045 | } | |||
| 1046 | ||||
| 1047 | template Expected<ArrayRef<ExceptionSectionEntry32>> | |||
| 1048 | XCOFFObjectFile::getExceptionEntries() const; | |||
| 1049 | template Expected<ArrayRef<ExceptionSectionEntry64>> | |||
| 1050 | XCOFFObjectFile::getExceptionEntries() const; | |||
| 1051 | ||||
| 1052 | Expected<XCOFFStringTable> | |||
| 1053 | XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) { | |||
| 1054 | // If there is a string table, then the buffer must contain at least 4 bytes | |||
| 1055 | // for the string table's size. Not having a string table is not an error. | |||
| 1056 | if (Error E = Binary::checkOffset( | |||
| 1057 | Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) { | |||
| 1058 | consumeError(std::move(E)); | |||
| 1059 | return XCOFFStringTable{0, nullptr}; | |||
| 1060 | } | |||
| 1061 | ||||
| 1062 | // Read the size out of the buffer. | |||
| 1063 | uint32_t Size = support::endian::read32be(Obj->base() + Offset); | |||
| 1064 | ||||
| 1065 | // If the size is less then 4, then the string table is just a size and no | |||
| 1066 | // string data. | |||
| 1067 | if (Size <= 4) | |||
| 1068 | return XCOFFStringTable{4, nullptr}; | |||
| 1069 | ||||
| 1070 | auto StringTableOrErr = | |||
| 1071 | getObject<char>(Obj->Data, Obj->base() + Offset, Size); | |||
| 1072 | if (!StringTableOrErr) | |||
| 1073 | return createError(toString(StringTableOrErr.takeError()) + | |||
| 1074 | ": string table with offset 0x" + | |||
| 1075 | Twine::utohexstr(Offset) + " and size 0x" + | |||
| 1076 | Twine::utohexstr(Size) + | |||
| 1077 | " goes past the end of the file"); | |||
| 1078 | ||||
| 1079 | const char *StringTablePtr = StringTableOrErr.get(); | |||
| 1080 | if (StringTablePtr[Size - 1] != '\0') | |||
| 1081 | return errorCodeToError(object_error::string_table_non_null_end); | |||
| 1082 | ||||
| 1083 | return XCOFFStringTable{Size, StringTablePtr}; | |||
| 1084 | } | |||
| 1085 | ||||
| 1086 | // This function returns the import file table. Each entry in the import file | |||
| 1087 | // table consists of: "path_name\0base_name\0archive_member_name\0". | |||
| 1088 | Expected<StringRef> XCOFFObjectFile::getImportFileTable() const { | |||
| 1089 | Expected<uintptr_t> LoaderSectionAddrOrError = | |||
| 1090 | getSectionFileOffsetToRawData(XCOFF::STYP_LOADER); | |||
| 1091 | if (!LoaderSectionAddrOrError) | |||
| 1092 | return LoaderSectionAddrOrError.takeError(); | |||
| 1093 | ||||
| 1094 | uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get(); | |||
| 1095 | if (!LoaderSectionAddr) | |||
| 1096 | return StringRef(); | |||
| 1097 | ||||
| 1098 | uint64_t OffsetToImportFileTable = 0; | |||
| 1099 | uint64_t LengthOfImportFileTable = 0; | |||
| 1100 | if (is64Bit()) { | |||
| 1101 | const LoaderSectionHeader64 *LoaderSec64 = | |||
| 1102 | viewAs<LoaderSectionHeader64>(LoaderSectionAddr); | |||
| 1103 | OffsetToImportFileTable = LoaderSec64->OffsetToImpid; | |||
| 1104 | LengthOfImportFileTable = LoaderSec64->LengthOfImpidStrTbl; | |||
| 1105 | } else { | |||
| 1106 | const LoaderSectionHeader32 *LoaderSec32 = | |||
| 1107 | viewAs<LoaderSectionHeader32>(LoaderSectionAddr); | |||
| 1108 | OffsetToImportFileTable = LoaderSec32->OffsetToImpid; | |||
| 1109 | LengthOfImportFileTable = LoaderSec32->LengthOfImpidStrTbl; | |||
| 1110 | } | |||
| 1111 | ||||
| 1112 | auto ImportTableOrErr = getObject<char>( | |||
| 1113 | Data, | |||
| 1114 | reinterpret_cast<void *>(LoaderSectionAddr + OffsetToImportFileTable), | |||
| 1115 | LengthOfImportFileTable); | |||
| 1116 | if (!ImportTableOrErr) | |||
| 1117 | return createError( | |||
| 1118 | toString(ImportTableOrErr.takeError()) + | |||
| 1119 | ": import file table with offset 0x" + | |||
| 1120 | Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) + | |||
| 1121 | " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) + | |||
| 1122 | " goes past the end of the file"); | |||
| 1123 | ||||
| 1124 | const char *ImportTablePtr = ImportTableOrErr.get(); | |||
| 1125 | if (ImportTablePtr[LengthOfImportFileTable - 1] != '\0') | |||
| 1126 | return createError( | |||
| 1127 | ": import file name table with offset 0x" + | |||
| 1128 | Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) + | |||
| 1129 | " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) + | |||
| 1130 | " must end with a null terminator"); | |||
| 1131 | ||||
| 1132 | return StringRef(ImportTablePtr, LengthOfImportFileTable); | |||
| 1133 | } | |||
| 1134 | ||||
| 1135 | Expected<std::unique_ptr<XCOFFObjectFile>> | |||
| 1136 | XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) { | |||
| 1137 | // Can't use std::make_unique because of the private constructor. | |||
| 1138 | std::unique_ptr<XCOFFObjectFile> Obj; | |||
| 1139 | Obj.reset(new XCOFFObjectFile(Type, MBR)); | |||
| 1140 | ||||
| 1141 | uint64_t CurOffset = 0; | |||
| 1142 | const auto *Base = Obj->base(); | |||
| 1143 | MemoryBufferRef Data = Obj->Data; | |||
| 1144 | ||||
| 1145 | // Parse file header. | |||
| 1146 | auto FileHeaderOrErr = | |||
| 1147 | getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize()); | |||
| 1148 | if (Error E = FileHeaderOrErr.takeError()) | |||
| 1149 | return std::move(E); | |||
| 1150 | Obj->FileHeader = FileHeaderOrErr.get(); | |||
| 1151 | ||||
| 1152 | CurOffset += Obj->getFileHeaderSize(); | |||
| 1153 | ||||
| 1154 | if (Obj->getOptionalHeaderSize()) { | |||
| 1155 | auto AuxiliaryHeaderOrErr = | |||
| 1156 | getObject<void>(Data, Base + CurOffset, Obj->getOptionalHeaderSize()); | |||
| 1157 | if (Error E = AuxiliaryHeaderOrErr.takeError()) | |||
| 1158 | return std::move(E); | |||
| 1159 | Obj->AuxiliaryHeader = AuxiliaryHeaderOrErr.get(); | |||
| 1160 | } | |||
| 1161 | ||||
| 1162 | CurOffset += Obj->getOptionalHeaderSize(); | |||
| 1163 | ||||
| 1164 | // Parse the section header table if it is present. | |||
| 1165 | if (Obj->getNumberOfSections()) { | |||
| 1166 | uint64_t SectionHeadersSize = | |||
| 1167 | Obj->getNumberOfSections() * Obj->getSectionHeaderSize(); | |||
| 1168 | auto SecHeadersOrErr = | |||
| 1169 | getObject<void>(Data, Base + CurOffset, SectionHeadersSize); | |||
| 1170 | if (!SecHeadersOrErr) | |||
| 1171 | return createError(toString(SecHeadersOrErr.takeError()) + | |||
| 1172 | ": section headers with offset 0x" + | |||
| 1173 | Twine::utohexstr(CurOffset) + " and size 0x" + | |||
| 1174 | Twine::utohexstr(SectionHeadersSize) + | |||
| 1175 | " go past the end of the file"); | |||
| 1176 | ||||
| 1177 | Obj->SectionHeaderTable = SecHeadersOrErr.get(); | |||
| 1178 | } | |||
| 1179 | ||||
| 1180 | const uint32_t NumberOfSymbolTableEntries = | |||
| 1181 | Obj->getNumberOfSymbolTableEntries(); | |||
| 1182 | ||||
| 1183 | // If there is no symbol table we are done parsing the memory buffer. | |||
| 1184 | if (NumberOfSymbolTableEntries == 0) | |||
| 1185 | return std::move(Obj); | |||
| 1186 | ||||
| 1187 | // Parse symbol table. | |||
| 1188 | CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64() | |||
| 1189 | : Obj->getSymbolTableOffset32(); | |||
| 1190 | const uint64_t SymbolTableSize = | |||
| 1191 | static_cast<uint64_t>(XCOFF::SymbolTableEntrySize) * | |||
| 1192 | NumberOfSymbolTableEntries; | |||
| 1193 | auto SymTableOrErr = | |||
| 1194 | getObject<void *>(Data, Base + CurOffset, SymbolTableSize); | |||
| 1195 | if (!SymTableOrErr) | |||
| 1196 | return createError( | |||
| 1197 | toString(SymTableOrErr.takeError()) + ": symbol table with offset 0x" + | |||
| 1198 | Twine::utohexstr(CurOffset) + " and size 0x" + | |||
| 1199 | Twine::utohexstr(SymbolTableSize) + " goes past the end of the file"); | |||
| 1200 | ||||
| 1201 | Obj->SymbolTblPtr = SymTableOrErr.get(); | |||
| 1202 | CurOffset += SymbolTableSize; | |||
| 1203 | ||||
| 1204 | // Parse String table. | |||
| 1205 | Expected<XCOFFStringTable> StringTableOrErr = | |||
| 1206 | parseStringTable(Obj.get(), CurOffset); | |||
| 1207 | if (Error E = StringTableOrErr.takeError()) | |||
| 1208 | return std::move(E); | |||
| 1209 | Obj->StringTable = StringTableOrErr.get(); | |||
| 1210 | ||||
| 1211 | return std::move(Obj); | |||
| 1212 | } | |||
| 1213 | ||||
| 1214 | Expected<std::unique_ptr<ObjectFile>> | |||
| 1215 | ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef, | |||
| 1216 | unsigned FileType) { | |||
| 1217 | return XCOFFObjectFile::create(FileType, MemBufRef); | |||
| 1218 | } | |||
| 1219 | ||||
| 1220 | bool XCOFFSymbolRef::isFunction() const { | |||
| 1221 | if (!isCsectSymbol()) | |||
| 1222 | return false; | |||
| 1223 | ||||
| 1224 | if (getSymbolType() & FunctionSym) | |||
| 1225 | return true; | |||
| 1226 | ||||
| 1227 | Expected<XCOFFCsectAuxRef> ExpCsectAuxEnt = getXCOFFCsectAuxRef(); | |||
| 1228 | if (!ExpCsectAuxEnt) { | |||
| 1229 | // If we could not get the CSECT auxiliary entry, then treat this symbol as | |||
| 1230 | // if it isn't a function. Consume the error and return `false` to move on. | |||
| 1231 | consumeError(ExpCsectAuxEnt.takeError()); | |||
| 1232 | return false; | |||
| 1233 | } | |||
| 1234 | ||||
| 1235 | const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get(); | |||
| 1236 | ||||
| 1237 | // A function definition should be a label definition. | |||
| 1238 | // FIXME: This is not necessarily the case when -ffunction-sections is | |||
| 1239 | // enabled. | |||
| 1240 | if (!CsectAuxRef.isLabel()) | |||
| 1241 | return false; | |||
| 1242 | ||||
| 1243 | if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR) | |||
| 1244 | return false; | |||
| 1245 | ||||
| 1246 | const int16_t SectNum = getSectionNumber(); | |||
| 1247 | Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum); | |||
| 1248 | if (!SI) { | |||
| 1249 | // If we could not get the section, then this symbol should not be | |||
| 1250 | // a function. So consume the error and return `false` to move on. | |||
| 1251 | consumeError(SI.takeError()); | |||
| 1252 | return false; | |||
| 1253 | } | |||
| 1254 | ||||
| 1255 | return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT); | |||
| 1256 | } | |||
| 1257 | ||||
| 1258 | bool XCOFFSymbolRef::isCsectSymbol() const { | |||
| 1259 | XCOFF::StorageClass SC = getStorageClass(); | |||
| 1260 | return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT || | |||
| 1261 | SC == XCOFF::C_HIDEXT); | |||
| 1262 | } | |||
| 1263 | ||||
| 1264 | Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const { | |||
| 1265 | assert(isCsectSymbol() &&(static_cast <bool> (isCsectSymbol() && "Calling csect symbol interface with a non-csect symbol." ) ? void (0) : __assert_fail ("isCsectSymbol() && \"Calling csect symbol interface with a non-csect symbol.\"" , "llvm/lib/Object/XCOFFObjectFile.cpp", 1266, __extension__ __PRETTY_FUNCTION__ )) | |||
| 1266 | "Calling csect symbol interface with a non-csect symbol.")(static_cast <bool> (isCsectSymbol() && "Calling csect symbol interface with a non-csect symbol." ) ? void (0) : __assert_fail ("isCsectSymbol() && \"Calling csect symbol interface with a non-csect symbol.\"" , "llvm/lib/Object/XCOFFObjectFile.cpp", 1266, __extension__ __PRETTY_FUNCTION__ )); | |||
| 1267 | ||||
| 1268 | uint8_t NumberOfAuxEntries = getNumberOfAuxEntries(); | |||
| 1269 | ||||
| 1270 | Expected<StringRef> NameOrErr = getName(); | |||
| 1271 | if (auto Err = NameOrErr.takeError()) | |||
| 1272 | return std::move(Err); | |||
| 1273 | ||||
| 1274 | uint32_t SymbolIdx = OwningObjectPtr->getSymbolIndex(getEntryAddress()); | |||
| 1275 | if (!NumberOfAuxEntries) { | |||
| 1276 | return createError("csect symbol \"" + *NameOrErr + "\" with index " + | |||
| 1277 | Twine(SymbolIdx) + " contains no auxiliary entry"); | |||
| 1278 | } | |||
| 1279 | ||||
| 1280 | if (!OwningObjectPtr->is64Bit()) { | |||
| 1281 | // In XCOFF32, the csect auxilliary entry is always the last auxiliary | |||
| 1282 | // entry for the symbol. | |||
| 1283 | uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress( | |||
| 1284 | getEntryAddress(), NumberOfAuxEntries); | |||
| 1285 | return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt32>(AuxAddr)); | |||
| 1286 | } | |||
| 1287 | ||||
| 1288 | // XCOFF64 uses SymbolAuxType to identify the auxiliary entry type. | |||
| 1289 | // We need to iterate through all the auxiliary entries to find it. | |||
| 1290 | for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) { | |||
| 1291 | uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress( | |||
| 1292 | getEntryAddress(), Index); | |||
| 1293 | if (*OwningObjectPtr->getSymbolAuxType(AuxAddr) == | |||
| 1294 | XCOFF::SymbolAuxType::AUX_CSECT) { | |||
| 1295 | #ifndef NDEBUG | |||
| 1296 | OwningObjectPtr->checkSymbolEntryPointer(AuxAddr); | |||
| 1297 | #endif | |||
| 1298 | return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr)); | |||
| 1299 | } | |||
| 1300 | } | |||
| 1301 | ||||
| 1302 | return createError( | |||
| 1303 | "a csect auxiliary entry has not been found for symbol \"" + *NameOrErr + | |||
| 1304 | "\" with index " + Twine(SymbolIdx)); | |||
| 1305 | } | |||
| 1306 | ||||
| 1307 | Expected<StringRef> XCOFFSymbolRef::getName() const { | |||
| 1308 | // A storage class value with the high-order bit on indicates that the name is | |||
| 1309 | // a symbolic debugger stabstring. | |||
| 1310 | if (getStorageClass() & 0x80) | |||
| 1311 | return StringRef("Unimplemented Debug Name"); | |||
| 1312 | ||||
| 1313 | if (Entry32) { | |||
| 1314 | if (Entry32->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) | |||
| 1315 | return generateXCOFFFixedNameStringRef(Entry32->SymbolName); | |||
| 1316 | ||||
| 1317 | return OwningObjectPtr->getStringTableEntry(Entry32->NameInStrTbl.Offset); | |||
| 1318 | } | |||
| 1319 | ||||
| 1320 | return OwningObjectPtr->getStringTableEntry(Entry64->Offset); | |||
| 1321 | } | |||
| 1322 | ||||
| 1323 | // Explictly instantiate template classes. | |||
| 1324 | template struct XCOFFSectionHeader<XCOFFSectionHeader32>; | |||
| 1325 | template struct XCOFFSectionHeader<XCOFFSectionHeader64>; | |||
| 1326 | ||||
| 1327 | template struct XCOFFRelocation<llvm::support::ubig32_t>; | |||
| 1328 | template struct XCOFFRelocation<llvm::support::ubig64_t>; | |||
| 1329 | ||||
| 1330 | template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation64>> | |||
| 1331 | llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader64, | |||
| 1332 | llvm::object::XCOFFRelocation64>( | |||
| 1333 | llvm::object::XCOFFSectionHeader64 const &) const; | |||
| 1334 | template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation32>> | |||
| 1335 | llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader32, | |||
| 1336 | llvm::object::XCOFFRelocation32>( | |||
| 1337 | llvm::object::XCOFFSectionHeader32 const &) const; | |||
| 1338 | ||||
| 1339 | bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) { | |||
| 1340 | if (Bytes.size() < 4) | |||
| 1341 | return false; | |||
| 1342 | ||||
| 1343 | return support::endian::read32be(Bytes.data()) == 0; | |||
| 1344 | } | |||
| 1345 | ||||
| 1346 | #define GETVALUEWITHMASK(X) (Data & (TracebackTable::X)) | |||
| 1347 | #define GETVALUEWITHMASKSHIFT(X, S) \ | |||
| 1348 | ((Data & (TracebackTable::X)) >> (TracebackTable::S)) | |||
| 1349 | ||||
| 1350 | Expected<TBVectorExt> TBVectorExt::create(StringRef TBvectorStrRef) { | |||
| 1351 | Error Err = Error::success(); | |||
| 1352 | TBVectorExt TBTVecExt(TBvectorStrRef, Err); | |||
| 1353 | if (Err) | |||
| 1354 | return std::move(Err); | |||
| 1355 | return TBTVecExt; | |||
| 1356 | } | |||
| 1357 | ||||
| 1358 | TBVectorExt::TBVectorExt(StringRef TBvectorStrRef, Error &Err) { | |||
| 1359 | const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data()); | |||
| 1360 | Data = support::endian::read16be(Ptr); | |||
| 1361 | uint32_t VecParmsTypeValue = support::endian::read32be(Ptr + 2); | |||
| 1362 | unsigned ParmsNum = | |||
| 1363 | GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift); | |||
| 1364 | ||||
| 1365 | ErrorAsOutParameter EAO(&Err); | |||
| 1366 | Expected<SmallString<32>> VecParmsTypeOrError = | |||
| 1367 | parseVectorParmsType(VecParmsTypeValue, ParmsNum); | |||
| 1368 | if (!VecParmsTypeOrError) | |||
| 1369 | Err = VecParmsTypeOrError.takeError(); | |||
| 1370 | else | |||
| 1371 | VecParmsInfo = VecParmsTypeOrError.get(); | |||
| 1372 | } | |||
| 1373 | ||||
| 1374 | uint8_t TBVectorExt::getNumberOfVRSaved() const { | |||
| 1375 | return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift); | |||
| 1376 | } | |||
| 1377 | ||||
| 1378 | bool TBVectorExt::isVRSavedOnStack() const { | |||
| 1379 | return GETVALUEWITHMASK(IsVRSavedOnStackMask); | |||
| 1380 | } | |||
| 1381 | ||||
| 1382 | bool TBVectorExt::hasVarArgs() const { | |||
| 1383 | return GETVALUEWITHMASK(HasVarArgsMask); | |||
| 1384 | } | |||
| 1385 | ||||
| 1386 | uint8_t TBVectorExt::getNumberOfVectorParms() const { | |||
| 1387 | return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, | |||
| 1388 | NumberOfVectorParmsShift); | |||
| 1389 | } | |||
| 1390 | ||||
| 1391 | bool TBVectorExt::hasVMXInstruction() const { | |||
| 1392 | return GETVALUEWITHMASK(HasVMXInstructionMask); | |||
| 1393 | } | |||
| 1394 | #undef GETVALUEWITHMASK | |||
| 1395 | #undef GETVALUEWITHMASKSHIFT | |||
| 1396 | ||||
| 1397 | Expected<XCOFFTracebackTable> XCOFFTracebackTable::create(const uint8_t *Ptr, | |||
| 1398 | uint64_t &Size) { | |||
| 1399 | Error Err = Error::success(); | |||
| 1400 | XCOFFTracebackTable TBT(Ptr, Size, Err); | |||
| 1401 | if (Err) | |||
| 1402 | return std::move(Err); | |||
| 1403 | return TBT; | |||
| 1404 | } | |||
| 1405 | ||||
| 1406 | XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, | |||
| 1407 | Error &Err) | |||
| 1408 | : TBPtr(Ptr) { | |||
| 1409 | ErrorAsOutParameter EAO(&Err); | |||
| 1410 | DataExtractor DE(ArrayRef<uint8_t>(Ptr, Size), /*IsLittleEndian=*/false, | |||
| 1411 | /*AddressSize=*/0); | |||
| 1412 | DataExtractor::Cursor Cur(/*Offset=*/0); | |||
| 1413 | ||||
| 1414 | // Skip 8 bytes of mandatory fields. | |||
| 1415 | DE.getU64(Cur); | |||
| 1416 | ||||
| 1417 | unsigned FixedParmsNum = getNumberOfFixedParms(); | |||
| 1418 | unsigned FloatingParmsNum = getNumberOfFPParms(); | |||
| 1419 | uint32_t ParamsTypeValue = 0; | |||
| 1420 | ||||
| 1421 | // Begin to parse optional fields. | |||
| 1422 | if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) | |||
| 1423 | ParamsTypeValue = DE.getU32(Cur); | |||
| 1424 | ||||
| 1425 | if (Cur && hasTraceBackTableOffset()) | |||
| 1426 | TraceBackTableOffset = DE.getU32(Cur); | |||
| 1427 | ||||
| 1428 | if (Cur && isInterruptHandler()) | |||
| 1429 | HandlerMask = DE.getU32(Cur); | |||
| 1430 | ||||
| 1431 | if (Cur && hasControlledStorage()) { | |||
| 1432 | NumOfCtlAnchors = DE.getU32(Cur); | |||
| 1433 | if (Cur && NumOfCtlAnchors) { | |||
| 1434 | SmallVector<uint32_t, 8> Disp; | |||
| 1435 | Disp.reserve(*NumOfCtlAnchors); | |||
| 1436 | for (uint32_t I = 0; I < NumOfCtlAnchors && Cur; ++I) | |||
| 1437 | Disp.push_back(DE.getU32(Cur)); | |||
| 1438 | if (Cur) | |||
| 1439 | ControlledStorageInfoDisp = std::move(Disp); | |||
| 1440 | } | |||
| 1441 | } | |||
| 1442 | ||||
| 1443 | if (Cur && isFuncNamePresent()) { | |||
| 1444 | uint16_t FunctionNameLen = DE.getU16(Cur); | |||
| 1445 | if (Cur) | |||
| 1446 | FunctionName = DE.getBytes(Cur, FunctionNameLen); | |||
| 1447 | } | |||
| 1448 | ||||
| 1449 | if (Cur && isAllocaUsed()) | |||
| 1450 | AllocaRegister = DE.getU8(Cur); | |||
| 1451 | ||||
| 1452 | unsigned VectorParmsNum = 0; | |||
| 1453 | if (Cur && hasVectorInfo()) { | |||
| 1454 | StringRef VectorExtRef = DE.getBytes(Cur, 6); | |||
| 1455 | if (Cur) { | |||
| 1456 | Expected<TBVectorExt> TBVecExtOrErr = TBVectorExt::create(VectorExtRef); | |||
| 1457 | if (!TBVecExtOrErr) { | |||
| 1458 | Err = TBVecExtOrErr.takeError(); | |||
| 1459 | return; | |||
| 1460 | } | |||
| 1461 | VecExt = TBVecExtOrErr.get(); | |||
| 1462 | VectorParmsNum = VecExt->getNumberOfVectorParms(); | |||
| 1463 | } | |||
| 1464 | } | |||
| 1465 | ||||
| 1466 | // As long as there is no fixed-point or floating-point parameter, this | |||
| 1467 | // field remains not present even when hasVectorInfo gives true and | |||
| 1468 | // indicates the presence of vector parameters. | |||
| 1469 | if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) { | |||
| 1470 | Expected<SmallString<32>> ParmsTypeOrError = | |||
| 1471 | hasVectorInfo() | |||
| 1472 | ? parseParmsTypeWithVecInfo(ParamsTypeValue, FixedParmsNum, | |||
| 1473 | FloatingParmsNum, VectorParmsNum) | |||
| 1474 | : parseParmsType(ParamsTypeValue, FixedParmsNum, FloatingParmsNum); | |||
| 1475 | ||||
| 1476 | if (!ParmsTypeOrError) { | |||
| 1477 | Err = ParmsTypeOrError.takeError(); | |||
| 1478 | return; | |||
| 1479 | } | |||
| 1480 | ParmsType = ParmsTypeOrError.get(); | |||
| 1481 | } | |||
| 1482 | ||||
| 1483 | if (Cur && hasExtensionTable()) | |||
| 1484 | ExtensionTable = DE.getU8(Cur); | |||
| 1485 | ||||
| 1486 | if (!Cur) | |||
| 1487 | Err = Cur.takeError(); | |||
| 1488 | ||||
| 1489 | Size = Cur.tell(); | |||
| 1490 | } | |||
| 1491 | ||||
| 1492 | #define GETBITWITHMASK(P, X) \ | |||
| 1493 | (support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) | |||
| 1494 | #define GETBITWITHMASKSHIFT(P, X, S) \ | |||
| 1495 | ((support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) >> \ | |||
| 1496 | (TracebackTable::S)) | |||
| 1497 | ||||
| 1498 | uint8_t XCOFFTracebackTable::getVersion() const { | |||
| 1499 | return GETBITWITHMASKSHIFT(0, VersionMask, VersionShift); | |||
| 1500 | } | |||
| 1501 | ||||
| 1502 | uint8_t XCOFFTracebackTable::getLanguageID() const { | |||
| 1503 | return GETBITWITHMASKSHIFT(0, LanguageIdMask, LanguageIdShift); | |||
| 1504 | } | |||
| 1505 | ||||
| 1506 | bool XCOFFTracebackTable::isGlobalLinkage() const { | |||
| 1507 | return GETBITWITHMASK(0, IsGlobaLinkageMask); | |||
| 1508 | } | |||
| 1509 | ||||
| 1510 | bool XCOFFTracebackTable::isOutOfLineEpilogOrPrologue() const { | |||
| 1511 | return GETBITWITHMASK(0, IsOutOfLineEpilogOrPrologueMask); | |||
| 1512 | } | |||
| 1513 | ||||
| 1514 | bool XCOFFTracebackTable::hasTraceBackTableOffset() const { | |||
| 1515 | return GETBITWITHMASK(0, HasTraceBackTableOffsetMask); | |||
| 1516 | } | |||
| 1517 | ||||
| 1518 | bool XCOFFTracebackTable::isInternalProcedure() const { | |||
| 1519 | return GETBITWITHMASK(0, IsInternalProcedureMask); | |||
| 1520 | } | |||
| 1521 | ||||
| 1522 | bool XCOFFTracebackTable::hasControlledStorage() const { | |||
| 1523 | return GETBITWITHMASK(0, HasControlledStorageMask); | |||
| 1524 | } | |||
| 1525 | ||||
| 1526 | bool XCOFFTracebackTable::isTOCless() const { | |||
| 1527 | return GETBITWITHMASK(0, IsTOClessMask); | |||
| 1528 | } | |||
| 1529 | ||||
| 1530 | bool XCOFFTracebackTable::isFloatingPointPresent() const { | |||
| 1531 | return GETBITWITHMASK(0, IsFloatingPointPresentMask); | |||
| 1532 | } | |||
| 1533 | ||||
| 1534 | bool XCOFFTracebackTable::isFloatingPointOperationLogOrAbortEnabled() const { | |||
| 1535 | return GETBITWITHMASK(0, IsFloatingPointOperationLogOrAbortEnabledMask); | |||
| 1536 | } | |||
| 1537 | ||||
| 1538 | bool XCOFFTracebackTable::isInterruptHandler() const { | |||
| 1539 | return GETBITWITHMASK(0, IsInterruptHandlerMask); | |||
| 1540 | } | |||
| 1541 | ||||
| 1542 | bool XCOFFTracebackTable::isFuncNamePresent() const { | |||
| 1543 | return GETBITWITHMASK(0, IsFunctionNamePresentMask); | |||
| 1544 | } | |||
| 1545 | ||||
| 1546 | bool XCOFFTracebackTable::isAllocaUsed() const { | |||
| 1547 | return GETBITWITHMASK(0, IsAllocaUsedMask); | |||
| 1548 | } | |||
| 1549 | ||||
| 1550 | uint8_t XCOFFTracebackTable::getOnConditionDirective() const { | |||
| 1551 | return GETBITWITHMASKSHIFT(0, OnConditionDirectiveMask, | |||
| 1552 | OnConditionDirectiveShift); | |||
| 1553 | } | |||
| 1554 | ||||
| 1555 | bool XCOFFTracebackTable::isCRSaved() const { | |||
| 1556 | return GETBITWITHMASK(0, IsCRSavedMask); | |||
| 1557 | } | |||
| 1558 | ||||
| 1559 | bool XCOFFTracebackTable::isLRSaved() const { | |||
| 1560 | return GETBITWITHMASK(0, IsLRSavedMask); | |||
| 1561 | } | |||
| 1562 | ||||
| 1563 | bool XCOFFTracebackTable::isBackChainStored() const { | |||
| 1564 | return GETBITWITHMASK(4, IsBackChainStoredMask); | |||
| 1565 | } | |||
| 1566 | ||||
| 1567 | bool XCOFFTracebackTable::isFixup() const { | |||
| 1568 | return GETBITWITHMASK(4, IsFixupMask); | |||
| 1569 | } | |||
| 1570 | ||||
| 1571 | uint8_t XCOFFTracebackTable::getNumOfFPRsSaved() const { | |||
| 1572 | return GETBITWITHMASKSHIFT(4, FPRSavedMask, FPRSavedShift); | |||
| 1573 | } | |||
| 1574 | ||||
| 1575 | bool XCOFFTracebackTable::hasExtensionTable() const { | |||
| 1576 | return GETBITWITHMASK(4, HasExtensionTableMask); | |||
| 1577 | } | |||
| 1578 | ||||
| 1579 | bool XCOFFTracebackTable::hasVectorInfo() const { | |||
| 1580 | return GETBITWITHMASK(4, HasVectorInfoMask); | |||
| 1581 | } | |||
| 1582 | ||||
| 1583 | uint8_t XCOFFTracebackTable::getNumOfGPRsSaved() const { | |||
| 1584 | return GETBITWITHMASKSHIFT(4, GPRSavedMask, GPRSavedShift); | |||
| 1585 | } | |||
| 1586 | ||||
| 1587 | uint8_t XCOFFTracebackTable::getNumberOfFixedParms() const { | |||
| 1588 | return GETBITWITHMASKSHIFT(4, NumberOfFixedParmsMask, | |||
| 1589 | NumberOfFixedParmsShift); | |||
| 1590 | } | |||
| 1591 | ||||
| 1592 | uint8_t XCOFFTracebackTable::getNumberOfFPParms() const { | |||
| 1593 | return GETBITWITHMASKSHIFT(4, NumberOfFloatingPointParmsMask, | |||
| 1594 | NumberOfFloatingPointParmsShift); | |||
| 1595 | } | |||
| 1596 | ||||
| 1597 | bool XCOFFTracebackTable::hasParmsOnStack() const { | |||
| 1598 | return GETBITWITHMASK(4, HasParmsOnStackMask); | |||
| 1599 | } | |||
| 1600 | ||||
| 1601 | #undef GETBITWITHMASK | |||
| 1602 | #undef GETBITWITHMASKSHIFT | |||
| 1603 | } // namespace object | |||
| 1604 | } // namespace llvm |
| 1 | //===- XCOFFObjectFile.h - XCOFF 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 XCOFFObjectFile class. | |||
| 10 | // | |||
| 11 | //===----------------------------------------------------------------------===// | |||
| 12 | ||||
| 13 | #ifndef LLVM_OBJECT_XCOFFOBJECTFILE_H | |||
| 14 | #define LLVM_OBJECT_XCOFFOBJECTFILE_H | |||
| 15 | ||||
| 16 | #include "llvm/ADT/SmallString.h" | |||
| 17 | #include "llvm/ADT/SmallVector.h" | |||
| 18 | #include "llvm/BinaryFormat/XCOFF.h" | |||
| 19 | #include "llvm/Object/ObjectFile.h" | |||
| 20 | #include "llvm/Support/Endian.h" | |||
| 21 | #include <limits> | |||
| 22 | ||||
| 23 | namespace llvm { | |||
| 24 | namespace object { | |||
| 25 | ||||
| 26 | struct XCOFFFileHeader32 { | |||
| 27 | support::ubig16_t Magic; | |||
| 28 | support::ubig16_t NumberOfSections; | |||
| 29 | ||||
| 30 | // Unix time value, value of 0 indicates no timestamp. | |||
| 31 | // Negative values are reserved. | |||
| 32 | support::big32_t TimeStamp; | |||
| 33 | ||||
| 34 | support::ubig32_t SymbolTableOffset; // File offset to symbol table. | |||
| 35 | support::big32_t NumberOfSymTableEntries; | |||
| 36 | support::ubig16_t AuxHeaderSize; | |||
| 37 | support::ubig16_t Flags; | |||
| 38 | }; | |||
| 39 | ||||
| 40 | struct XCOFFFileHeader64 { | |||
| 41 | support::ubig16_t Magic; | |||
| 42 | support::ubig16_t NumberOfSections; | |||
| 43 | ||||
| 44 | // Unix time value, value of 0 indicates no timestamp. | |||
| 45 | // Negative values are reserved. | |||
| 46 | support::big32_t TimeStamp; | |||
| 47 | ||||
| 48 | support::ubig64_t SymbolTableOffset; // File offset to symbol table. | |||
| 49 | support::ubig16_t AuxHeaderSize; | |||
| 50 | support::ubig16_t Flags; | |||
| 51 | support::ubig32_t NumberOfSymTableEntries; | |||
| 52 | }; | |||
| 53 | ||||
| 54 | template <typename T> struct XCOFFAuxiliaryHeader { | |||
| 55 | static constexpr uint8_t AuxiHeaderFlagMask = 0xF0; | |||
| 56 | static constexpr uint8_t AuxiHeaderTDataAlignmentMask = 0x0F; | |||
| 57 | ||||
| 58 | public: | |||
| 59 | uint8_t getFlag() const { | |||
| 60 | return static_cast<const T *>(this)->FlagAndTDataAlignment & | |||
| 61 | AuxiHeaderFlagMask; | |||
| 62 | } | |||
| 63 | ||||
| 64 | uint8_t getTDataAlignment() const { | |||
| 65 | return static_cast<const T *>(this)->FlagAndTDataAlignment & | |||
| 66 | AuxiHeaderTDataAlignmentMask; | |||
| 67 | } | |||
| 68 | ||||
| 69 | uint16_t getVersion() const { return static_cast<const T *>(this)->Version; } | |||
| 70 | }; | |||
| 71 | ||||
| 72 | struct XCOFFAuxiliaryHeader32 : XCOFFAuxiliaryHeader<XCOFFAuxiliaryHeader32> { | |||
| 73 | support::ubig16_t | |||
| 74 | AuxMagic; ///< If the value of the o_vstamp field is greater than 1, the | |||
| 75 | ///< o_mflags field is reserved for future use and it should | |||
| 76 | ///< contain 0. Otherwise, this field is not used. | |||
| 77 | support::ubig16_t | |||
| 78 | Version; ///< The valid values are 1 and 2. When the o_vstamp field is 2 | |||
| 79 | ///< in an XCOFF32 file, the new interpretation of the n_type | |||
| 80 | ///< field in the symbol table entry is used. | |||
| 81 | support::ubig32_t TextSize; | |||
| 82 | support::ubig32_t InitDataSize; | |||
| 83 | support::ubig32_t BssDataSize; | |||
| 84 | support::ubig32_t EntryPointAddr; | |||
| 85 | support::ubig32_t TextStartAddr; | |||
| 86 | support::ubig32_t DataStartAddr; | |||
| 87 | support::ubig32_t TOCAnchorAddr; | |||
| 88 | support::ubig16_t SecNumOfEntryPoint; | |||
| 89 | support::ubig16_t SecNumOfText; | |||
| 90 | support::ubig16_t SecNumOfData; | |||
| 91 | support::ubig16_t SecNumOfTOC; | |||
| 92 | support::ubig16_t SecNumOfLoader; | |||
| 93 | support::ubig16_t SecNumOfBSS; | |||
| 94 | support::ubig16_t MaxAlignOfText; | |||
| 95 | support::ubig16_t MaxAlignOfData; | |||
| 96 | support::ubig16_t ModuleType; | |||
| 97 | uint8_t CpuFlag; | |||
| 98 | uint8_t CpuType; | |||
| 99 | support::ubig32_t MaxStackSize; ///< If the value is 0, the system default | |||
| 100 | ///< maximum stack size is used. | |||
| 101 | support::ubig32_t MaxDataSize; ///< If the value is 0, the system default | |||
| 102 | ///< maximum data size is used. | |||
| 103 | support::ubig32_t | |||
| 104 | ReservedForDebugger; ///< This field should contain 0. When a loaded | |||
| 105 | ///< program is being debugged, the memory image of | |||
| 106 | ///< this field may be modified by a debugger to | |||
| 107 | ///< insert a trap instruction. | |||
| 108 | uint8_t TextPageSize; ///< Specifies the size of pages for the exec text. The | |||
| 109 | ///< default value is 0 (system-selected page size). | |||
| 110 | uint8_t DataPageSize; ///< Specifies the size of pages for the exec data. The | |||
| 111 | ///< default value is 0 (system-selected page size). | |||
| 112 | uint8_t StackPageSize; ///< Specifies the size of pages for the stack. The | |||
| 113 | ///< default value is 0 (system-selected page size). | |||
| 114 | uint8_t FlagAndTDataAlignment; | |||
| 115 | support::ubig16_t SecNumOfTData; | |||
| 116 | support::ubig16_t SecNumOfTBSS; | |||
| 117 | }; | |||
| 118 | ||||
| 119 | struct XCOFFAuxiliaryHeader64 : XCOFFAuxiliaryHeader<XCOFFAuxiliaryHeader64> { | |||
| 120 | support::ubig16_t AuxMagic; | |||
| 121 | support::ubig16_t Version; | |||
| 122 | support::ubig32_t ReservedForDebugger; | |||
| 123 | support::ubig64_t TextStartAddr; | |||
| 124 | support::ubig64_t DataStartAddr; | |||
| 125 | support::ubig64_t TOCAnchorAddr; | |||
| 126 | support::ubig16_t SecNumOfEntryPoint; | |||
| 127 | support::ubig16_t SecNumOfText; | |||
| 128 | support::ubig16_t SecNumOfData; | |||
| 129 | support::ubig16_t SecNumOfTOC; | |||
| 130 | support::ubig16_t SecNumOfLoader; | |||
| 131 | support::ubig16_t SecNumOfBSS; | |||
| 132 | support::ubig16_t MaxAlignOfText; | |||
| 133 | support::ubig16_t MaxAlignOfData; | |||
| 134 | support::ubig16_t ModuleType; | |||
| 135 | uint8_t CpuFlag; | |||
| 136 | uint8_t CpuType; | |||
| 137 | uint8_t TextPageSize; | |||
| 138 | uint8_t DataPageSize; | |||
| 139 | uint8_t StackPageSize; | |||
| 140 | uint8_t FlagAndTDataAlignment; | |||
| 141 | support::ubig64_t TextSize; | |||
| 142 | support::ubig64_t InitDataSize; | |||
| 143 | support::ubig64_t BssDataSize; | |||
| 144 | support::ubig64_t EntryPointAddr; | |||
| 145 | support::ubig64_t MaxStackSize; | |||
| 146 | support::ubig64_t MaxDataSize; | |||
| 147 | support::ubig16_t SecNumOfTData; | |||
| 148 | support::ubig16_t SecNumOfTBSS; | |||
| 149 | support::ubig16_t XCOFF64Flag; | |||
| 150 | }; | |||
| 151 | ||||
| 152 | template <typename T> struct XCOFFSectionHeader { | |||
| 153 | // Least significant 3 bits are reserved. | |||
| 154 | static constexpr unsigned SectionFlagsReservedMask = 0x7; | |||
| 155 | ||||
| 156 | // The low order 16 bits of section flags denotes the section type. | |||
| 157 | static constexpr unsigned SectionFlagsTypeMask = 0xffffu; | |||
| 158 | ||||
| 159 | public: | |||
| 160 | StringRef getName() const; | |||
| 161 | uint16_t getSectionType() const; | |||
| 162 | bool isReservedSectionType() const; | |||
| 163 | }; | |||
| 164 | ||||
| 165 | // Explicit extern template declarations. | |||
| 166 | struct XCOFFSectionHeader32; | |||
| 167 | struct XCOFFSectionHeader64; | |||
| 168 | extern template struct XCOFFSectionHeader<XCOFFSectionHeader32>; | |||
| 169 | extern template struct XCOFFSectionHeader<XCOFFSectionHeader64>; | |||
| 170 | ||||
| 171 | struct XCOFFSectionHeader32 : XCOFFSectionHeader<XCOFFSectionHeader32> { | |||
| 172 | char Name[XCOFF::NameSize]; | |||
| 173 | support::ubig32_t PhysicalAddress; | |||
| 174 | support::ubig32_t VirtualAddress; | |||
| 175 | support::ubig32_t SectionSize; | |||
| 176 | support::ubig32_t FileOffsetToRawData; | |||
| 177 | support::ubig32_t FileOffsetToRelocationInfo; | |||
| 178 | support::ubig32_t FileOffsetToLineNumberInfo; | |||
| 179 | support::ubig16_t NumberOfRelocations; | |||
| 180 | support::ubig16_t NumberOfLineNumbers; | |||
| 181 | support::big32_t Flags; | |||
| 182 | }; | |||
| 183 | ||||
| 184 | struct XCOFFSectionHeader64 : XCOFFSectionHeader<XCOFFSectionHeader64> { | |||
| 185 | char Name[XCOFF::NameSize]; | |||
| 186 | support::ubig64_t PhysicalAddress; | |||
| 187 | support::ubig64_t VirtualAddress; | |||
| 188 | support::ubig64_t SectionSize; | |||
| 189 | support::big64_t FileOffsetToRawData; | |||
| 190 | support::big64_t FileOffsetToRelocationInfo; | |||
| 191 | support::big64_t FileOffsetToLineNumberInfo; | |||
| 192 | support::ubig32_t NumberOfRelocations; | |||
| 193 | support::ubig32_t NumberOfLineNumbers; | |||
| 194 | support::big32_t Flags; | |||
| 195 | char Padding[4]; | |||
| 196 | }; | |||
| 197 | ||||
| 198 | struct LoaderSectionHeader32; | |||
| 199 | struct LoaderSectionHeader64; | |||
| 200 | struct LoaderSectionSymbolEntry32 { | |||
| 201 | struct NameOffsetInStrTbl { | |||
| 202 | support::big32_t IsNameInStrTbl; // Zero indicates name in string table. | |||
| 203 | support::ubig32_t Offset; | |||
| 204 | }; | |||
| 205 | ||||
| 206 | char SymbolName[XCOFF::NameSize]; | |||
| 207 | support::ubig32_t Value; // The virtual address of the symbol. | |||
| 208 | support::big16_t SectionNumber; | |||
| 209 | uint8_t SymbolType; | |||
| 210 | XCOFF::StorageClass StorageClass; | |||
| 211 | support::ubig32_t ImportFileID; | |||
| 212 | support::ubig32_t ParameterTypeCheck; | |||
| 213 | ||||
| 214 | Expected<StringRef> | |||
| 215 | getSymbolName(const LoaderSectionHeader32 *LoaderSecHeader) const; | |||
| 216 | }; | |||
| 217 | ||||
| 218 | struct LoaderSectionSymbolEntry64 { | |||
| 219 | support::ubig64_t Value; // The virtual address of the symbol. | |||
| 220 | support::ubig32_t Offset; | |||
| 221 | support::big16_t SectionNumber; | |||
| 222 | uint8_t SymbolType; | |||
| 223 | XCOFF::StorageClass StorageClass; | |||
| 224 | support::ubig32_t ImportFileID; | |||
| 225 | support::ubig32_t ParameterTypeCheck; | |||
| 226 | ||||
| 227 | Expected<StringRef> | |||
| 228 | getSymbolName(const LoaderSectionHeader64 *LoaderSecHeader) const; | |||
| 229 | }; | |||
| 230 | ||||
| 231 | struct LoaderSectionRelocationEntry32 { | |||
| 232 | support::ubig32_t VirtualAddr; | |||
| 233 | support::big32_t SymbolIndex; | |||
| 234 | support::ubig16_t Type; | |||
| 235 | support::big16_t SectionNum; | |||
| 236 | }; | |||
| 237 | ||||
| 238 | struct LoaderSectionRelocationEntry64 { | |||
| 239 | support::ubig64_t VirtualAddr; | |||
| 240 | support::ubig16_t Type; | |||
| 241 | support::big16_t SectionNum; | |||
| 242 | support::big32_t SymbolIndex; | |||
| 243 | }; | |||
| 244 | ||||
| 245 | struct LoaderSectionHeader32 { | |||
| 246 | support::ubig32_t Version; | |||
| 247 | support::ubig32_t NumberOfSymTabEnt; | |||
| 248 | support::ubig32_t NumberOfRelTabEnt; | |||
| 249 | support::ubig32_t LengthOfImpidStrTbl; | |||
| 250 | support::ubig32_t NumberOfImpid; | |||
| 251 | support::big32_t OffsetToImpid; | |||
| 252 | support::ubig32_t LengthOfStrTbl; | |||
| 253 | support::big32_t OffsetToStrTbl; | |||
| 254 | ||||
| 255 | uint64_t getOffsetToSymTbl() const { | |||
| 256 | return NumberOfSymTabEnt == 0 ? 0 : sizeof(LoaderSectionHeader32); | |||
| 257 | } | |||
| 258 | ||||
| 259 | uint64_t getOffsetToRelEnt() const { | |||
| 260 | // Relocation table is after Symbol table. | |||
| 261 | return NumberOfRelTabEnt == 0 | |||
| 262 | ? 0 | |||
| 263 | : sizeof(LoaderSectionHeader32) + | |||
| 264 | sizeof(LoaderSectionSymbolEntry32) * NumberOfSymTabEnt; | |||
| 265 | } | |||
| 266 | }; | |||
| 267 | ||||
| 268 | struct LoaderSectionHeader64 { | |||
| 269 | support::ubig32_t Version; | |||
| 270 | support::ubig32_t NumberOfSymTabEnt; | |||
| 271 | support::ubig32_t NumberOfRelTabEnt; | |||
| 272 | support::ubig32_t LengthOfImpidStrTbl; | |||
| 273 | support::ubig32_t NumberOfImpid; | |||
| 274 | support::ubig32_t LengthOfStrTbl; | |||
| 275 | support::big64_t OffsetToImpid; | |||
| 276 | support::big64_t OffsetToStrTbl; | |||
| 277 | support::big64_t OffsetToSymTbl; | |||
| 278 | support::big64_t OffsetToRelEnt; | |||
| 279 | ||||
| 280 | uint64_t getOffsetToSymTbl() const { return OffsetToSymTbl; } | |||
| 281 | uint64_t getOffsetToRelEnt() const { return OffsetToRelEnt; } | |||
| 282 | }; | |||
| 283 | ||||
| 284 | template <typename AddressType> struct ExceptionSectionEntry { | |||
| 285 | union { | |||
| 286 | support::ubig32_t SymbolIdx; | |||
| 287 | AddressType TrapInstAddr; | |||
| 288 | }; | |||
| 289 | uint8_t LangId; | |||
| 290 | uint8_t Reason; | |||
| 291 | ||||
| 292 | uint32_t getSymbolIndex() const { | |||
| 293 | assert(Reason == 0 && "Get symbol table index of the function only when "(static_cast <bool> (Reason == 0 && "Get symbol table index of the function only when " "the e_reason field is 0.") ? void (0) : __assert_fail ("Reason == 0 && \"Get symbol table index of the function only when \" \"the e_reason field is 0.\"" , "llvm/include/llvm/Object/XCOFFObjectFile.h", 294, __extension__ __PRETTY_FUNCTION__)) | |||
| 294 | "the e_reason field is 0.")(static_cast <bool> (Reason == 0 && "Get symbol table index of the function only when " "the e_reason field is 0.") ? void (0) : __assert_fail ("Reason == 0 && \"Get symbol table index of the function only when \" \"the e_reason field is 0.\"" , "llvm/include/llvm/Object/XCOFFObjectFile.h", 294, __extension__ __PRETTY_FUNCTION__)); | |||
| 295 | return SymbolIdx; | |||
| 296 | } | |||
| 297 | ||||
| 298 | uint64_t getTrapInstAddr() const { | |||
| 299 | assert(Reason != 0 && "Zero is not a valid trap exception reason code.")(static_cast <bool> (Reason != 0 && "Zero is not a valid trap exception reason code." ) ? void (0) : __assert_fail ("Reason != 0 && \"Zero is not a valid trap exception reason code.\"" , "llvm/include/llvm/Object/XCOFFObjectFile.h", 299, __extension__ __PRETTY_FUNCTION__)); | |||
| 300 | return TrapInstAddr; | |||
| 301 | } | |||
| 302 | uint8_t getLangID() const { return LangId; } | |||
| 303 | uint8_t getReason() const { return Reason; } | |||
| 304 | }; | |||
| 305 | ||||
| 306 | typedef ExceptionSectionEntry<support::ubig32_t> ExceptionSectionEntry32; | |||
| 307 | typedef ExceptionSectionEntry<support::ubig64_t> ExceptionSectionEntry64; | |||
| 308 | ||||
| 309 | // Explicit extern template declarations. | |||
| 310 | extern template struct ExceptionSectionEntry<support::ubig32_t>; | |||
| 311 | extern template struct ExceptionSectionEntry<support::ubig64_t>; | |||
| 312 | ||||
| 313 | struct XCOFFStringTable { | |||
| 314 | uint32_t Size; | |||
| 315 | const char *Data; | |||
| 316 | }; | |||
| 317 | ||||
| 318 | struct XCOFFCsectAuxEnt32 { | |||
| 319 | support::ubig32_t SectionOrLength; | |||
| 320 | support::ubig32_t ParameterHashIndex; | |||
| 321 | support::ubig16_t TypeChkSectNum; | |||
| 322 | uint8_t SymbolAlignmentAndType; | |||
| 323 | XCOFF::StorageMappingClass StorageMappingClass; | |||
| 324 | support::ubig32_t StabInfoIndex; | |||
| 325 | support::ubig16_t StabSectNum; | |||
| 326 | }; | |||
| 327 | ||||
| 328 | struct XCOFFCsectAuxEnt64 { | |||
| 329 | support::ubig32_t SectionOrLengthLowByte; | |||
| 330 | support::ubig32_t ParameterHashIndex; | |||
| 331 | support::ubig16_t TypeChkSectNum; | |||
| 332 | uint8_t SymbolAlignmentAndType; | |||
| 333 | XCOFF::StorageMappingClass StorageMappingClass; | |||
| 334 | support::ubig32_t SectionOrLengthHighByte; | |||
| 335 | uint8_t Pad; | |||
| 336 | XCOFF::SymbolAuxType AuxType; | |||
| 337 | }; | |||
| 338 | ||||
| 339 | class XCOFFCsectAuxRef { | |||
| 340 | public: | |||
| 341 | static constexpr uint8_t SymbolTypeMask = 0x07; | |||
| 342 | static constexpr uint8_t SymbolAlignmentMask = 0xF8; | |||
| 343 | static constexpr size_t SymbolAlignmentBitOffset = 3; | |||
| 344 | ||||
| 345 | XCOFFCsectAuxRef(const XCOFFCsectAuxEnt32 *Entry32) : Entry32(Entry32) {} | |||
| 346 | XCOFFCsectAuxRef(const XCOFFCsectAuxEnt64 *Entry64) : Entry64(Entry64) {} | |||
| 347 | ||||
| 348 | // For getSectionOrLength(), | |||
| 349 | // If the symbol type is XTY_SD or XTY_CM, the csect length. | |||
| 350 | // If the symbol type is XTY_LD, the symbol table | |||
| 351 | // index of the containing csect. | |||
| 352 | // If the symbol type is XTY_ER, 0. | |||
| 353 | uint64_t getSectionOrLength() const { | |||
| 354 | return Entry32 ? getSectionOrLength32() : getSectionOrLength64(); | |||
| 355 | } | |||
| 356 | ||||
| 357 | uint32_t getSectionOrLength32() const { | |||
| 358 | assert(Entry32 && "32-bit interface called on 64-bit object file.")(static_cast <bool> (Entry32 && "32-bit interface called on 64-bit object file." ) ? void (0) : __assert_fail ("Entry32 && \"32-bit interface called on 64-bit object file.\"" , "llvm/include/llvm/Object/XCOFFObjectFile.h", 358, __extension__ __PRETTY_FUNCTION__)); | |||
| 359 | return Entry32->SectionOrLength; | |||
| 360 | } | |||
| 361 | ||||
| 362 | uint64_t getSectionOrLength64() const { | |||
| 363 | assert(Entry64 && "64-bit interface called on 32-bit object file.")(static_cast <bool> (Entry64 && "64-bit interface called on 32-bit object file." ) ? void (0) : __assert_fail ("Entry64 && \"64-bit interface called on 32-bit object file.\"" , "llvm/include/llvm/Object/XCOFFObjectFile.h", 363, __extension__ __PRETTY_FUNCTION__)); | |||
| 364 | return (static_cast<uint64_t>(Entry64->SectionOrLengthHighByte) << 32) | | |||
| 365 | Entry64->SectionOrLengthLowByte; | |||
| 366 | } | |||
| 367 | ||||
| 368 | #define GETVALUE(X) Entry32 ? Entry32->X : Entry64->X | |||
| 369 | ||||
| 370 | uint32_t getParameterHashIndex() const { | |||
| 371 | return GETVALUE(ParameterHashIndex); | |||
| 372 | } | |||
| 373 | ||||
| 374 | uint16_t getTypeChkSectNum() const { return GETVALUE(TypeChkSectNum); } | |||
| 375 | ||||
| 376 | XCOFF::StorageMappingClass getStorageMappingClass() const { | |||
| 377 | return GETVALUE(StorageMappingClass); | |||
| 378 | } | |||
| 379 | ||||
| 380 | uintptr_t getEntryAddress() const { | |||
| 381 | return Entry32 ? reinterpret_cast<uintptr_t>(Entry32) | |||
| 382 | : reinterpret_cast<uintptr_t>(Entry64); | |||
| 383 | } | |||
| 384 | ||||
| 385 | uint16_t getAlignmentLog2() const { | |||
| 386 | return (getSymbolAlignmentAndType() & SymbolAlignmentMask) >> | |||
| 387 | SymbolAlignmentBitOffset; | |||
| 388 | } | |||
| 389 | ||||
| 390 | uint8_t getSymbolType() const { | |||
| 391 | return getSymbolAlignmentAndType() & SymbolTypeMask; | |||
| 392 | } | |||
| 393 | ||||
| 394 | bool isLabel() const { return getSymbolType() == XCOFF::XTY_LD; } | |||
| 395 | ||||
| 396 | uint32_t getStabInfoIndex32() const { | |||
| 397 | assert(Entry32 && "32-bit interface called on 64-bit object file.")(static_cast <bool> (Entry32 && "32-bit interface called on 64-bit object file." ) ? void (0) : __assert_fail ("Entry32 && \"32-bit interface called on 64-bit object file.\"" , "llvm/include/llvm/Object/XCOFFObjectFile.h", 397, __extension__ __PRETTY_FUNCTION__)); | |||
| 398 | return Entry32->StabInfoIndex; | |||
| 399 | } | |||
| 400 | ||||
| 401 | uint16_t getStabSectNum32() const { | |||
| 402 | assert(Entry32 && "32-bit interface called on 64-bit object file.")(static_cast <bool> (Entry32 && "32-bit interface called on 64-bit object file." ) ? void (0) : __assert_fail ("Entry32 && \"32-bit interface called on 64-bit object file.\"" , "llvm/include/llvm/Object/XCOFFObjectFile.h", 402, __extension__ __PRETTY_FUNCTION__)); | |||
| 403 | return Entry32->StabSectNum; | |||
| 404 | } | |||
| 405 | ||||
| 406 | XCOFF::SymbolAuxType getAuxType64() const { | |||
| 407 | assert(Entry64 && "64-bit interface called on 32-bit object file.")(static_cast <bool> (Entry64 && "64-bit interface called on 32-bit object file." ) ? void (0) : __assert_fail ("Entry64 && \"64-bit interface called on 32-bit object file.\"" , "llvm/include/llvm/Object/XCOFFObjectFile.h", 407, __extension__ __PRETTY_FUNCTION__)); | |||
| 408 | return Entry64->AuxType; | |||
| 409 | } | |||
| 410 | ||||
| 411 | private: | |||
| 412 | uint8_t getSymbolAlignmentAndType() const { | |||
| 413 | return GETVALUE(SymbolAlignmentAndType); | |||
| 414 | } | |||
| 415 | ||||
| 416 | #undef GETVALUE | |||
| 417 | ||||
| 418 | const XCOFFCsectAuxEnt32 *Entry32 = nullptr; | |||
| 419 | const XCOFFCsectAuxEnt64 *Entry64 = nullptr; | |||
| 420 | }; | |||
| 421 | ||||
| 422 | struct XCOFFFileAuxEnt { | |||
| 423 | typedef struct { | |||
| 424 | support::big32_t Magic; // Zero indicates name in string table. | |||
| 425 | support::ubig32_t Offset; | |||
| 426 | char NamePad[XCOFF::FileNamePadSize]; | |||
| 427 | } NameInStrTblType; | |||
| 428 | union { | |||
| 429 | char Name[XCOFF::NameSize + XCOFF::FileNamePadSize]; | |||
| 430 | NameInStrTblType NameInStrTbl; | |||
| 431 | }; | |||
| 432 | XCOFF::CFileStringType Type; | |||
| 433 | uint8_t ReservedZeros[2]; | |||
| 434 | XCOFF::SymbolAuxType AuxType; // 64-bit XCOFF file only. | |||
| 435 | }; | |||
| 436 | ||||
| 437 | struct XCOFFSectAuxEntForStat { | |||
| 438 | support::ubig32_t SectionLength; | |||
| 439 | support::ubig16_t NumberOfRelocEnt; | |||
| 440 | support::ubig16_t NumberOfLineNum; | |||
| 441 | uint8_t Pad[10]; | |||
| 442 | }; // 32-bit XCOFF file only. | |||
| 443 | ||||
| 444 | struct XCOFFFunctionAuxEnt32 { | |||
| 445 | support::ubig32_t OffsetToExceptionTbl; | |||
| 446 | support::ubig32_t SizeOfFunction; | |||
| 447 | support::ubig32_t PtrToLineNum; | |||
| 448 | support::big32_t SymIdxOfNextBeyond; | |||
| 449 | uint8_t Pad[2]; | |||
| 450 | }; | |||
| 451 | ||||
| 452 | struct XCOFFFunctionAuxEnt64 { | |||
| 453 | support::ubig64_t PtrToLineNum; | |||
| 454 | support::ubig32_t SizeOfFunction; | |||
| 455 | support::big32_t SymIdxOfNextBeyond; | |||
| 456 | uint8_t Pad; | |||
| 457 | XCOFF::SymbolAuxType AuxType; // Contains _AUX_FCN; Type of auxiliary entry | |||
| 458 | }; | |||
| 459 | ||||
| 460 | struct XCOFFExceptionAuxEnt { | |||
| 461 | support::ubig64_t OffsetToExceptionTbl; | |||
| 462 | support::ubig32_t SizeOfFunction; | |||
| 463 | support::big32_t SymIdxOfNextBeyond; | |||
| 464 | uint8_t Pad; | |||
| 465 | XCOFF::SymbolAuxType AuxType; // Contains _AUX_EXCEPT; Type of auxiliary entry | |||
| 466 | }; | |||
| 467 | ||||
| 468 | struct XCOFFBlockAuxEnt32 { | |||
| 469 | uint8_t ReservedZeros1[2]; | |||
| 470 | support::ubig16_t LineNumHi; | |||
| 471 | support::ubig16_t LineNumLo; | |||
| 472 | uint8_t ReservedZeros2[12]; | |||
| 473 | }; | |||
| 474 | ||||
| 475 | struct XCOFFBlockAuxEnt64 { | |||
| 476 | support::ubig32_t LineNum; | |||
| 477 | uint8_t Pad[13]; | |||
| 478 | XCOFF::SymbolAuxType AuxType; // Contains _AUX_SYM; Type of auxiliary entry | |||
| 479 | }; | |||
| 480 | ||||
| 481 | struct XCOFFSectAuxEntForDWARF32 { | |||
| 482 | support::ubig32_t LengthOfSectionPortion; | |||
| 483 | uint8_t Pad1[4]; | |||
| 484 | support::ubig32_t NumberOfRelocEnt; | |||
| 485 | uint8_t Pad2[6]; | |||
| 486 | }; | |||
| 487 | ||||
| 488 | struct XCOFFSectAuxEntForDWARF64 { | |||
| 489 | support::ubig64_t LengthOfSectionPortion; | |||
| 490 | support::ubig64_t NumberOfRelocEnt; | |||
| 491 | uint8_t Pad; | |||
| 492 | XCOFF::SymbolAuxType AuxType; // Contains _AUX_SECT; Type of Auxillary entry | |||
| 493 | }; | |||
| 494 | ||||
| 495 | template <typename AddressType> struct XCOFFRelocation { | |||
| 496 | public: | |||
| 497 | AddressType VirtualAddress; | |||
| 498 | support::ubig32_t SymbolIndex; | |||
| 499 | ||||
| 500 | // Packed field, see XR_* masks for details of packing. | |||
| 501 | uint8_t Info; | |||
| 502 | ||||
| 503 | XCOFF::RelocationType Type; | |||
| 504 | ||||
| 505 | public: | |||
| 506 | bool isRelocationSigned() const; | |||
| 507 | bool isFixupIndicated() const; | |||
| 508 | ||||
| 509 | // Returns the number of bits being relocated. | |||
| 510 | uint8_t getRelocatedLength() const; | |||
| 511 | }; | |||
| 512 | ||||
| 513 | extern template struct XCOFFRelocation<llvm::support::ubig32_t>; | |||
| 514 | extern template struct XCOFFRelocation<llvm::support::ubig64_t>; | |||
| 515 | ||||
| 516 | struct XCOFFRelocation32 : XCOFFRelocation<llvm::support::ubig32_t> {}; | |||
| 517 | struct XCOFFRelocation64 : XCOFFRelocation<llvm::support::ubig64_t> {}; | |||
| 518 | ||||
| 519 | class XCOFFSymbolRef; | |||
| 520 | ||||
| 521 | class XCOFFObjectFile : public ObjectFile { | |||
| 522 | private: | |||
| 523 | const void *FileHeader = nullptr; | |||
| 524 | const void *AuxiliaryHeader = nullptr; | |||
| 525 | const void *SectionHeaderTable = nullptr; | |||
| 526 | ||||
| 527 | const void *SymbolTblPtr = nullptr; | |||
| 528 | XCOFFStringTable StringTable = {0, nullptr}; | |||
| 529 | ||||
| 530 | const XCOFFSectionHeader32 *sectionHeaderTable32() const; | |||
| 531 | const XCOFFSectionHeader64 *sectionHeaderTable64() const; | |||
| 532 | template <typename T> const T *sectionHeaderTable() const; | |||
| 533 | ||||
| 534 | size_t getFileHeaderSize() const; | |||
| 535 | size_t getSectionHeaderSize() const; | |||
| 536 | ||||
| 537 | const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const; | |||
| 538 | const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const; | |||
| 539 | uintptr_t getSectionHeaderTableAddress() const; | |||
| 540 | uintptr_t getEndOfSymbolTableAddress() const; | |||
| 541 | ||||
| 542 | DataRefImpl getSectionByType(XCOFF::SectionTypeFlags SectType) const; | |||
| 543 | uint64_t getSectionFileOffsetToRawData(DataRefImpl Sec) const; | |||
| 544 | ||||
| 545 | // This returns a pointer to the start of the storage for the name field of | |||
| 546 | // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily | |||
| 547 | // null-terminated. | |||
| 548 | const char *getSectionNameInternal(DataRefImpl Sec) const; | |||
| 549 | ||||
| 550 | static bool isReservedSectionNumber(int16_t SectionNumber); | |||
| 551 | ||||
| 552 | // Constructor and "create" factory function. The constructor is only a thin | |||
| 553 | // wrapper around the base constructor. The "create" function fills out the | |||
| 554 | // XCOFF-specific information and performs the error checking along the way. | |||
| 555 | XCOFFObjectFile(unsigned Type, MemoryBufferRef Object); | |||
| 556 | static Expected<std::unique_ptr<XCOFFObjectFile>> create(unsigned Type, | |||
| 557 | MemoryBufferRef MBR); | |||
| 558 | ||||
| 559 | // Helper for parsing the StringTable. Returns an 'Error' if parsing failed | |||
| 560 | // and an XCOFFStringTable if parsing succeeded. | |||
| 561 | static Expected<XCOFFStringTable> parseStringTable(const XCOFFObjectFile *Obj, | |||
| 562 | uint64_t Offset); | |||
| 563 | ||||
| 564 | // Make a friend so it can call the private 'create' function. | |||
| 565 | friend Expected<std::unique_ptr<ObjectFile>> | |||
| 566 | ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType); | |||
| 567 | ||||
| 568 | void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const; | |||
| 569 | ||||
| 570 | public: | |||
| 571 | static constexpr uint64_t InvalidRelocOffset = | |||
| 572 | std::numeric_limits<uint64_t>::max(); | |||
| 573 | ||||
| 574 | // Interface inherited from base classes. | |||
| 575 | void moveSymbolNext(DataRefImpl &Symb) const override; | |||
| 576 | Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; | |||
| 577 | basic_symbol_iterator symbol_begin() const override; | |||
| 578 | basic_symbol_iterator symbol_end() const override; | |||
| 579 | bool is64Bit() const override; | |||
| 580 | Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; | |||
| 581 | Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; | |||
| 582 | uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; | |||
| 583 | uint32_t getSymbolAlignment(DataRefImpl Symb) const override; | |||
| 584 | uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; | |||
| 585 | Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; | |||
| 586 | Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; | |||
| 587 | ||||
| 588 | void moveSectionNext(DataRefImpl &Sec) const override; | |||
| 589 | Expected<StringRef> getSectionName(DataRefImpl Sec) const override; | |||
| 590 | uint64_t getSectionAddress(DataRefImpl Sec) const override; | |||
| 591 | uint64_t getSectionIndex(DataRefImpl Sec) const override; | |||
| 592 | uint64_t getSectionSize(DataRefImpl Sec) const override; | |||
| 593 | Expected<ArrayRef<uint8_t>> | |||
| 594 | getSectionContents(DataRefImpl Sec) const override; | |||
| 595 | uint64_t getSectionAlignment(DataRefImpl Sec) const override; | |||
| 596 | bool isSectionCompressed(DataRefImpl Sec) const override; | |||
| 597 | bool isSectionText(DataRefImpl Sec) const override; | |||
| 598 | bool isSectionData(DataRefImpl Sec) const override; | |||
| 599 | bool isSectionBSS(DataRefImpl Sec) const override; | |||
| 600 | bool isDebugSection(DataRefImpl Sec) const override; | |||
| 601 | ||||
| 602 | bool isSectionVirtual(DataRefImpl Sec) const override; | |||
| 603 | relocation_iterator section_rel_begin(DataRefImpl Sec) const override; | |||
| 604 | relocation_iterator section_rel_end(DataRefImpl Sec) const override; | |||
| 605 | ||||
| 606 | void moveRelocationNext(DataRefImpl &Rel) const override; | |||
| 607 | ||||
| 608 | /// \returns the relocation offset with the base address of the containing | |||
| 609 | /// section as zero, or InvalidRelocOffset on errors (such as a relocation | |||
| 610 | /// that does not refer to an address in any section). | |||
| 611 | uint64_t getRelocationOffset(DataRefImpl Rel) const override; | |||
| 612 | symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; | |||
| 613 | uint64_t getRelocationType(DataRefImpl Rel) const override; | |||
| 614 | void getRelocationTypeName(DataRefImpl Rel, | |||
| 615 | SmallVectorImpl<char> &Result) const override; | |||
| 616 | ||||
| 617 | section_iterator section_begin() const override; | |||
| 618 | section_iterator section_end() const override; | |||
| 619 | uint8_t getBytesInAddress() const override; | |||
| 620 | StringRef getFileFormatName() const override; | |||
| 621 | Triple::ArchType getArch() const override; | |||
| 622 | Expected<SubtargetFeatures> getFeatures() const override; | |||
| 623 | Expected<uint64_t> getStartAddress() const override; | |||
| 624 | StringRef mapDebugSectionName(StringRef Name) const override; | |||
| 625 | bool isRelocatableObject() const override; | |||
| 626 | ||||
| 627 | // Below here is the non-inherited interface. | |||
| 628 | ||||
| 629 | Expected<StringRef> getRawData(const char *Start, uint64_t Size, | |||
| 630 | StringRef Name) const; | |||
| 631 | ||||
| 632 | const XCOFFAuxiliaryHeader32 *auxiliaryHeader32() const; | |||
| 633 | const XCOFFAuxiliaryHeader64 *auxiliaryHeader64() const; | |||
| 634 | ||||
| 635 | const void *getPointerToSymbolTable() const { return SymbolTblPtr; } | |||
| 636 | ||||
| 637 | Expected<StringRef> getSymbolSectionName(XCOFFSymbolRef Ref) const; | |||
| 638 | unsigned getSymbolSectionID(SymbolRef Sym) const; | |||
| 639 | XCOFFSymbolRef toSymbolRef(DataRefImpl Ref) const; | |||
| 640 | ||||
| 641 | // File header related interfaces. | |||
| 642 | const XCOFFFileHeader32 *fileHeader32() const; | |||
| 643 | const XCOFFFileHeader64 *fileHeader64() const; | |||
| 644 | uint16_t getMagic() const; | |||
| 645 | uint16_t getNumberOfSections() const; | |||
| 646 | int32_t getTimeStamp() const; | |||
| 647 | ||||
| 648 | // Symbol table offset and entry count are handled differently between | |||
| 649 | // XCOFF32 and XCOFF64. | |||
| 650 | uint32_t getSymbolTableOffset32() const; | |||
| 651 | uint64_t getSymbolTableOffset64() const; | |||
| 652 | ||||
| 653 | // Note that this value is signed and might return a negative value. Negative | |||
| 654 | // values are reserved for future use. | |||
| 655 | int32_t getRawNumberOfSymbolTableEntries32() const; | |||
| 656 | ||||
| 657 | // The sanitized value appropriate to use as an index into the symbol table. | |||
| 658 | uint32_t getLogicalNumberOfSymbolTableEntries32() const; | |||
| 659 | ||||
| 660 | uint32_t getNumberOfSymbolTableEntries64() const; | |||
| 661 | ||||
| 662 | // Return getLogicalNumberOfSymbolTableEntries32 or | |||
| 663 | // getNumberOfSymbolTableEntries64 depending on the object mode. | |||
| 664 | uint32_t getNumberOfSymbolTableEntries() const; | |||
| 665 | ||||
| 666 | uint32_t getSymbolIndex(uintptr_t SymEntPtr) const; | |||
| 667 | uint64_t getSymbolSize(DataRefImpl Symb) const; | |||
| 668 | uintptr_t getSymbolByIndex(uint32_t Idx) const { | |||
| 669 | return reinterpret_cast<uintptr_t>(SymbolTblPtr) + | |||
| 670 | XCOFF::SymbolTableEntrySize * Idx; | |||
| 671 | } | |||
| 672 | uintptr_t getSymbolEntryAddressByIndex(uint32_t SymbolTableIndex) const; | |||
| 673 | Expected<StringRef> getSymbolNameByIndex(uint32_t SymbolTableIndex) const; | |||
| 674 | ||||
| 675 | Expected<StringRef> getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const; | |||
| 676 | uint16_t getOptionalHeaderSize() const; | |||
| 677 | uint16_t getFlags() const; | |||
| 678 | ||||
| 679 | // Section header table related interfaces. | |||
| 680 | ArrayRef<XCOFFSectionHeader32> sections32() const; | |||
| 681 | ArrayRef<XCOFFSectionHeader64> sections64() const; | |||
| 682 | ||||
| 683 | int32_t getSectionFlags(DataRefImpl Sec) const; | |||
| 684 | Expected<DataRefImpl> getSectionByNum(int16_t Num) const; | |||
| 685 | ||||
| 686 | Expected<uintptr_t> | |||
| 687 | getSectionFileOffsetToRawData(XCOFF::SectionTypeFlags SectType) const; | |||
| 688 | ||||
| 689 | void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const; | |||
| 690 | ||||
| 691 | // Relocation-related interfaces. | |||
| 692 | template <typename T> | |||
| 693 | Expected<uint32_t> | |||
| 694 | getNumberOfRelocationEntries(const XCOFFSectionHeader<T> &Sec) const; | |||
| 695 | ||||
| 696 | template <typename Shdr, typename Reloc> | |||
| 697 | Expected<ArrayRef<Reloc>> relocations(const Shdr &Sec) const; | |||
| 698 | ||||
| 699 | // Loader section related interfaces. | |||
| 700 | Expected<StringRef> getImportFileTable() const; | |||
| 701 | ||||
| 702 | // Exception-related interface. | |||
| 703 | template <typename ExceptEnt> | |||
| 704 | Expected<ArrayRef<ExceptEnt>> getExceptionEntries() const; | |||
| 705 | ||||
| 706 | // This function returns string table entry. | |||
| 707 | Expected<StringRef> getStringTableEntry(uint32_t Offset) const; | |||
| 708 | ||||
| 709 | // This function returns the string table. | |||
| 710 | StringRef getStringTable() const; | |||
| 711 | ||||
| 712 | const XCOFF::SymbolAuxType *getSymbolAuxType(uintptr_t AuxEntryAddress) const; | |||
| 713 | ||||
| 714 | static uintptr_t getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress, | |||
| 715 | uint32_t Distance); | |||
| 716 | ||||
| 717 | static bool classof(const Binary *B) { return B->isXCOFF(); } | |||
| 718 | }; // XCOFFObjectFile | |||
| 719 | ||||
| 720 | typedef struct { | |||
| 721 | uint8_t LanguageId; | |||
| 722 | uint8_t CpuTypeId; | |||
| 723 | } CFileLanguageIdAndTypeIdType; | |||
| 724 | ||||
| 725 | struct XCOFFSymbolEntry32 { | |||
| 726 | typedef struct { | |||
| 727 | support::big32_t Magic; // Zero indicates name in string table. | |||
| 728 | support::ubig32_t Offset; | |||
| 729 | } NameInStrTblType; | |||
| 730 | ||||
| 731 | union { | |||
| 732 | char SymbolName[XCOFF::NameSize]; | |||
| 733 | NameInStrTblType NameInStrTbl; | |||
| 734 | }; | |||
| 735 | ||||
| 736 | support::ubig32_t Value; // Symbol value; storage class-dependent. | |||
| 737 | support::big16_t SectionNumber; | |||
| 738 | ||||
| 739 | union { | |||
| 740 | support::ubig16_t SymbolType; | |||
| 741 | CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId; | |||
| 742 | }; | |||
| 743 | ||||
| 744 | XCOFF::StorageClass StorageClass; | |||
| 745 | uint8_t NumberOfAuxEntries; | |||
| 746 | }; | |||
| 747 | ||||
| 748 | struct XCOFFSymbolEntry64 { | |||
| 749 | support::ubig64_t Value; // Symbol value; storage class-dependent. | |||
| 750 | support::ubig32_t Offset; | |||
| 751 | support::big16_t SectionNumber; | |||
| 752 | ||||
| 753 | union { | |||
| 754 | support::ubig16_t SymbolType; | |||
| 755 | CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId; | |||
| 756 | }; | |||
| 757 | ||||
| 758 | XCOFF::StorageClass StorageClass; | |||
| 759 | uint8_t NumberOfAuxEntries; | |||
| 760 | }; | |||
| 761 | ||||
| 762 | class XCOFFSymbolRef { | |||
| 763 | public: | |||
| 764 | enum { NAME_IN_STR_TBL_MAGIC = 0x0 }; | |||
| 765 | ||||
| 766 | XCOFFSymbolRef(DataRefImpl SymEntDataRef, | |||
| 767 | const XCOFFObjectFile *OwningObjectPtr) | |||
| 768 | : OwningObjectPtr(OwningObjectPtr) { | |||
| 769 | assert(OwningObjectPtr && "OwningObjectPtr cannot be nullptr!")(static_cast <bool> (OwningObjectPtr && "OwningObjectPtr cannot be nullptr!" ) ? void (0) : __assert_fail ("OwningObjectPtr && \"OwningObjectPtr cannot be nullptr!\"" , "llvm/include/llvm/Object/XCOFFObjectFile.h", 769, __extension__ __PRETTY_FUNCTION__)); | |||
| 770 | assert(SymEntDataRef.p != 0 &&(static_cast <bool> (SymEntDataRef.p != 0 && "Symbol table entry pointer cannot be nullptr!" ) ? void (0) : __assert_fail ("SymEntDataRef.p != 0 && \"Symbol table entry pointer cannot be nullptr!\"" , "llvm/include/llvm/Object/XCOFFObjectFile.h", 771, __extension__ __PRETTY_FUNCTION__)) | |||
| 771 | "Symbol table entry pointer cannot be nullptr!")(static_cast <bool> (SymEntDataRef.p != 0 && "Symbol table entry pointer cannot be nullptr!" ) ? void (0) : __assert_fail ("SymEntDataRef.p != 0 && \"Symbol table entry pointer cannot be nullptr!\"" , "llvm/include/llvm/Object/XCOFFObjectFile.h", 771, __extension__ __PRETTY_FUNCTION__)); | |||
| 772 | ||||
| 773 | if (OwningObjectPtr->is64Bit()) | |||
| 774 | Entry64 = reinterpret_cast<const XCOFFSymbolEntry64 *>(SymEntDataRef.p); | |||
| 775 | else | |||
| 776 | Entry32 = reinterpret_cast<const XCOFFSymbolEntry32 *>(SymEntDataRef.p); | |||
| 777 | } | |||
| 778 | ||||
| 779 | const XCOFFSymbolEntry32 *getSymbol32() { return Entry32; } | |||
| 780 | const XCOFFSymbolEntry64 *getSymbol64() { return Entry64; } | |||
| 781 | ||||
| 782 | uint64_t getValue() const { return Entry32 ? getValue32() : getValue64(); } | |||
| 783 | ||||
| 784 | uint32_t getValue32() const { return Entry32->Value; } | |||
| 785 | ||||
| 786 | uint64_t getValue64() const { return Entry64->Value; } | |||
| 787 | ||||
| 788 | #define GETVALUE(X) Entry32 ? Entry32->X : Entry64->X | |||
| 789 | ||||
| 790 | int16_t getSectionNumber() const { return GETVALUE(SectionNumber); } | |||
| ||||
| 791 | ||||
| 792 | uint16_t getSymbolType() const { return GETVALUE(SymbolType); } | |||
| 793 | ||||
| 794 | uint8_t getLanguageIdForCFile() const { | |||
| 795 | assert(getStorageClass() == XCOFF::C_FILE &&(static_cast <bool> (getStorageClass() == XCOFF::C_FILE && "This interface is for C_FILE only.") ? void (0) : __assert_fail ("getStorageClass() == XCOFF::C_FILE && \"This interface is for C_FILE only.\"" , "llvm/include/llvm/Object/XCOFFObjectFile.h", 796, __extension__ __PRETTY_FUNCTION__)) | |||
| 796 | "This interface is for C_FILE only.")(static_cast <bool> (getStorageClass() == XCOFF::C_FILE && "This interface is for C_FILE only.") ? void (0) : __assert_fail ("getStorageClass() == XCOFF::C_FILE && \"This interface is for C_FILE only.\"" , "llvm/include/llvm/Object/XCOFFObjectFile.h", 796, __extension__ __PRETTY_FUNCTION__)); | |||
| 797 | return GETVALUE(CFileLanguageIdAndTypeId.LanguageId); | |||
| 798 | } | |||
| 799 | ||||
| 800 | uint8_t getCPUTypeIddForCFile() const { | |||
| 801 | assert(getStorageClass() == XCOFF::C_FILE &&(static_cast <bool> (getStorageClass() == XCOFF::C_FILE && "This interface is for C_FILE only.") ? void (0) : __assert_fail ("getStorageClass() == XCOFF::C_FILE && \"This interface is for C_FILE only.\"" , "llvm/include/llvm/Object/XCOFFObjectFile.h", 802, __extension__ __PRETTY_FUNCTION__)) | |||
| 802 | "This interface is for C_FILE only.")(static_cast <bool> (getStorageClass() == XCOFF::C_FILE && "This interface is for C_FILE only.") ? void (0) : __assert_fail ("getStorageClass() == XCOFF::C_FILE && \"This interface is for C_FILE only.\"" , "llvm/include/llvm/Object/XCOFFObjectFile.h", 802, __extension__ __PRETTY_FUNCTION__)); | |||
| 803 | return GETVALUE(CFileLanguageIdAndTypeId.CpuTypeId); | |||
| 804 | } | |||
| 805 | ||||
| 806 | XCOFF::StorageClass getStorageClass() const { return GETVALUE(StorageClass); } | |||
| 807 | ||||
| 808 | uint8_t getNumberOfAuxEntries() const { return GETVALUE(NumberOfAuxEntries); } | |||
| 809 | ||||
| 810 | #undef GETVALUE | |||
| 811 | ||||
| 812 | uintptr_t getEntryAddress() const { | |||
| 813 | return Entry32 ? reinterpret_cast<uintptr_t>(Entry32) | |||
| 814 | : reinterpret_cast<uintptr_t>(Entry64); | |||
| 815 | } | |||
| 816 | ||||
| 817 | Expected<StringRef> getName() const; | |||
| 818 | bool isFunction() const; | |||
| 819 | bool isCsectSymbol() const; | |||
| 820 | Expected<XCOFFCsectAuxRef> getXCOFFCsectAuxRef() const; | |||
| 821 | ||||
| 822 | private: | |||
| 823 | const XCOFFObjectFile *OwningObjectPtr; | |||
| 824 | const XCOFFSymbolEntry32 *Entry32 = nullptr; | |||
| 825 | const XCOFFSymbolEntry64 *Entry64 = nullptr; | |||
| 826 | }; | |||
| 827 | ||||
| 828 | class TBVectorExt { | |||
| 829 | uint16_t Data; | |||
| 830 | SmallString<32> VecParmsInfo; | |||
| 831 | ||||
| 832 | TBVectorExt(StringRef TBvectorStrRef, Error &Err); | |||
| 833 | ||||
| 834 | public: | |||
| 835 | static Expected<TBVectorExt> create(StringRef TBvectorStrRef); | |||
| 836 | uint8_t getNumberOfVRSaved() const; | |||
| 837 | bool isVRSavedOnStack() const; | |||
| 838 | bool hasVarArgs() const; | |||
| 839 | uint8_t getNumberOfVectorParms() const; | |||
| 840 | bool hasVMXInstruction() const; | |||
| 841 | SmallString<32> getVectorParmsInfo() const { return VecParmsInfo; }; | |||
| 842 | }; | |||
| 843 | ||||
| 844 | /// This class provides methods to extract traceback table data from a buffer. | |||
| 845 | /// The various accessors may reference the buffer provided via the constructor. | |||
| 846 | ||||
| 847 | class XCOFFTracebackTable { | |||
| 848 | const uint8_t *const TBPtr; | |||
| 849 | std::optional<SmallString<32>> ParmsType; | |||
| 850 | std::optional<uint32_t> TraceBackTableOffset; | |||
| 851 | std::optional<uint32_t> HandlerMask; | |||
| 852 | std::optional<uint32_t> NumOfCtlAnchors; | |||
| 853 | std::optional<SmallVector<uint32_t, 8>> ControlledStorageInfoDisp; | |||
| 854 | std::optional<StringRef> FunctionName; | |||
| 855 | std::optional<uint8_t> AllocaRegister; | |||
| 856 | std::optional<TBVectorExt> VecExt; | |||
| 857 | std::optional<uint8_t> ExtensionTable; | |||
| 858 | ||||
| 859 | XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, Error &Err); | |||
| 860 | ||||
| 861 | public: | |||
| 862 | /// Parse an XCOFF Traceback Table from \a Ptr with \a Size bytes. | |||
| 863 | /// Returns an XCOFFTracebackTable upon successful parsing, otherwise an | |||
| 864 | /// Error is returned. | |||
| 865 | /// | |||
| 866 | /// \param[in] Ptr | |||
| 867 | /// A pointer that points just past the initial 4 bytes of zeros at the | |||
| 868 | /// beginning of an XCOFF Traceback Table. | |||
| 869 | /// | |||
| 870 | /// \param[in, out] Size | |||
| 871 | /// A pointer that points to the length of the XCOFF Traceback Table. | |||
| 872 | /// If the XCOFF Traceback Table is not parsed successfully or there are | |||
| 873 | /// extra bytes that are not recognized, \a Size will be updated to be the | |||
| 874 | /// size up to the end of the last successfully parsed field of the table. | |||
| 875 | static Expected<XCOFFTracebackTable> create(const uint8_t *Ptr, | |||
| 876 | uint64_t &Size); | |||
| 877 | uint8_t getVersion() const; | |||
| 878 | uint8_t getLanguageID() const; | |||
| 879 | ||||
| 880 | bool isGlobalLinkage() const; | |||
| 881 | bool isOutOfLineEpilogOrPrologue() const; | |||
| 882 | bool hasTraceBackTableOffset() const; | |||
| 883 | bool isInternalProcedure() const; | |||
| 884 | bool hasControlledStorage() const; | |||
| 885 | bool isTOCless() const; | |||
| 886 | bool isFloatingPointPresent() const; | |||
| 887 | bool isFloatingPointOperationLogOrAbortEnabled() const; | |||
| 888 | ||||
| 889 | bool isInterruptHandler() const; | |||
| 890 | bool isFuncNamePresent() const; | |||
| 891 | bool isAllocaUsed() const; | |||
| 892 | uint8_t getOnConditionDirective() const; | |||
| 893 | bool isCRSaved() const; | |||
| 894 | bool isLRSaved() const; | |||
| 895 | ||||
| 896 | bool isBackChainStored() const; | |||
| 897 | bool isFixup() const; | |||
| 898 | uint8_t getNumOfFPRsSaved() const; | |||
| 899 | ||||
| 900 | bool hasVectorInfo() const; | |||
| 901 | bool hasExtensionTable() const; | |||
| 902 | uint8_t getNumOfGPRsSaved() const; | |||
| 903 | ||||
| 904 | uint8_t getNumberOfFixedParms() const; | |||
| 905 | ||||
| 906 | uint8_t getNumberOfFPParms() const; | |||
| 907 | bool hasParmsOnStack() const; | |||
| 908 | ||||
| 909 | const std::optional<SmallString<32>> &getParmsType() const { | |||
| 910 | return ParmsType; | |||
| 911 | } | |||
| 912 | const std::optional<uint32_t> &getTraceBackTableOffset() const { | |||
| 913 | return TraceBackTableOffset; | |||
| 914 | } | |||
| 915 | const std::optional<uint32_t> &getHandlerMask() const { return HandlerMask; } | |||
| 916 | const std::optional<uint32_t> &getNumOfCtlAnchors() { | |||
| 917 | return NumOfCtlAnchors; | |||
| 918 | } | |||
| 919 | const std::optional<SmallVector<uint32_t, 8>> & | |||
| 920 | getControlledStorageInfoDisp() { | |||
| 921 | return ControlledStorageInfoDisp; | |||
| 922 | } | |||
| 923 | const std::optional<StringRef> &getFunctionName() const { | |||
| 924 | return FunctionName; | |||
| 925 | } | |||
| 926 | const std::optional<uint8_t> &getAllocaRegister() const { | |||
| 927 | return AllocaRegister; | |||
| 928 | } | |||
| 929 | const std::optional<TBVectorExt> &getVectorExt() const { return VecExt; } | |||
| 930 | const std::optional<uint8_t> &getExtensionTable() const { | |||
| 931 | return ExtensionTable; | |||
| 932 | } | |||
| 933 | }; | |||
| 934 | ||||
| 935 | bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes); | |||
| 936 | } // namespace object | |||
| 937 | } // namespace llvm | |||
| 938 | ||||
| 939 | #endif // LLVM_OBJECT_XCOFFOBJECTFILE_H |