1ab2eb2bfSHubert Tong //===--- XCOFFObjectFile.cpp - XCOFF object file implementation -----------===//
2ab2eb2bfSHubert Tong //
3ab2eb2bfSHubert Tong // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ab2eb2bfSHubert Tong // See https://llvm.org/LICENSE.txt for license information.
5ab2eb2bfSHubert Tong // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ab2eb2bfSHubert Tong //
7ab2eb2bfSHubert Tong //===----------------------------------------------------------------------===//
8ab2eb2bfSHubert Tong //
9ab2eb2bfSHubert Tong // This file defines the XCOFFObjectFile class.
10ab2eb2bfSHubert Tong //
11ab2eb2bfSHubert Tong //===----------------------------------------------------------------------===//
12ab2eb2bfSHubert Tong
13ab2eb2bfSHubert Tong #include "llvm/Object/XCOFFObjectFile.h"
14d33b016aSChen Zheng #include "llvm/ADT/StringSwitch.h"
150865d414SSimon Pilgrim #include "llvm/MC/SubtargetFeature.h"
162f0d755dSdiggerlin #include "llvm/Support/DataExtractor.h"
17ab2eb2bfSHubert Tong #include <cstddef>
18ab2eb2bfSHubert Tong #include <cstring>
19ab2eb2bfSHubert Tong
20ab2eb2bfSHubert Tong namespace llvm {
212f0d755dSdiggerlin
222f0d755dSdiggerlin using namespace XCOFF;
232f0d755dSdiggerlin
24ab2eb2bfSHubert Tong namespace object {
25ab2eb2bfSHubert Tong
26d60d7d69Sjasonliu static const uint8_t FunctionSym = 0x20;
27d60d7d69Sjasonliu static const uint16_t NoRelMask = 0x0001;
288e84311aSjasonliu static const size_t SymbolAuxTypeOffset = 17;
297c72e82bSJason Liu
30837ae69fSSean Fertile // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer
31837ae69fSSean Fertile // 'M'. Returns a pointer to the underlying object on success.
32ab2eb2bfSHubert Tong template <typename T>
getObject(MemoryBufferRef M,const void * Ptr,const uint64_t Size=sizeof (T))33837ae69fSSean Fertile static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr,
34ab2eb2bfSHubert Tong const uint64_t Size = sizeof(T)) {
3522cf54a7SArthur O'Dwyer uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr);
36e03a135bSReid Kleckner if (Error E = Binary::checkOffset(M, Addr, Size))
37e03a135bSReid Kleckner return std::move(E);
38837ae69fSSean Fertile return reinterpret_cast<const T *>(Addr);
39837ae69fSSean Fertile }
40837ae69fSSean Fertile
getWithOffset(uintptr_t Base,ptrdiff_t Offset)41837ae69fSSean Fertile static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) {
42837ae69fSSean Fertile return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) +
43837ae69fSSean Fertile Offset);
44ab2eb2bfSHubert Tong }
45ab2eb2bfSHubert Tong
viewAs(uintptr_t in)46a93a33cbSSean Fertile template <typename T> static const T *viewAs(uintptr_t in) {
47a93a33cbSSean Fertile return reinterpret_cast<const T *>(in);
48a93a33cbSSean Fertile }
49a93a33cbSSean Fertile
generateXCOFFFixedNameStringRef(const char * Name)507c72e82bSJason Liu static StringRef generateXCOFFFixedNameStringRef(const char *Name) {
5129141da7SSean Fertile auto NulCharPtr =
5229141da7SSean Fertile static_cast<const char *>(memchr(Name, '\0', XCOFF::NameSize));
539212206dSJason Liu return NulCharPtr ? StringRef(Name, NulCharPtr - Name)
5429141da7SSean Fertile : StringRef(Name, XCOFF::NameSize);
559212206dSJason Liu }
569212206dSJason Liu
getName() const57c63c1a72Sdiggerlin template <typename T> StringRef XCOFFSectionHeader<T>::getName() const {
58c63c1a72Sdiggerlin const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
59c63c1a72Sdiggerlin return generateXCOFFFixedNameStringRef(DerivedXCOFFSectionHeader.Name);
60c63c1a72Sdiggerlin }
61c63c1a72Sdiggerlin
getSectionType() const62c63c1a72Sdiggerlin template <typename T> uint16_t XCOFFSectionHeader<T>::getSectionType() const {
63c63c1a72Sdiggerlin const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
64c63c1a72Sdiggerlin return DerivedXCOFFSectionHeader.Flags & SectionFlagsTypeMask;
65c63c1a72Sdiggerlin }
66c63c1a72Sdiggerlin
67c63c1a72Sdiggerlin template <typename T>
isReservedSectionType() const68c63c1a72Sdiggerlin bool XCOFFSectionHeader<T>::isReservedSectionType() const {
69c63c1a72Sdiggerlin return getSectionType() & SectionFlagsReservedMask;
70c63c1a72Sdiggerlin }
71c63c1a72Sdiggerlin
722cdfd0b2SMaryam Benimmar template <typename AddressType>
isRelocationSigned() const732cdfd0b2SMaryam Benimmar bool XCOFFRelocation<AddressType>::isRelocationSigned() const {
7434d4bff3SDigger Lin return Info & XR_SIGN_INDICATOR_MASK;
7534d4bff3SDigger Lin }
7634d4bff3SDigger Lin
772cdfd0b2SMaryam Benimmar template <typename AddressType>
isFixupIndicated() const782cdfd0b2SMaryam Benimmar bool XCOFFRelocation<AddressType>::isFixupIndicated() const {
7934d4bff3SDigger Lin return Info & XR_FIXUP_INDICATOR_MASK;
8034d4bff3SDigger Lin }
8134d4bff3SDigger Lin
822cdfd0b2SMaryam Benimmar template <typename AddressType>
getRelocatedLength() const832cdfd0b2SMaryam Benimmar uint8_t XCOFFRelocation<AddressType>::getRelocatedLength() const {
8434d4bff3SDigger Lin // The relocation encodes the bit length being relocated minus 1. Add back
8534d4bff3SDigger Lin // the 1 to get the actual length being relocated.
8634d4bff3SDigger Lin return (Info & XR_BIASED_LENGTH_MASK) + 1;
8734d4bff3SDigger Lin }
8834d4bff3SDigger Lin
898e84311aSjasonliu uintptr_t
getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,uint32_t Distance)908e84311aSjasonliu XCOFFObjectFile::getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,
918e84311aSjasonliu uint32_t Distance) {
928e84311aSjasonliu return getWithOffset(CurrentAddress, Distance * XCOFF::SymbolTableEntrySize);
938e84311aSjasonliu }
948e84311aSjasonliu
958e84311aSjasonliu const XCOFF::SymbolAuxType *
getSymbolAuxType(uintptr_t AuxEntryAddress) const968e84311aSjasonliu XCOFFObjectFile::getSymbolAuxType(uintptr_t AuxEntryAddress) const {
978e84311aSjasonliu assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
988e84311aSjasonliu return viewAs<XCOFF::SymbolAuxType>(
998e84311aSjasonliu getWithOffset(AuxEntryAddress, SymbolAuxTypeOffset));
1008e84311aSjasonliu }
1018e84311aSjasonliu
checkSectionAddress(uintptr_t Addr,uintptr_t TableAddress) const102837ae69fSSean Fertile void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr,
103837ae69fSSean Fertile uintptr_t TableAddress) const {
104837ae69fSSean Fertile if (Addr < TableAddress)
105a93a33cbSSean Fertile report_fatal_error("Section header outside of section header table.");
106a93a33cbSSean Fertile
107837ae69fSSean Fertile uintptr_t Offset = Addr - TableAddress;
108837ae69fSSean Fertile if (Offset >= getSectionHeaderSize() * getNumberOfSections())
109837ae69fSSean Fertile report_fatal_error("Section header outside of section header table.");
110837ae69fSSean Fertile
111a93a33cbSSean Fertile if (Offset % getSectionHeaderSize() != 0)
112a93a33cbSSean Fertile report_fatal_error(
113a93a33cbSSean Fertile "Section header pointer does not point to a valid section header.");
114837ae69fSSean Fertile }
115837ae69fSSean Fertile
116837ae69fSSean Fertile const XCOFFSectionHeader32 *
toSection32(DataRefImpl Ref) const117837ae69fSSean Fertile XCOFFObjectFile::toSection32(DataRefImpl Ref) const {
118837ae69fSSean Fertile assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
119837ae69fSSean Fertile #ifndef NDEBUG
120837ae69fSSean Fertile checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
121a93a33cbSSean Fertile #endif
122837ae69fSSean Fertile return viewAs<XCOFFSectionHeader32>(Ref.p);
123837ae69fSSean Fertile }
124837ae69fSSean Fertile
125837ae69fSSean Fertile const XCOFFSectionHeader64 *
toSection64(DataRefImpl Ref) const126837ae69fSSean Fertile XCOFFObjectFile::toSection64(DataRefImpl Ref) const {
127837ae69fSSean Fertile assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
128837ae69fSSean Fertile #ifndef NDEBUG
129837ae69fSSean Fertile checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
130837ae69fSSean Fertile #endif
131837ae69fSSean Fertile return viewAs<XCOFFSectionHeader64>(Ref.p);
132a93a33cbSSean Fertile }
133a93a33cbSSean Fertile
toSymbolRef(DataRefImpl Ref) const1348e84311aSjasonliu XCOFFSymbolRef XCOFFObjectFile::toSymbolRef(DataRefImpl Ref) const {
1359212206dSJason Liu assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!");
1367c72e82bSJason Liu #ifndef NDEBUG
1377c72e82bSJason Liu checkSymbolEntryPointer(Ref.p);
1387c72e82bSJason Liu #endif
1398e84311aSjasonliu return XCOFFSymbolRef(Ref, this);
1409212206dSJason Liu }
1419212206dSJason Liu
fileHeader32() const142837ae69fSSean Fertile const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const {
143837ae69fSSean Fertile assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
144837ae69fSSean Fertile return static_cast<const XCOFFFileHeader32 *>(FileHeader);
145a93a33cbSSean Fertile }
146a93a33cbSSean Fertile
fileHeader64() const147837ae69fSSean Fertile const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const {
148837ae69fSSean Fertile assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
149837ae69fSSean Fertile return static_cast<const XCOFFFileHeader64 *>(FileHeader);
150a93a33cbSSean Fertile }
151a93a33cbSSean Fertile
auxiliaryHeader32() const152158083f0Szhijian const XCOFFAuxiliaryHeader32 *XCOFFObjectFile::auxiliaryHeader32() const {
153158083f0Szhijian assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
154158083f0Szhijian return static_cast<const XCOFFAuxiliaryHeader32 *>(AuxiliaryHeader);
155158083f0Szhijian }
156158083f0Szhijian
auxiliaryHeader64() const157158083f0Szhijian const XCOFFAuxiliaryHeader64 *XCOFFObjectFile::auxiliaryHeader64() const {
158158083f0Szhijian assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
159158083f0Szhijian return static_cast<const XCOFFAuxiliaryHeader64 *>(AuxiliaryHeader);
160158083f0Szhijian }
161158083f0Szhijian
sectionHeaderTable() const1622cdfd0b2SMaryam Benimmar template <typename T> const T *XCOFFObjectFile::sectionHeaderTable() const {
1632cdfd0b2SMaryam Benimmar return static_cast<const T *>(SectionHeaderTable);
1642cdfd0b2SMaryam Benimmar }
1652cdfd0b2SMaryam Benimmar
166837ae69fSSean Fertile const XCOFFSectionHeader32 *
sectionHeaderTable32() const167837ae69fSSean Fertile XCOFFObjectFile::sectionHeaderTable32() const {
168837ae69fSSean Fertile assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
169837ae69fSSean Fertile return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable);
170837ae69fSSean Fertile }
171837ae69fSSean Fertile
172837ae69fSSean Fertile const XCOFFSectionHeader64 *
sectionHeaderTable64() const173837ae69fSSean Fertile XCOFFObjectFile::sectionHeaderTable64() const {
174837ae69fSSean Fertile assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
175837ae69fSSean Fertile return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable);
176837ae69fSSean Fertile }
1779212206dSJason Liu
moveSymbolNext(DataRefImpl & Symb) const178ab2eb2bfSHubert Tong void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
1798e84311aSjasonliu uintptr_t NextSymbolAddr = getAdvancedSymbolEntryAddress(
1808e84311aSjasonliu Symb.p, toSymbolRef(Symb).getNumberOfAuxEntries() + 1);
1817c72e82bSJason Liu #ifndef NDEBUG
1827c72e82bSJason Liu // This function is used by basic_symbol_iterator, which allows to
1837c72e82bSJason Liu // point to the end-of-symbol-table address.
1848e84311aSjasonliu if (NextSymbolAddr != getEndOfSymbolTableAddress())
1858e84311aSjasonliu checkSymbolEntryPointer(NextSymbolAddr);
1867c72e82bSJason Liu #endif
1878e84311aSjasonliu Symb.p = NextSymbolAddr;
188ab2eb2bfSHubert Tong }
189ab2eb2bfSHubert Tong
1907c72e82bSJason Liu Expected<StringRef>
getStringTableEntry(uint32_t Offset) const1917c72e82bSJason Liu XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const {
1927c72e82bSJason Liu // The byte offset is relative to the start of the string table.
1937c72e82bSJason Liu // A byte offset value of 0 is a null or zero-length symbol
1949212206dSJason Liu // name. A byte offset in the range 1 to 3 (inclusive) points into the length
1959212206dSJason Liu // field; as a soft-error recovery mechanism, we treat such cases as having an
1969212206dSJason Liu // offset of 0.
1979212206dSJason Liu if (Offset < 4)
1989212206dSJason Liu return StringRef(nullptr, 0);
1999212206dSJason Liu
2009212206dSJason Liu if (StringTable.Data != nullptr && StringTable.Size > Offset)
2019212206dSJason Liu return (StringTable.Data + Offset);
2029212206dSJason Liu
203a00ff716SEsme-Yi return createError("entry with offset 0x" + Twine::utohexstr(Offset) +
204a00ff716SEsme-Yi " in a string table with size 0x" +
205a00ff716SEsme-Yi Twine::utohexstr(StringTable.Size) + " is invalid");
206ab2eb2bfSHubert Tong }
207ab2eb2bfSHubert Tong
getStringTable() const2080dad3f6eSEsme-Yi StringRef XCOFFObjectFile::getStringTable() const {
20969396896SEsme-Yi // If the size is less than or equal to 4, then the string table contains no
21069396896SEsme-Yi // string data.
21169396896SEsme-Yi return StringRef(StringTable.Data,
21269396896SEsme-Yi StringTable.Size <= 4 ? 0 : StringTable.Size);
2130dad3f6eSEsme-Yi }
2140dad3f6eSEsme-Yi
2157c72e82bSJason Liu Expected<StringRef>
getCFileName(const XCOFFFileAuxEnt * CFileEntPtr) const2167c72e82bSJason Liu XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const {
2178e84311aSjasonliu if (CFileEntPtr->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
2187c72e82bSJason Liu return generateXCOFFFixedNameStringRef(CFileEntPtr->Name);
2197c72e82bSJason Liu return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset);
2207c72e82bSJason Liu }
2217c72e82bSJason Liu
getSymbolName(DataRefImpl Symb) const2227c72e82bSJason Liu Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
2238e84311aSjasonliu return toSymbolRef(Symb).getName();
2247c72e82bSJason Liu }
2257c72e82bSJason Liu
getSymbolAddress(DataRefImpl Symb) const226ab2eb2bfSHubert Tong Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
2278e84311aSjasonliu return toSymbolRef(Symb).getValue();
228ab2eb2bfSHubert Tong }
229ab2eb2bfSHubert Tong
getSymbolValueImpl(DataRefImpl Symb) const230ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
2318e84311aSjasonliu return toSymbolRef(Symb).getValue();
232ab2eb2bfSHubert Tong }
233ab2eb2bfSHubert Tong
getSymbolAlignment(DataRefImpl Symb) const2345b44c716Szhijian uint32_t XCOFFObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
2355b44c716Szhijian uint64_t Result = 0;
2365b44c716Szhijian XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
2375b44c716Szhijian if (XCOFFSym.isCsectSymbol()) {
2385b44c716Szhijian Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
2395b44c716Szhijian XCOFFSym.getXCOFFCsectAuxRef();
2405b44c716Szhijian if (!CsectAuxRefOrError)
2415b44c716Szhijian // TODO: report the error up the stack.
2425b44c716Szhijian consumeError(CsectAuxRefOrError.takeError());
2435b44c716Szhijian else
2441549be3eSAaron Ballman Result = 1ULL << CsectAuxRefOrError.get().getAlignmentLog2();
2455b44c716Szhijian }
2465b44c716Szhijian return Result;
2475b44c716Szhijian }
2485b44c716Szhijian
getCommonSymbolSizeImpl(DataRefImpl Symb) const249ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
250ab2eb2bfSHubert Tong uint64_t Result = 0;
2515b44c716Szhijian XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
2525b44c716Szhijian if (XCOFFSym.isCsectSymbol()) {
2535b44c716Szhijian Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
2545b44c716Szhijian XCOFFSym.getXCOFFCsectAuxRef();
2555b44c716Szhijian if (!CsectAuxRefOrError)
2565b44c716Szhijian // TODO: report the error up the stack.
2575b44c716Szhijian consumeError(CsectAuxRefOrError.takeError());
2585b44c716Szhijian else {
2595b44c716Szhijian XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get();
2605b44c716Szhijian assert(CsectAuxRef.getSymbolType() == XCOFF::XTY_CM);
2615b44c716Szhijian Result = CsectAuxRef.getSectionOrLength();
2625b44c716Szhijian }
2635b44c716Szhijian }
264ab2eb2bfSHubert Tong return Result;
265ab2eb2bfSHubert Tong }
266ab2eb2bfSHubert Tong
267ab2eb2bfSHubert Tong Expected<SymbolRef::Type>
getSymbolType(DataRefImpl Symb) const268ab2eb2bfSHubert Tong XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
2695b44c716Szhijian XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
2705b44c716Szhijian
2715b44c716Szhijian if (XCOFFSym.isFunction())
2725b44c716Szhijian return SymbolRef::ST_Function;
2735b44c716Szhijian
2745b44c716Szhijian if (XCOFF::C_FILE == XCOFFSym.getStorageClass())
2755b44c716Szhijian return SymbolRef::ST_File;
2765b44c716Szhijian
2775b44c716Szhijian int16_t SecNum = XCOFFSym.getSectionNumber();
2785b44c716Szhijian if (SecNum <= 0)
2795b44c716Szhijian return SymbolRef::ST_Other;
2805b44c716Szhijian
2815b44c716Szhijian Expected<DataRefImpl> SecDRIOrErr =
2825b44c716Szhijian getSectionByNum(XCOFFSym.getSectionNumber());
2835b44c716Szhijian
2845b44c716Szhijian if (!SecDRIOrErr)
2855b44c716Szhijian return SecDRIOrErr.takeError();
2865b44c716Szhijian
2875b44c716Szhijian DataRefImpl SecDRI = SecDRIOrErr.get();
2885b44c716Szhijian
2895b44c716Szhijian Expected<StringRef> SymNameOrError = XCOFFSym.getName();
2905b44c716Szhijian if (SymNameOrError) {
2915b44c716Szhijian // The "TOC" symbol is treated as SymbolRef::ST_Other.
2925b44c716Szhijian if (SymNameOrError.get() == "TOC")
2935b44c716Szhijian return SymbolRef::ST_Other;
2945b44c716Szhijian
2955b44c716Szhijian // The symbol for a section name is treated as SymbolRef::ST_Other.
2965b44c716Szhijian StringRef SecName;
2975b44c716Szhijian if (is64Bit())
2985b44c716Szhijian SecName = XCOFFObjectFile::toSection64(SecDRIOrErr.get())->getName();
2995b44c716Szhijian else
3005b44c716Szhijian SecName = XCOFFObjectFile::toSection32(SecDRIOrErr.get())->getName();
3015b44c716Szhijian
3025b44c716Szhijian if (SecName == SymNameOrError.get())
3035b44c716Szhijian return SymbolRef::ST_Other;
3045b44c716Szhijian } else
3055b44c716Szhijian return SymNameOrError.takeError();
3065b44c716Szhijian
3075b44c716Szhijian if (isSectionData(SecDRI) || isSectionBSS(SecDRI))
3085b44c716Szhijian return SymbolRef::ST_Data;
3095b44c716Szhijian
3105b44c716Szhijian if (isDebugSection(SecDRI))
3115b44c716Szhijian return SymbolRef::ST_Debug;
3125b44c716Szhijian
313ab2eb2bfSHubert Tong return SymbolRef::ST_Other;
314ab2eb2bfSHubert Tong }
315ab2eb2bfSHubert Tong
316ab2eb2bfSHubert Tong Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const317ab2eb2bfSHubert Tong XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
3188e84311aSjasonliu const int16_t SectNum = toSymbolRef(Symb).getSectionNumber();
3199212206dSJason Liu
3209212206dSJason Liu if (isReservedSectionNumber(SectNum))
3219212206dSJason Liu return section_end();
3229212206dSJason Liu
323837ae69fSSean Fertile Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum);
324837ae69fSSean Fertile if (!ExpSec)
325837ae69fSSean Fertile return ExpSec.takeError();
3269212206dSJason Liu
327837ae69fSSean Fertile return section_iterator(SectionRef(ExpSec.get(), this));
328ab2eb2bfSHubert Tong }
329ab2eb2bfSHubert Tong
moveSectionNext(DataRefImpl & Sec) const330ab2eb2bfSHubert Tong void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
331a93a33cbSSean Fertile const char *Ptr = reinterpret_cast<const char *>(Sec.p);
332a93a33cbSSean Fertile Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize());
333ab2eb2bfSHubert Tong }
334ab2eb2bfSHubert Tong
getSectionName(DataRefImpl Sec) const3358be28cdcSFangrui Song Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const {
3367c72e82bSJason Liu return generateXCOFFFixedNameStringRef(getSectionNameInternal(Sec));
337ab2eb2bfSHubert Tong }
338ab2eb2bfSHubert Tong
getSectionAddress(DataRefImpl Sec) const339ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
340210314aeSSean Fertile // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
341210314aeSSean Fertile // with MSVC.
342210314aeSSean Fertile if (is64Bit())
343210314aeSSean Fertile return toSection64(Sec)->VirtualAddress;
344210314aeSSean Fertile
345210314aeSSean Fertile return toSection32(Sec)->VirtualAddress;
346ab2eb2bfSHubert Tong }
347ab2eb2bfSHubert Tong
getSectionIndex(DataRefImpl Sec) const348ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
349a93a33cbSSean Fertile // Section numbers in XCOFF are numbered beginning at 1. A section number of
350a93a33cbSSean Fertile // zero is used to indicate that a symbol is being imported or is undefined.
351837ae69fSSean Fertile if (is64Bit())
352837ae69fSSean Fertile return toSection64(Sec) - sectionHeaderTable64() + 1;
353837ae69fSSean Fertile else
354837ae69fSSean Fertile return toSection32(Sec) - sectionHeaderTable32() + 1;
355ab2eb2bfSHubert Tong }
356ab2eb2bfSHubert Tong
getSectionSize(DataRefImpl Sec) const357ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
358210314aeSSean Fertile // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
359210314aeSSean Fertile // with MSVC.
360210314aeSSean Fertile if (is64Bit())
361210314aeSSean Fertile return toSection64(Sec)->SectionSize;
362210314aeSSean Fertile
363210314aeSSean Fertile return toSection32(Sec)->SectionSize;
364ab2eb2bfSHubert Tong }
365ab2eb2bfSHubert Tong
366e1cb2c0fSFangrui Song Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Sec) const367e1cb2c0fSFangrui Song XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
368b91f798fSdiggerlin if (isSectionVirtual(Sec))
369b91f798fSdiggerlin return ArrayRef<uint8_t>();
370b91f798fSdiggerlin
371ea13683fSdiggerlin uint64_t OffsetToRaw;
372ea13683fSdiggerlin if (is64Bit())
373ea13683fSdiggerlin OffsetToRaw = toSection64(Sec)->FileOffsetToRawData;
374ea13683fSdiggerlin else
375ea13683fSdiggerlin OffsetToRaw = toSection32(Sec)->FileOffsetToRawData;
376b91f798fSdiggerlin
377b91f798fSdiggerlin const uint8_t * ContentStart = base() + OffsetToRaw;
378b91f798fSdiggerlin uint64_t SectionSize = getSectionSize(Sec);
379ea81898dSEsme-Yi if (Error E = Binary::checkOffset(
380ea81898dSEsme-Yi Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize))
381a00ff716SEsme-Yi return createError(
382a00ff716SEsme-Yi toString(std::move(E)) + ": section data with offset 0x" +
383a00ff716SEsme-Yi Twine::utohexstr(OffsetToRaw) + " and size 0x" +
384a00ff716SEsme-Yi Twine::utohexstr(SectionSize) + " goes past the end of the file");
385b91f798fSdiggerlin
386b91f798fSdiggerlin return makeArrayRef(ContentStart,SectionSize);
387ab2eb2bfSHubert Tong }
388ab2eb2bfSHubert Tong
getSectionAlignment(DataRefImpl Sec) const389ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
390ab2eb2bfSHubert Tong uint64_t Result = 0;
391ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!");
392ab2eb2bfSHubert Tong return Result;
393ab2eb2bfSHubert Tong }
394ab2eb2bfSHubert Tong
getLoaderSectionAddress() const395b21ed75eSEsme-Yi Expected<uintptr_t> XCOFFObjectFile::getLoaderSectionAddress() const {
396b21ed75eSEsme-Yi uint64_t OffsetToLoaderSection = 0;
397b21ed75eSEsme-Yi uint64_t SizeOfLoaderSection = 0;
398b21ed75eSEsme-Yi
399b21ed75eSEsme-Yi if (is64Bit()) {
400b21ed75eSEsme-Yi for (const auto &Sec64 : sections64())
401b21ed75eSEsme-Yi if (Sec64.getSectionType() == XCOFF::STYP_LOADER) {
402b21ed75eSEsme-Yi OffsetToLoaderSection = Sec64.FileOffsetToRawData;
403b21ed75eSEsme-Yi SizeOfLoaderSection = Sec64.SectionSize;
404b21ed75eSEsme-Yi break;
405b21ed75eSEsme-Yi }
406b21ed75eSEsme-Yi } else {
407b21ed75eSEsme-Yi for (const auto &Sec32 : sections32())
408b21ed75eSEsme-Yi if (Sec32.getSectionType() == XCOFF::STYP_LOADER) {
409b21ed75eSEsme-Yi OffsetToLoaderSection = Sec32.FileOffsetToRawData;
410b21ed75eSEsme-Yi SizeOfLoaderSection = Sec32.SectionSize;
411b21ed75eSEsme-Yi break;
412b21ed75eSEsme-Yi }
413b21ed75eSEsme-Yi }
414b21ed75eSEsme-Yi
415b21ed75eSEsme-Yi // No loader section is not an error.
416b21ed75eSEsme-Yi if (!SizeOfLoaderSection)
417b21ed75eSEsme-Yi return 0;
418b21ed75eSEsme-Yi
419b21ed75eSEsme-Yi uintptr_t LoderSectionStart =
420b21ed75eSEsme-Yi reinterpret_cast<uintptr_t>(base() + OffsetToLoaderSection);
421b21ed75eSEsme-Yi if (Error E =
422b21ed75eSEsme-Yi Binary::checkOffset(Data, LoderSectionStart, SizeOfLoaderSection))
423a00ff716SEsme-Yi return createError(toString(std::move(E)) +
424a00ff716SEsme-Yi ": loader section with offset 0x" +
425a00ff716SEsme-Yi Twine::utohexstr(OffsetToLoaderSection) +
426a00ff716SEsme-Yi " and size 0x" + Twine::utohexstr(SizeOfLoaderSection) +
427a00ff716SEsme-Yi " goes past the end of the file");
428a00ff716SEsme-Yi
429b21ed75eSEsme-Yi return LoderSectionStart;
430b21ed75eSEsme-Yi }
431b21ed75eSEsme-Yi
isSectionCompressed(DataRefImpl Sec) const432ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
433d33b016aSChen Zheng return false;
434ab2eb2bfSHubert Tong }
435ab2eb2bfSHubert Tong
isSectionText(DataRefImpl Sec) const436ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const {
437837ae69fSSean Fertile return getSectionFlags(Sec) & XCOFF::STYP_TEXT;
438ab2eb2bfSHubert Tong }
439ab2eb2bfSHubert Tong
isSectionData(DataRefImpl Sec) const440ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const {
441837ae69fSSean Fertile uint32_t Flags = getSectionFlags(Sec);
442a93a33cbSSean Fertile return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA);
443ab2eb2bfSHubert Tong }
444ab2eb2bfSHubert Tong
isSectionBSS(DataRefImpl Sec) const445ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const {
446837ae69fSSean Fertile uint32_t Flags = getSectionFlags(Sec);
447a93a33cbSSean Fertile return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS);
448ab2eb2bfSHubert Tong }
449ab2eb2bfSHubert Tong
isDebugSection(DataRefImpl Sec) const450c8e980abSEsme-Yi bool XCOFFObjectFile::isDebugSection(DataRefImpl Sec) const {
451c8e980abSEsme-Yi uint32_t Flags = getSectionFlags(Sec);
452c8e980abSEsme-Yi return Flags & (XCOFF::STYP_DEBUG | XCOFF::STYP_DWARF);
453c8e980abSEsme-Yi }
454c8e980abSEsme-Yi
isSectionVirtual(DataRefImpl Sec) const455ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const {
456b91f798fSdiggerlin return is64Bit() ? toSection64(Sec)->FileOffsetToRawData == 0
457b91f798fSdiggerlin : toSection32(Sec)->FileOffsetToRawData == 0;
458ab2eb2bfSHubert Tong }
459ab2eb2bfSHubert Tong
section_rel_begin(DataRefImpl Sec) const460ab2eb2bfSHubert Tong relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const {
461d60d7d69Sjasonliu DataRefImpl Ret;
4622cdfd0b2SMaryam Benimmar if (is64Bit()) {
4632cdfd0b2SMaryam Benimmar const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec);
4642cdfd0b2SMaryam Benimmar auto RelocationsOrErr =
4652cdfd0b2SMaryam Benimmar relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr);
4662cdfd0b2SMaryam Benimmar if (Error E = RelocationsOrErr.takeError()) {
4672cdfd0b2SMaryam Benimmar // TODO: report the error up the stack.
4682cdfd0b2SMaryam Benimmar consumeError(std::move(E));
4692cdfd0b2SMaryam Benimmar return relocation_iterator(RelocationRef());
4702cdfd0b2SMaryam Benimmar }
471d60d7d69Sjasonliu Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
4722cdfd0b2SMaryam Benimmar } else {
4732cdfd0b2SMaryam Benimmar const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
4742cdfd0b2SMaryam Benimmar auto RelocationsOrErr =
4752cdfd0b2SMaryam Benimmar relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr);
4762cdfd0b2SMaryam Benimmar if (Error E = RelocationsOrErr.takeError()) {
4772cdfd0b2SMaryam Benimmar // TODO: report the error up the stack.
4782cdfd0b2SMaryam Benimmar consumeError(std::move(E));
4792cdfd0b2SMaryam Benimmar return relocation_iterator(RelocationRef());
4802cdfd0b2SMaryam Benimmar }
4812cdfd0b2SMaryam Benimmar Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
4822cdfd0b2SMaryam Benimmar }
483d60d7d69Sjasonliu return relocation_iterator(RelocationRef(Ret, this));
484ab2eb2bfSHubert Tong }
485ab2eb2bfSHubert Tong
section_rel_end(DataRefImpl Sec) const486ab2eb2bfSHubert Tong relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const {
487d60d7d69Sjasonliu DataRefImpl Ret;
4882cdfd0b2SMaryam Benimmar if (is64Bit()) {
4892cdfd0b2SMaryam Benimmar const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec);
4902cdfd0b2SMaryam Benimmar auto RelocationsOrErr =
4912cdfd0b2SMaryam Benimmar relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr);
4922cdfd0b2SMaryam Benimmar if (Error E = RelocationsOrErr.takeError()) {
4932cdfd0b2SMaryam Benimmar // TODO: report the error up the stack.
4942cdfd0b2SMaryam Benimmar consumeError(std::move(E));
4952cdfd0b2SMaryam Benimmar return relocation_iterator(RelocationRef());
4962cdfd0b2SMaryam Benimmar }
497d60d7d69Sjasonliu Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
4982cdfd0b2SMaryam Benimmar } else {
4992cdfd0b2SMaryam Benimmar const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
5002cdfd0b2SMaryam Benimmar auto RelocationsOrErr =
5012cdfd0b2SMaryam Benimmar relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr);
5022cdfd0b2SMaryam Benimmar if (Error E = RelocationsOrErr.takeError()) {
5032cdfd0b2SMaryam Benimmar // TODO: report the error up the stack.
5042cdfd0b2SMaryam Benimmar consumeError(std::move(E));
5052cdfd0b2SMaryam Benimmar return relocation_iterator(RelocationRef());
5062cdfd0b2SMaryam Benimmar }
5072cdfd0b2SMaryam Benimmar Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
5082cdfd0b2SMaryam Benimmar }
509d60d7d69Sjasonliu return relocation_iterator(RelocationRef(Ret, this));
510ab2eb2bfSHubert Tong }
511ab2eb2bfSHubert Tong
moveRelocationNext(DataRefImpl & Rel) const512ab2eb2bfSHubert Tong void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
5132cdfd0b2SMaryam Benimmar if (is64Bit())
5142cdfd0b2SMaryam Benimmar Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation64>(Rel.p) + 1);
5152cdfd0b2SMaryam Benimmar else
516d60d7d69Sjasonliu Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1);
517ab2eb2bfSHubert Tong }
518ab2eb2bfSHubert Tong
getRelocationOffset(DataRefImpl Rel) const519ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
5202cdfd0b2SMaryam Benimmar if (is64Bit()) {
5212cdfd0b2SMaryam Benimmar const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
5222cdfd0b2SMaryam Benimmar const XCOFFSectionHeader64 *Sec64 = sectionHeaderTable64();
5232cdfd0b2SMaryam Benimmar const uint64_t RelocAddress = Reloc->VirtualAddress;
5242cdfd0b2SMaryam Benimmar const uint16_t NumberOfSections = getNumberOfSections();
5252cdfd0b2SMaryam Benimmar for (uint16_t I = 0; I < NumberOfSections; ++I) {
5262cdfd0b2SMaryam Benimmar // Find which section this relocation belongs to, and get the
5272cdfd0b2SMaryam Benimmar // relocation offset relative to the start of the section.
5282cdfd0b2SMaryam Benimmar if (Sec64->VirtualAddress <= RelocAddress &&
5292cdfd0b2SMaryam Benimmar RelocAddress < Sec64->VirtualAddress + Sec64->SectionSize) {
5302cdfd0b2SMaryam Benimmar return RelocAddress - Sec64->VirtualAddress;
5312cdfd0b2SMaryam Benimmar }
5322cdfd0b2SMaryam Benimmar ++Sec64;
5332cdfd0b2SMaryam Benimmar }
5342cdfd0b2SMaryam Benimmar } else {
535d60d7d69Sjasonliu const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
536d60d7d69Sjasonliu const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32();
537d60d7d69Sjasonliu const uint32_t RelocAddress = Reloc->VirtualAddress;
538d60d7d69Sjasonliu const uint16_t NumberOfSections = getNumberOfSections();
5392cdfd0b2SMaryam Benimmar for (uint16_t I = 0; I < NumberOfSections; ++I) {
5402cdfd0b2SMaryam Benimmar // Find which section this relocation belongs to, and get the
541d60d7d69Sjasonliu // relocation offset relative to the start of the section.
542d60d7d69Sjasonliu if (Sec32->VirtualAddress <= RelocAddress &&
543d60d7d69Sjasonliu RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) {
544d60d7d69Sjasonliu return RelocAddress - Sec32->VirtualAddress;
545d60d7d69Sjasonliu }
546d60d7d69Sjasonliu ++Sec32;
547d60d7d69Sjasonliu }
5482cdfd0b2SMaryam Benimmar }
549d60d7d69Sjasonliu return InvalidRelocOffset;
550ab2eb2bfSHubert Tong }
551ab2eb2bfSHubert Tong
getRelocationSymbol(DataRefImpl Rel) const552ab2eb2bfSHubert Tong symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
5532cdfd0b2SMaryam Benimmar uint32_t Index;
5542cdfd0b2SMaryam Benimmar if (is64Bit()) {
5552cdfd0b2SMaryam Benimmar const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
5562cdfd0b2SMaryam Benimmar Index = Reloc->SymbolIndex;
5572cdfd0b2SMaryam Benimmar
5582cdfd0b2SMaryam Benimmar if (Index >= getNumberOfSymbolTableEntries64())
5592cdfd0b2SMaryam Benimmar return symbol_end();
5602cdfd0b2SMaryam Benimmar } else {
561d60d7d69Sjasonliu const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
5622cdfd0b2SMaryam Benimmar Index = Reloc->SymbolIndex;
563d60d7d69Sjasonliu
564d60d7d69Sjasonliu if (Index >= getLogicalNumberOfSymbolTableEntries32())
565d60d7d69Sjasonliu return symbol_end();
5662cdfd0b2SMaryam Benimmar }
567d60d7d69Sjasonliu DataRefImpl SymDRI;
5688e84311aSjasonliu SymDRI.p = getSymbolEntryAddressByIndex(Index);
569d60d7d69Sjasonliu return symbol_iterator(SymbolRef(SymDRI, this));
570ab2eb2bfSHubert Tong }
571ab2eb2bfSHubert Tong
getRelocationType(DataRefImpl Rel) const572ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const {
573d60d7d69Sjasonliu if (is64Bit())
5742cdfd0b2SMaryam Benimmar return viewAs<XCOFFRelocation64>(Rel.p)->Type;
575d60d7d69Sjasonliu return viewAs<XCOFFRelocation32>(Rel.p)->Type;
576ab2eb2bfSHubert Tong }
577ab2eb2bfSHubert Tong
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const578ab2eb2bfSHubert Tong void XCOFFObjectFile::getRelocationTypeName(
579ab2eb2bfSHubert Tong DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
5802cdfd0b2SMaryam Benimmar StringRef Res;
5812cdfd0b2SMaryam Benimmar if (is64Bit()) {
5822cdfd0b2SMaryam Benimmar const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
5832cdfd0b2SMaryam Benimmar Res = XCOFF::getRelocationTypeString(Reloc->Type);
5842cdfd0b2SMaryam Benimmar } else {
585d60d7d69Sjasonliu const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
5862cdfd0b2SMaryam Benimmar Res = XCOFF::getRelocationTypeString(Reloc->Type);
5872cdfd0b2SMaryam Benimmar }
588d60d7d69Sjasonliu Result.append(Res.begin(), Res.end());
589ab2eb2bfSHubert Tong }
590ab2eb2bfSHubert Tong
getSymbolFlags(DataRefImpl Symb) const591ac00376aSvgxbj Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
5925b44c716Szhijian XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
5935b44c716Szhijian uint32_t Result = SymbolRef::SF_None;
5945b44c716Szhijian
5955b44c716Szhijian if (XCOFFSym.getSectionNumber() == XCOFF::N_ABS)
5965b44c716Szhijian Result |= SymbolRef::SF_Absolute;
5975b44c716Szhijian
5985b44c716Szhijian XCOFF::StorageClass SC = XCOFFSym.getStorageClass();
5995b44c716Szhijian if (XCOFF::C_EXT == SC || XCOFF::C_WEAKEXT == SC)
6005b44c716Szhijian Result |= SymbolRef::SF_Global;
6015b44c716Szhijian
6025b44c716Szhijian if (XCOFF::C_WEAKEXT == SC)
6035b44c716Szhijian Result |= SymbolRef::SF_Weak;
6045b44c716Szhijian
6055b44c716Szhijian if (XCOFFSym.isCsectSymbol()) {
6065b44c716Szhijian Expected<XCOFFCsectAuxRef> CsectAuxEntOrErr =
6075b44c716Szhijian XCOFFSym.getXCOFFCsectAuxRef();
6085b44c716Szhijian if (CsectAuxEntOrErr) {
6095b44c716Szhijian if (CsectAuxEntOrErr.get().getSymbolType() == XCOFF::XTY_CM)
6105b44c716Szhijian Result |= SymbolRef::SF_Common;
6115b44c716Szhijian } else
6125b44c716Szhijian return CsectAuxEntOrErr.takeError();
6135b44c716Szhijian }
6145b44c716Szhijian
6155b44c716Szhijian if (XCOFFSym.getSectionNumber() == XCOFF::N_UNDEF)
6165b44c716Szhijian Result |= SymbolRef::SF_Undefined;
6175b44c716Szhijian
618fd3ba1f8Szhijian // There is no visibility in old 32 bit XCOFF object file interpret.
619fd3ba1f8Szhijian if (is64Bit() || (auxiliaryHeader32() && (auxiliaryHeader32()->getVersion() ==
620fd3ba1f8Szhijian NEW_XCOFF_INTERPRET))) {
621fd3ba1f8Szhijian uint16_t SymType = XCOFFSym.getSymbolType();
622fd3ba1f8Szhijian if ((SymType & VISIBILITY_MASK) == SYM_V_HIDDEN)
623fd3ba1f8Szhijian Result |= SymbolRef::SF_Hidden;
624fd3ba1f8Szhijian
625fd3ba1f8Szhijian if ((SymType & VISIBILITY_MASK) == SYM_V_EXPORTED)
626fd3ba1f8Szhijian Result |= SymbolRef::SF_Exported;
627fd3ba1f8Szhijian }
628ab2eb2bfSHubert Tong return Result;
629ab2eb2bfSHubert Tong }
630ab2eb2bfSHubert Tong
symbol_begin() const631ab2eb2bfSHubert Tong basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
6329212206dSJason Liu DataRefImpl SymDRI;
6339212206dSJason Liu SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr);
6349212206dSJason Liu return basic_symbol_iterator(SymbolRef(SymDRI, this));
635ab2eb2bfSHubert Tong }
636ab2eb2bfSHubert Tong
symbol_end() const637ab2eb2bfSHubert Tong basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
6389212206dSJason Liu DataRefImpl SymDRI;
6398e84311aSjasonliu const uint32_t NumberOfSymbolTableEntries = getNumberOfSymbolTableEntries();
6408e84311aSjasonliu SymDRI.p = getSymbolEntryAddressByIndex(NumberOfSymbolTableEntries);
6419212206dSJason Liu return basic_symbol_iterator(SymbolRef(SymDRI, this));
642ab2eb2bfSHubert Tong }
643ab2eb2bfSHubert Tong
section_begin() const644ab2eb2bfSHubert Tong section_iterator XCOFFObjectFile::section_begin() const {
645a93a33cbSSean Fertile DataRefImpl DRI;
646837ae69fSSean Fertile DRI.p = getSectionHeaderTableAddress();
647a93a33cbSSean Fertile return section_iterator(SectionRef(DRI, this));
648ab2eb2bfSHubert Tong }
649ab2eb2bfSHubert Tong
section_end() const650ab2eb2bfSHubert Tong section_iterator XCOFFObjectFile::section_end() const {
651a93a33cbSSean Fertile DataRefImpl DRI;
652837ae69fSSean Fertile DRI.p = getWithOffset(getSectionHeaderTableAddress(),
653837ae69fSSean Fertile getNumberOfSections() * getSectionHeaderSize());
654a93a33cbSSean Fertile return section_iterator(SectionRef(DRI, this));
655ab2eb2bfSHubert Tong }
656ab2eb2bfSHubert Tong
getBytesInAddress() const657837ae69fSSean Fertile uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; }
658ab2eb2bfSHubert Tong
getFileFormatName() const659ab2eb2bfSHubert Tong StringRef XCOFFObjectFile::getFileFormatName() const {
660837ae69fSSean Fertile return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000";
661ab2eb2bfSHubert Tong }
662ab2eb2bfSHubert Tong
getArch() const663ab2eb2bfSHubert Tong Triple::ArchType XCOFFObjectFile::getArch() const {
664837ae69fSSean Fertile return is64Bit() ? Triple::ppc64 : Triple::ppc;
665ab2eb2bfSHubert Tong }
666ab2eb2bfSHubert Tong
getFeatures() const667ab2eb2bfSHubert Tong SubtargetFeatures XCOFFObjectFile::getFeatures() const {
668ab2eb2bfSHubert Tong return SubtargetFeatures();
669ab2eb2bfSHubert Tong }
670ab2eb2bfSHubert Tong
isRelocatableObject() const671ab2eb2bfSHubert Tong bool XCOFFObjectFile::isRelocatableObject() const {
672d60d7d69Sjasonliu if (is64Bit())
6738ec73e96SAmir Ayupov return !(fileHeader64()->Flags & NoRelMask);
674d60d7d69Sjasonliu return !(fileHeader32()->Flags & NoRelMask);
675ab2eb2bfSHubert Tong }
676ab2eb2bfSHubert Tong
getStartAddress() const677a93a33cbSSean Fertile Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
678a93a33cbSSean Fertile // TODO FIXME Should get from auxiliary_header->o_entry when support for the
679a93a33cbSSean Fertile // auxiliary_header is added.
680a93a33cbSSean Fertile return 0;
681a93a33cbSSean Fertile }
682a93a33cbSSean Fertile
mapDebugSectionName(StringRef Name) const683d33b016aSChen Zheng StringRef XCOFFObjectFile::mapDebugSectionName(StringRef Name) const {
684d33b016aSChen Zheng return StringSwitch<StringRef>(Name)
685d33b016aSChen Zheng .Case("dwinfo", "debug_info")
686d33b016aSChen Zheng .Case("dwline", "debug_line")
687d33b016aSChen Zheng .Case("dwpbnms", "debug_pubnames")
688d33b016aSChen Zheng .Case("dwpbtyp", "debug_pubtypes")
689d33b016aSChen Zheng .Case("dwarnge", "debug_aranges")
690d33b016aSChen Zheng .Case("dwabrev", "debug_abbrev")
691d33b016aSChen Zheng .Case("dwstr", "debug_str")
692d33b016aSChen Zheng .Case("dwrnges", "debug_ranges")
693d33b016aSChen Zheng .Case("dwloc", "debug_loc")
694d33b016aSChen Zheng .Case("dwframe", "debug_frame")
695d33b016aSChen Zheng .Case("dwmac", "debug_macinfo")
696d33b016aSChen Zheng .Default(Name);
697d33b016aSChen Zheng }
698d33b016aSChen Zheng
getFileHeaderSize() const699837ae69fSSean Fertile size_t XCOFFObjectFile::getFileHeaderSize() const {
700837ae69fSSean Fertile return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32);
7019212206dSJason Liu }
7029212206dSJason Liu
getSectionHeaderSize() const703837ae69fSSean Fertile size_t XCOFFObjectFile::getSectionHeaderSize() const {
704837ae69fSSean Fertile return is64Bit() ? sizeof(XCOFFSectionHeader64) :
705837ae69fSSean Fertile sizeof(XCOFFSectionHeader32);
706837ae69fSSean Fertile }
707837ae69fSSean Fertile
is64Bit() const708837ae69fSSean Fertile bool XCOFFObjectFile::is64Bit() const {
709837ae69fSSean Fertile return Binary::ID_XCOFF64 == getType();
710837ae69fSSean Fertile }
711837ae69fSSean Fertile
getRawData(const char * Start,uint64_t Size,StringRef Name) const71261835d19Sesmeyi Expected<StringRef> XCOFFObjectFile::getRawData(const char *Start,
71361835d19Sesmeyi uint64_t Size,
71461835d19Sesmeyi StringRef Name) const {
71561835d19Sesmeyi uintptr_t StartPtr = reinterpret_cast<uintptr_t>(Start);
71661835d19Sesmeyi // TODO: this path is untested.
71761835d19Sesmeyi if (Error E = Binary::checkOffset(Data, StartPtr, Size))
71861835d19Sesmeyi return createError(toString(std::move(E)) + ": " + Name.data() +
71961835d19Sesmeyi " data with offset 0x" + Twine::utohexstr(StartPtr) +
72061835d19Sesmeyi " and size 0x" + Twine::utohexstr(Size) +
72161835d19Sesmeyi " goes past the end of the file");
72261835d19Sesmeyi return StringRef(Start, Size);
72361835d19Sesmeyi }
72461835d19Sesmeyi
getMagic() const725837ae69fSSean Fertile uint16_t XCOFFObjectFile::getMagic() const {
726837ae69fSSean Fertile return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic;
727837ae69fSSean Fertile }
728837ae69fSSean Fertile
getSectionByNum(int16_t Num) const729837ae69fSSean Fertile Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
730837ae69fSSean Fertile if (Num <= 0 || Num > getNumberOfSections())
731b98c3e95SEsme-Yi return createStringError(object_error::invalid_section_index,
732b98c3e95SEsme-Yi "the section index (" + Twine(Num) +
733b98c3e95SEsme-Yi ") is invalid");
734837ae69fSSean Fertile
735837ae69fSSean Fertile DataRefImpl DRI;
736837ae69fSSean Fertile DRI.p = getWithOffset(getSectionHeaderTableAddress(),
737837ae69fSSean Fertile getSectionHeaderSize() * (Num - 1));
738837ae69fSSean Fertile return DRI;
7399212206dSJason Liu }
7409212206dSJason Liu
7419212206dSJason Liu Expected<StringRef>
getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const7428e84311aSjasonliu XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const {
7438e84311aSjasonliu const int16_t SectionNum = SymEntPtr.getSectionNumber();
7449212206dSJason Liu
7459212206dSJason Liu switch (SectionNum) {
7469212206dSJason Liu case XCOFF::N_DEBUG:
7479212206dSJason Liu return "N_DEBUG";
7489212206dSJason Liu case XCOFF::N_ABS:
7499212206dSJason Liu return "N_ABS";
7509212206dSJason Liu case XCOFF::N_UNDEF:
7519212206dSJason Liu return "N_UNDEF";
752837ae69fSSean Fertile default:
753837ae69fSSean Fertile Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum);
754837ae69fSSean Fertile if (SecRef)
7557c72e82bSJason Liu return generateXCOFFFixedNameStringRef(
7567c72e82bSJason Liu getSectionNameInternal(SecRef.get()));
757837ae69fSSean Fertile return SecRef.takeError();
7589212206dSJason Liu }
7599212206dSJason Liu }
7609212206dSJason Liu
getSymbolSectionID(SymbolRef Sym) const7618a23f74eSEsme-Yi unsigned XCOFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
7628a23f74eSEsme-Yi XCOFFSymbolRef XCOFFSymRef(Sym.getRawDataRefImpl(), this);
7638a23f74eSEsme-Yi return XCOFFSymRef.getSectionNumber();
7648a23f74eSEsme-Yi }
7658a23f74eSEsme-Yi
isReservedSectionNumber(int16_t SectionNumber)7669212206dSJason Liu bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) {
7679212206dSJason Liu return (SectionNumber <= 0 && SectionNumber >= -2);
7689212206dSJason Liu }
7699212206dSJason Liu
getNumberOfSections() const7709212206dSJason Liu uint16_t XCOFFObjectFile::getNumberOfSections() const {
771837ae69fSSean Fertile return is64Bit() ? fileHeader64()->NumberOfSections
772837ae69fSSean Fertile : fileHeader32()->NumberOfSections;
7739212206dSJason Liu }
7749212206dSJason Liu
getTimeStamp() const775837ae69fSSean Fertile int32_t XCOFFObjectFile::getTimeStamp() const {
776837ae69fSSean Fertile return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp;
7779212206dSJason Liu }
7789212206dSJason Liu
getOptionalHeaderSize() const7799212206dSJason Liu uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
780837ae69fSSean Fertile return is64Bit() ? fileHeader64()->AuxHeaderSize
781837ae69fSSean Fertile : fileHeader32()->AuxHeaderSize;
7829212206dSJason Liu }
7839212206dSJason Liu
getSymbolTableOffset32() const784837ae69fSSean Fertile uint32_t XCOFFObjectFile::getSymbolTableOffset32() const {
785837ae69fSSean Fertile return fileHeader32()->SymbolTableOffset;
786837ae69fSSean Fertile }
787ab2eb2bfSHubert Tong
getRawNumberOfSymbolTableEntries32() const788837ae69fSSean Fertile int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const {
789837ae69fSSean Fertile // As far as symbol table size is concerned, if this field is negative it is
790837ae69fSSean Fertile // to be treated as a 0. However since this field is also used for printing we
791837ae69fSSean Fertile // don't want to truncate any negative values.
792837ae69fSSean Fertile return fileHeader32()->NumberOfSymTableEntries;
793837ae69fSSean Fertile }
794ab2eb2bfSHubert Tong
getLogicalNumberOfSymbolTableEntries32() const795837ae69fSSean Fertile uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const {
796837ae69fSSean Fertile return (fileHeader32()->NumberOfSymTableEntries >= 0
797837ae69fSSean Fertile ? fileHeader32()->NumberOfSymTableEntries
798837ae69fSSean Fertile : 0);
799837ae69fSSean Fertile }
800a93a33cbSSean Fertile
getSymbolTableOffset64() const801837ae69fSSean Fertile uint64_t XCOFFObjectFile::getSymbolTableOffset64() const {
802837ae69fSSean Fertile return fileHeader64()->SymbolTableOffset;
803837ae69fSSean Fertile }
804837ae69fSSean Fertile
getNumberOfSymbolTableEntries64() const805837ae69fSSean Fertile uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
806837ae69fSSean Fertile return fileHeader64()->NumberOfSymTableEntries;
807837ae69fSSean Fertile }
808837ae69fSSean Fertile
getNumberOfSymbolTableEntries() const8098e84311aSjasonliu uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const {
8108e84311aSjasonliu return is64Bit() ? getNumberOfSymbolTableEntries64()
8117c72e82bSJason Liu : getLogicalNumberOfSymbolTableEntries32();
8128e84311aSjasonliu }
8138e84311aSjasonliu
getEndOfSymbolTableAddress() const8148e84311aSjasonliu uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const {
8158e84311aSjasonliu const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
8167c72e82bSJason Liu return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr),
8177c72e82bSJason Liu XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries);
8187c72e82bSJason Liu }
8197c72e82bSJason Liu
checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const8207c72e82bSJason Liu void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const {
8217c72e82bSJason Liu if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr))
8227c72e82bSJason Liu report_fatal_error("Symbol table entry is outside of symbol table.");
8237c72e82bSJason Liu
8247c72e82bSJason Liu if (SymbolEntPtr >= getEndOfSymbolTableAddress())
8257c72e82bSJason Liu report_fatal_error("Symbol table entry is outside of symbol table.");
8267c72e82bSJason Liu
8277c72e82bSJason Liu ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) -
8287c72e82bSJason Liu reinterpret_cast<const char *>(SymbolTblPtr);
8297c72e82bSJason Liu
8307c72e82bSJason Liu if (Offset % XCOFF::SymbolTableEntrySize != 0)
8317c72e82bSJason Liu report_fatal_error(
8327c72e82bSJason Liu "Symbol table entry position is not valid inside of symbol table.");
8337c72e82bSJason Liu }
8347c72e82bSJason Liu
getSymbolIndex(uintptr_t SymbolEntPtr) const8357c72e82bSJason Liu uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const {
8367c72e82bSJason Liu return (reinterpret_cast<const char *>(SymbolEntPtr) -
8377c72e82bSJason Liu reinterpret_cast<const char *>(SymbolTblPtr)) /
8387c72e82bSJason Liu XCOFF::SymbolTableEntrySize;
8397c72e82bSJason Liu }
8407c72e82bSJason Liu
getSymbolSize(DataRefImpl Symb) const8415b44c716Szhijian uint64_t XCOFFObjectFile::getSymbolSize(DataRefImpl Symb) const {
8425b44c716Szhijian uint64_t Result = 0;
8435b44c716Szhijian XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
8445b44c716Szhijian if (XCOFFSym.isCsectSymbol()) {
8455b44c716Szhijian Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
8465b44c716Szhijian XCOFFSym.getXCOFFCsectAuxRef();
8475b44c716Szhijian if (!CsectAuxRefOrError)
8485b44c716Szhijian // TODO: report the error up the stack.
8495b44c716Szhijian consumeError(CsectAuxRefOrError.takeError());
8505b44c716Szhijian else {
8515b44c716Szhijian XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get();
8525b44c716Szhijian uint8_t SymType = CsectAuxRef.getSymbolType();
8535b44c716Szhijian if (SymType == XCOFF::XTY_SD || SymType == XCOFF::XTY_CM)
8545b44c716Szhijian Result = CsectAuxRef.getSectionOrLength();
8555b44c716Szhijian }
8565b44c716Szhijian }
8575b44c716Szhijian return Result;
8585b44c716Szhijian }
8595b44c716Szhijian
getSymbolEntryAddressByIndex(uint32_t Index) const8608e84311aSjasonliu uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const {
8618e84311aSjasonliu return getAdvancedSymbolEntryAddress(
8628e84311aSjasonliu reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index);
8638e84311aSjasonliu }
8648e84311aSjasonliu
86534d4bff3SDigger Lin Expected<StringRef>
getSymbolNameByIndex(uint32_t Index) const86634d4bff3SDigger Lin XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const {
8678e84311aSjasonliu const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
86834d4bff3SDigger Lin
8698e84311aSjasonliu if (Index >= NumberOfSymTableEntries)
870a00ff716SEsme-Yi return createError("symbol index " + Twine(Index) +
871a00ff716SEsme-Yi " exceeds symbol count " +
872a00ff716SEsme-Yi Twine(NumberOfSymTableEntries));
87334d4bff3SDigger Lin
87434d4bff3SDigger Lin DataRefImpl SymDRI;
8758e84311aSjasonliu SymDRI.p = getSymbolEntryAddressByIndex(Index);
87634d4bff3SDigger Lin return getSymbolName(SymDRI);
87734d4bff3SDigger Lin }
87834d4bff3SDigger Lin
getFlags() const879837ae69fSSean Fertile uint16_t XCOFFObjectFile::getFlags() const {
880837ae69fSSean Fertile return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags;
881837ae69fSSean Fertile }
882837ae69fSSean Fertile
getSectionNameInternal(DataRefImpl Sec) const883837ae69fSSean Fertile const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const {
884837ae69fSSean Fertile return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name;
885837ae69fSSean Fertile }
886837ae69fSSean Fertile
getSectionHeaderTableAddress() const887837ae69fSSean Fertile uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const {
888837ae69fSSean Fertile return reinterpret_cast<uintptr_t>(SectionHeaderTable);
889837ae69fSSean Fertile }
890837ae69fSSean Fertile
getSectionFlags(DataRefImpl Sec) const891837ae69fSSean Fertile int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const {
892837ae69fSSean Fertile return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags;
893837ae69fSSean Fertile }
894837ae69fSSean Fertile
XCOFFObjectFile(unsigned int Type,MemoryBufferRef Object)895837ae69fSSean Fertile XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object)
896837ae69fSSean Fertile : ObjectFile(Type, Object) {
897837ae69fSSean Fertile assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64);
898837ae69fSSean Fertile }
899837ae69fSSean Fertile
sections64() const900837ae69fSSean Fertile ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const {
901837ae69fSSean Fertile assert(is64Bit() && "64-bit interface called for non 64-bit file.");
902837ae69fSSean Fertile const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64();
903837ae69fSSean Fertile return ArrayRef<XCOFFSectionHeader64>(TablePtr,
904837ae69fSSean Fertile TablePtr + getNumberOfSections());
905837ae69fSSean Fertile }
906837ae69fSSean Fertile
sections32() const907837ae69fSSean Fertile ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const {
908837ae69fSSean Fertile assert(!is64Bit() && "32-bit interface called for non 32-bit file.");
909837ae69fSSean Fertile const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32();
910837ae69fSSean Fertile return ArrayRef<XCOFFSectionHeader32>(TablePtr,
911837ae69fSSean Fertile TablePtr + getNumberOfSections());
912837ae69fSSean Fertile }
913837ae69fSSean Fertile
91434d4bff3SDigger Lin // In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO
91534d4bff3SDigger Lin // section header contains the actual count of relocation entries in the s_paddr
91634d4bff3SDigger Lin // field. STYP_OVRFLO headers contain the section index of their corresponding
91734d4bff3SDigger Lin // sections as their raw "NumberOfRelocations" field value.
9182cdfd0b2SMaryam Benimmar template <typename T>
getNumberOfRelocationEntries(const XCOFFSectionHeader<T> & Sec) const9192cdfd0b2SMaryam Benimmar Expected<uint32_t> XCOFFObjectFile::getNumberOfRelocationEntries(
9202cdfd0b2SMaryam Benimmar const XCOFFSectionHeader<T> &Sec) const {
9212cdfd0b2SMaryam Benimmar const T &Section = static_cast<const T &>(Sec);
9222cdfd0b2SMaryam Benimmar if (is64Bit())
9232cdfd0b2SMaryam Benimmar return Section.NumberOfRelocations;
92434d4bff3SDigger Lin
9252cdfd0b2SMaryam Benimmar uint16_t SectionIndex = &Section - sectionHeaderTable<T>() + 1;
9262cdfd0b2SMaryam Benimmar if (Section.NumberOfRelocations < XCOFF::RelocOverflow)
9272cdfd0b2SMaryam Benimmar return Section.NumberOfRelocations;
92834d4bff3SDigger Lin for (const auto &Sec : sections32()) {
92934d4bff3SDigger Lin if (Sec.Flags == XCOFF::STYP_OVRFLO &&
93034d4bff3SDigger Lin Sec.NumberOfRelocations == SectionIndex)
93134d4bff3SDigger Lin return Sec.PhysicalAddress;
93234d4bff3SDigger Lin }
93334d4bff3SDigger Lin return errorCodeToError(object_error::parse_failed);
93434d4bff3SDigger Lin }
93534d4bff3SDigger Lin
9362cdfd0b2SMaryam Benimmar template <typename Shdr, typename Reloc>
relocations(const Shdr & Sec) const9372cdfd0b2SMaryam Benimmar Expected<ArrayRef<Reloc>> XCOFFObjectFile::relocations(const Shdr &Sec) const {
93834d4bff3SDigger Lin uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader),
93934d4bff3SDigger Lin Sec.FileOffsetToRelocationInfo);
9402cdfd0b2SMaryam Benimmar auto NumRelocEntriesOrErr = getNumberOfRelocationEntries(Sec);
94134d4bff3SDigger Lin if (Error E = NumRelocEntriesOrErr.takeError())
942c55cf4afSBill Wendling return std::move(E);
94334d4bff3SDigger Lin
94434d4bff3SDigger Lin uint32_t NumRelocEntries = NumRelocEntriesOrErr.get();
9452cdfd0b2SMaryam Benimmar static_assert((sizeof(Reloc) == XCOFF::RelocationSerializationSize64 ||
9462cdfd0b2SMaryam Benimmar sizeof(Reloc) == XCOFF::RelocationSerializationSize32),
9472cdfd0b2SMaryam Benimmar "Relocation structure is incorrect");
94834d4bff3SDigger Lin auto RelocationOrErr =
9492cdfd0b2SMaryam Benimmar getObject<Reloc>(Data, reinterpret_cast<void *>(RelocAddr),
9502cdfd0b2SMaryam Benimmar NumRelocEntries * sizeof(Reloc));
951a00ff716SEsme-Yi if (!RelocationOrErr)
952a00ff716SEsme-Yi return createError(
953a00ff716SEsme-Yi toString(RelocationOrErr.takeError()) + ": relocations with offset 0x" +
954a00ff716SEsme-Yi Twine::utohexstr(Sec.FileOffsetToRelocationInfo) + " and size 0x" +
955a00ff716SEsme-Yi Twine::utohexstr(NumRelocEntries * sizeof(Reloc)) +
956a00ff716SEsme-Yi " go past the end of the file");
95734d4bff3SDigger Lin
9582cdfd0b2SMaryam Benimmar const Reloc *StartReloc = RelocationOrErr.get();
95934d4bff3SDigger Lin
9602cdfd0b2SMaryam Benimmar return ArrayRef<Reloc>(StartReloc, StartReloc + NumRelocEntries);
96134d4bff3SDigger Lin }
96234d4bff3SDigger Lin
963837ae69fSSean Fertile Expected<XCOFFStringTable>
parseStringTable(const XCOFFObjectFile * Obj,uint64_t Offset)964837ae69fSSean Fertile XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
965837ae69fSSean Fertile // If there is a string table, then the buffer must contain at least 4 bytes
966837ae69fSSean Fertile // for the string table's size. Not having a string table is not an error.
967e03a135bSReid Kleckner if (Error E = Binary::checkOffset(
968e03a135bSReid Kleckner Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) {
969e03a135bSReid Kleckner consumeError(std::move(E));
970837ae69fSSean Fertile return XCOFFStringTable{0, nullptr};
971e03a135bSReid Kleckner }
972837ae69fSSean Fertile
973837ae69fSSean Fertile // Read the size out of the buffer.
974837ae69fSSean Fertile uint32_t Size = support::endian::read32be(Obj->base() + Offset);
975837ae69fSSean Fertile
976837ae69fSSean Fertile // If the size is less then 4, then the string table is just a size and no
977837ae69fSSean Fertile // string data.
978837ae69fSSean Fertile if (Size <= 4)
979837ae69fSSean Fertile return XCOFFStringTable{4, nullptr};
980837ae69fSSean Fertile
981837ae69fSSean Fertile auto StringTableOrErr =
982837ae69fSSean Fertile getObject<char>(Obj->Data, Obj->base() + Offset, Size);
983a00ff716SEsme-Yi if (!StringTableOrErr)
984a00ff716SEsme-Yi return createError(toString(StringTableOrErr.takeError()) +
985a00ff716SEsme-Yi ": string table with offset 0x" +
986a00ff716SEsme-Yi Twine::utohexstr(Offset) + " and size 0x" +
987a00ff716SEsme-Yi Twine::utohexstr(Size) +
988a00ff716SEsme-Yi " goes past the end of the file");
989837ae69fSSean Fertile
990837ae69fSSean Fertile const char *StringTablePtr = StringTableOrErr.get();
991837ae69fSSean Fertile if (StringTablePtr[Size - 1] != '\0')
992837ae69fSSean Fertile return errorCodeToError(object_error::string_table_non_null_end);
993837ae69fSSean Fertile
994837ae69fSSean Fertile return XCOFFStringTable{Size, StringTablePtr};
995837ae69fSSean Fertile }
996837ae69fSSean Fertile
997b21ed75eSEsme-Yi // This function returns the import file table. Each entry in the import file
998b21ed75eSEsme-Yi // table consists of: "path_name\0base_name\0archive_member_name\0".
getImportFileTable() const999b21ed75eSEsme-Yi Expected<StringRef> XCOFFObjectFile::getImportFileTable() const {
1000b21ed75eSEsme-Yi Expected<uintptr_t> LoaderSectionAddrOrError = getLoaderSectionAddress();
1001b21ed75eSEsme-Yi if (!LoaderSectionAddrOrError)
1002b21ed75eSEsme-Yi return LoaderSectionAddrOrError.takeError();
1003b21ed75eSEsme-Yi
1004b21ed75eSEsme-Yi uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get();
1005b21ed75eSEsme-Yi if (!LoaderSectionAddr)
1006b21ed75eSEsme-Yi return StringRef();
1007b21ed75eSEsme-Yi
1008b21ed75eSEsme-Yi uint64_t OffsetToImportFileTable = 0;
1009b21ed75eSEsme-Yi uint64_t LengthOfImportFileTable = 0;
1010b21ed75eSEsme-Yi if (is64Bit()) {
1011b21ed75eSEsme-Yi const LoaderSectionHeader64 *LoaderSec64 =
1012b21ed75eSEsme-Yi viewAs<LoaderSectionHeader64>(LoaderSectionAddr);
1013b21ed75eSEsme-Yi OffsetToImportFileTable = LoaderSec64->OffsetToImpid;
1014b21ed75eSEsme-Yi LengthOfImportFileTable = LoaderSec64->LengthOfImpidStrTbl;
1015b21ed75eSEsme-Yi } else {
1016b21ed75eSEsme-Yi const LoaderSectionHeader32 *LoaderSec32 =
1017b21ed75eSEsme-Yi viewAs<LoaderSectionHeader32>(LoaderSectionAddr);
1018b21ed75eSEsme-Yi OffsetToImportFileTable = LoaderSec32->OffsetToImpid;
1019b21ed75eSEsme-Yi LengthOfImportFileTable = LoaderSec32->LengthOfImpidStrTbl;
1020b21ed75eSEsme-Yi }
1021b21ed75eSEsme-Yi
1022b21ed75eSEsme-Yi auto ImportTableOrErr = getObject<char>(
1023b21ed75eSEsme-Yi Data,
1024b21ed75eSEsme-Yi reinterpret_cast<void *>(LoaderSectionAddr + OffsetToImportFileTable),
1025b21ed75eSEsme-Yi LengthOfImportFileTable);
1026a00ff716SEsme-Yi if (!ImportTableOrErr)
1027a00ff716SEsme-Yi return createError(
1028a00ff716SEsme-Yi toString(ImportTableOrErr.takeError()) +
1029a00ff716SEsme-Yi ": import file table with offset 0x" +
1030a00ff716SEsme-Yi Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) +
1031a00ff716SEsme-Yi " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) +
1032a00ff716SEsme-Yi " goes past the end of the file");
1033b21ed75eSEsme-Yi
1034b21ed75eSEsme-Yi const char *ImportTablePtr = ImportTableOrErr.get();
1035b21ed75eSEsme-Yi if (ImportTablePtr[LengthOfImportFileTable - 1] != '\0')
1036a00ff716SEsme-Yi return createError(
1037a00ff716SEsme-Yi ": import file name table with offset 0x" +
1038a00ff716SEsme-Yi Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) +
1039a00ff716SEsme-Yi " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) +
1040a00ff716SEsme-Yi " must end with a null terminator");
1041b21ed75eSEsme-Yi
1042b21ed75eSEsme-Yi return StringRef(ImportTablePtr, LengthOfImportFileTable);
1043b21ed75eSEsme-Yi }
1044b21ed75eSEsme-Yi
1045837ae69fSSean Fertile Expected<std::unique_ptr<XCOFFObjectFile>>
create(unsigned Type,MemoryBufferRef MBR)1046837ae69fSSean Fertile XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
10470eaee545SJonas Devlieghere // Can't use std::make_unique because of the private constructor.
1048837ae69fSSean Fertile std::unique_ptr<XCOFFObjectFile> Obj;
1049837ae69fSSean Fertile Obj.reset(new XCOFFObjectFile(Type, MBR));
1050837ae69fSSean Fertile
1051837ae69fSSean Fertile uint64_t CurOffset = 0;
1052837ae69fSSean Fertile const auto *Base = Obj->base();
1053837ae69fSSean Fertile MemoryBufferRef Data = Obj->Data;
1054837ae69fSSean Fertile
1055837ae69fSSean Fertile // Parse file header.
1056837ae69fSSean Fertile auto FileHeaderOrErr =
1057837ae69fSSean Fertile getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize());
1058837ae69fSSean Fertile if (Error E = FileHeaderOrErr.takeError())
1059c55cf4afSBill Wendling return std::move(E);
1060837ae69fSSean Fertile Obj->FileHeader = FileHeaderOrErr.get();
1061837ae69fSSean Fertile
1062837ae69fSSean Fertile CurOffset += Obj->getFileHeaderSize();
1063158083f0Szhijian
1064158083f0Szhijian if (Obj->getOptionalHeaderSize()) {
1065158083f0Szhijian auto AuxiliaryHeaderOrErr =
1066158083f0Szhijian getObject<void>(Data, Base + CurOffset, Obj->getOptionalHeaderSize());
1067158083f0Szhijian if (Error E = AuxiliaryHeaderOrErr.takeError())
1068158083f0Szhijian return std::move(E);
1069158083f0Szhijian Obj->AuxiliaryHeader = AuxiliaryHeaderOrErr.get();
1070158083f0Szhijian }
1071158083f0Szhijian
1072837ae69fSSean Fertile CurOffset += Obj->getOptionalHeaderSize();
1073a93a33cbSSean Fertile
1074837ae69fSSean Fertile // Parse the section header table if it is present.
1075837ae69fSSean Fertile if (Obj->getNumberOfSections()) {
1076a00ff716SEsme-Yi uint64_t SectionHeadersSize =
1077a00ff716SEsme-Yi Obj->getNumberOfSections() * Obj->getSectionHeaderSize();
1078a00ff716SEsme-Yi auto SecHeadersOrErr =
1079a00ff716SEsme-Yi getObject<void>(Data, Base + CurOffset, SectionHeadersSize);
1080a00ff716SEsme-Yi if (!SecHeadersOrErr)
1081a00ff716SEsme-Yi return createError(toString(SecHeadersOrErr.takeError()) +
1082a00ff716SEsme-Yi ": section headers with offset 0x" +
1083a00ff716SEsme-Yi Twine::utohexstr(CurOffset) + " and size 0x" +
1084a00ff716SEsme-Yi Twine::utohexstr(SectionHeadersSize) +
1085a00ff716SEsme-Yi " go past the end of the file");
1086a00ff716SEsme-Yi
1087837ae69fSSean Fertile Obj->SectionHeaderTable = SecHeadersOrErr.get();
1088a93a33cbSSean Fertile }
1089ab2eb2bfSHubert Tong
10908e84311aSjasonliu const uint32_t NumberOfSymbolTableEntries =
10918e84311aSjasonliu Obj->getNumberOfSymbolTableEntries();
1092fd75ee91SSean Fertile
1093837ae69fSSean Fertile // If there is no symbol table we are done parsing the memory buffer.
10948e84311aSjasonliu if (NumberOfSymbolTableEntries == 0)
1095c55cf4afSBill Wendling return std::move(Obj);
1096837ae69fSSean Fertile
1097837ae69fSSean Fertile // Parse symbol table.
10988e84311aSjasonliu CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64()
10998e84311aSjasonliu : Obj->getSymbolTableOffset32();
11008e84311aSjasonliu const uint64_t SymbolTableSize =
11018e84311aSjasonliu static_cast<uint64_t>(XCOFF::SymbolTableEntrySize) *
11028e84311aSjasonliu NumberOfSymbolTableEntries;
1103837ae69fSSean Fertile auto SymTableOrErr =
11048e84311aSjasonliu getObject<void *>(Data, Base + CurOffset, SymbolTableSize);
1105a00ff716SEsme-Yi if (!SymTableOrErr)
1106a00ff716SEsme-Yi return createError(
1107a00ff716SEsme-Yi toString(SymTableOrErr.takeError()) + ": symbol table with offset 0x" +
1108a00ff716SEsme-Yi Twine::utohexstr(CurOffset) + " and size 0x" +
1109a00ff716SEsme-Yi Twine::utohexstr(SymbolTableSize) + " goes past the end of the file");
1110a00ff716SEsme-Yi
1111837ae69fSSean Fertile Obj->SymbolTblPtr = SymTableOrErr.get();
1112837ae69fSSean Fertile CurOffset += SymbolTableSize;
1113fd75ee91SSean Fertile
1114837ae69fSSean Fertile // Parse String table.
1115837ae69fSSean Fertile Expected<XCOFFStringTable> StringTableOrErr =
1116837ae69fSSean Fertile parseStringTable(Obj.get(), CurOffset);
1117837ae69fSSean Fertile if (Error E = StringTableOrErr.takeError())
1118c55cf4afSBill Wendling return std::move(E);
1119837ae69fSSean Fertile Obj->StringTable = StringTableOrErr.get();
1120fd75ee91SSean Fertile
1121c55cf4afSBill Wendling return std::move(Obj);
1122fd75ee91SSean Fertile }
1123fd75ee91SSean Fertile
1124ab2eb2bfSHubert Tong Expected<std::unique_ptr<ObjectFile>>
createXCOFFObjectFile(MemoryBufferRef MemBufRef,unsigned FileType)1125837ae69fSSean Fertile ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
1126837ae69fSSean Fertile unsigned FileType) {
1127837ae69fSSean Fertile return XCOFFObjectFile::create(FileType, MemBufRef);
1128ab2eb2bfSHubert Tong }
1129ab2eb2bfSHubert Tong
isFunction() const11308e84311aSjasonliu bool XCOFFSymbolRef::isFunction() const {
11318e84311aSjasonliu if (!isCsectSymbol())
11328e84311aSjasonliu return false;
11338e84311aSjasonliu
11348e84311aSjasonliu if (getSymbolType() & FunctionSym)
11358e84311aSjasonliu return true;
11368e84311aSjasonliu
11378e84311aSjasonliu Expected<XCOFFCsectAuxRef> ExpCsectAuxEnt = getXCOFFCsectAuxRef();
113861106ca7Sesmeyi if (!ExpCsectAuxEnt) {
113961106ca7Sesmeyi // If we could not get the CSECT auxiliary entry, then treat this symbol as
114061106ca7Sesmeyi // if it isn't a function. Consume the error and return `false` to move on.
114161106ca7Sesmeyi consumeError(ExpCsectAuxEnt.takeError());
11428e84311aSjasonliu return false;
114361106ca7Sesmeyi }
11448e84311aSjasonliu
11458e84311aSjasonliu const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get();
11468e84311aSjasonliu
11478e84311aSjasonliu // A function definition should be a label definition.
11488e84311aSjasonliu // FIXME: This is not necessarily the case when -ffunction-sections is
11498e84311aSjasonliu // enabled.
11508e84311aSjasonliu if (!CsectAuxRef.isLabel())
11518e84311aSjasonliu return false;
11528e84311aSjasonliu
11538e84311aSjasonliu if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR)
11548e84311aSjasonliu return false;
11558e84311aSjasonliu
11568e84311aSjasonliu const int16_t SectNum = getSectionNumber();
11578e84311aSjasonliu Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum);
11588e84311aSjasonliu if (!SI) {
11598e84311aSjasonliu // If we could not get the section, then this symbol should not be
11608e84311aSjasonliu // a function. So consume the error and return `false` to move on.
11618e84311aSjasonliu consumeError(SI.takeError());
11628e84311aSjasonliu return false;
11637c72e82bSJason Liu }
11647c72e82bSJason Liu
11658e84311aSjasonliu return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT);
11667c72e82bSJason Liu }
11677c72e82bSJason Liu
isCsectSymbol() const11688e84311aSjasonliu bool XCOFFSymbolRef::isCsectSymbol() const {
11697c72e82bSJason Liu XCOFF::StorageClass SC = getStorageClass();
11707c72e82bSJason Liu return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT ||
11717c72e82bSJason Liu SC == XCOFF::C_HIDEXT);
11727c72e82bSJason Liu }
11737c72e82bSJason Liu
getXCOFFCsectAuxRef() const11748e84311aSjasonliu Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const {
11758e84311aSjasonliu assert(isCsectSymbol() &&
11768e84311aSjasonliu "Calling csect symbol interface with a non-csect symbol.");
11777c72e82bSJason Liu
11788e84311aSjasonliu uint8_t NumberOfAuxEntries = getNumberOfAuxEntries();
11797c72e82bSJason Liu
11808e84311aSjasonliu Expected<StringRef> NameOrErr = getName();
11818e84311aSjasonliu if (auto Err = NameOrErr.takeError())
11828e84311aSjasonliu return std::move(Err);
11837c72e82bSJason Liu
1184a00ff716SEsme-Yi uint32_t SymbolIdx = OwningObjectPtr->getSymbolIndex(getEntryAddress());
11858e84311aSjasonliu if (!NumberOfAuxEntries) {
1186a00ff716SEsme-Yi return createError("csect symbol \"" + *NameOrErr + "\" with index " +
1187a00ff716SEsme-Yi Twine(SymbolIdx) + " contains no auxiliary entry");
11888e84311aSjasonliu }
11897c72e82bSJason Liu
11908e84311aSjasonliu if (!OwningObjectPtr->is64Bit()) {
11918e84311aSjasonliu // In XCOFF32, the csect auxilliary entry is always the last auxiliary
11928e84311aSjasonliu // entry for the symbol.
11938e84311aSjasonliu uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
11948e84311aSjasonliu getEntryAddress(), NumberOfAuxEntries);
11958e84311aSjasonliu return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt32>(AuxAddr));
11968e84311aSjasonliu }
11977c72e82bSJason Liu
11988e84311aSjasonliu // XCOFF64 uses SymbolAuxType to identify the auxiliary entry type.
11998e84311aSjasonliu // We need to iterate through all the auxiliary entries to find it.
12008e84311aSjasonliu for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) {
12018e84311aSjasonliu uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
12028e84311aSjasonliu getEntryAddress(), Index);
12038e84311aSjasonliu if (*OwningObjectPtr->getSymbolAuxType(AuxAddr) ==
12048e84311aSjasonliu XCOFF::SymbolAuxType::AUX_CSECT) {
12058e84311aSjasonliu #ifndef NDEBUG
12068e84311aSjasonliu OwningObjectPtr->checkSymbolEntryPointer(AuxAddr);
12078e84311aSjasonliu #endif
12088e84311aSjasonliu return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr));
12098e84311aSjasonliu }
12108e84311aSjasonliu }
12117c72e82bSJason Liu
1212a00ff716SEsme-Yi return createError(
1213a00ff716SEsme-Yi "a csect auxiliary entry has not been found for symbol \"" + *NameOrErr +
1214a00ff716SEsme-Yi "\" with index " + Twine(SymbolIdx));
12158e84311aSjasonliu }
12167c72e82bSJason Liu
getName() const12178e84311aSjasonliu Expected<StringRef> XCOFFSymbolRef::getName() const {
12188e84311aSjasonliu // A storage class value with the high-order bit on indicates that the name is
12198e84311aSjasonliu // a symbolic debugger stabstring.
12208e84311aSjasonliu if (getStorageClass() & 0x80)
12218e84311aSjasonliu return StringRef("Unimplemented Debug Name");
12228e84311aSjasonliu
12238e84311aSjasonliu if (Entry32) {
12248e84311aSjasonliu if (Entry32->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
12258e84311aSjasonliu return generateXCOFFFixedNameStringRef(Entry32->SymbolName);
12268e84311aSjasonliu
12278e84311aSjasonliu return OwningObjectPtr->getStringTableEntry(Entry32->NameInStrTbl.Offset);
12288e84311aSjasonliu }
12298e84311aSjasonliu
12308e84311aSjasonliu return OwningObjectPtr->getStringTableEntry(Entry64->Offset);
1231ab2eb2bfSHubert Tong }
1232ab2eb2bfSHubert Tong
1233f8622543SFangrui Song // Explictly instantiate template classes.
1234f8622543SFangrui Song template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
1235f8622543SFangrui Song template struct XCOFFSectionHeader<XCOFFSectionHeader64>;
1236f8622543SFangrui Song
12372cdfd0b2SMaryam Benimmar template struct XCOFFRelocation<llvm::support::ubig32_t>;
12382cdfd0b2SMaryam Benimmar template struct XCOFFRelocation<llvm::support::ubig64_t>;
12392cdfd0b2SMaryam Benimmar
12402cdfd0b2SMaryam Benimmar template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation64>>
12412cdfd0b2SMaryam Benimmar llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader64,
12422cdfd0b2SMaryam Benimmar llvm::object::XCOFFRelocation64>(
12432cdfd0b2SMaryam Benimmar llvm::object::XCOFFSectionHeader64 const &) const;
12442cdfd0b2SMaryam Benimmar template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation32>>
12452cdfd0b2SMaryam Benimmar llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader32,
12462cdfd0b2SMaryam Benimmar llvm::object::XCOFFRelocation32>(
12472cdfd0b2SMaryam Benimmar llvm::object::XCOFFSectionHeader32 const &) const;
12482cdfd0b2SMaryam Benimmar
doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes)12492f0d755dSdiggerlin bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) {
12502f0d755dSdiggerlin if (Bytes.size() < 4)
12512f0d755dSdiggerlin return false;
12522f0d755dSdiggerlin
12532f0d755dSdiggerlin return support::endian::read32be(Bytes.data()) == 0;
12542f0d755dSdiggerlin }
12552f0d755dSdiggerlin
1256ab77fa51Sdiggerlin #define GETVALUEWITHMASK(X) (Data & (TracebackTable::X))
1257ab77fa51Sdiggerlin #define GETVALUEWITHMASKSHIFT(X, S) \
1258ab77fa51Sdiggerlin ((Data & (TracebackTable::X)) >> (TracebackTable::S))
12597ed515d1Szhijian
create(StringRef TBvectorStrRef)12607ed515d1Szhijian Expected<TBVectorExt> TBVectorExt::create(StringRef TBvectorStrRef) {
12617ed515d1Szhijian Error Err = Error::success();
12627ed515d1Szhijian TBVectorExt TBTVecExt(TBvectorStrRef, Err);
12637ed515d1Szhijian if (Err)
12647ed515d1Szhijian return std::move(Err);
12657ed515d1Szhijian return TBTVecExt;
12667ed515d1Szhijian }
12677ed515d1Szhijian
TBVectorExt(StringRef TBvectorStrRef,Error & Err)12687ed515d1Szhijian TBVectorExt::TBVectorExt(StringRef TBvectorStrRef, Error &Err) {
12697ed515d1Szhijian const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data());
12707ed515d1Szhijian Data = support::endian::read16be(Ptr);
12717ed515d1Szhijian uint32_t VecParmsTypeValue = support::endian::read32be(Ptr + 2);
12727ed515d1Szhijian unsigned ParmsNum =
12737ed515d1Szhijian GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift);
12747ed515d1Szhijian
12757ed515d1Szhijian ErrorAsOutParameter EAO(&Err);
12767ed515d1Szhijian Expected<SmallString<32>> VecParmsTypeOrError =
12777ed515d1Szhijian parseVectorParmsType(VecParmsTypeValue, ParmsNum);
12787ed515d1Szhijian if (!VecParmsTypeOrError)
12797ed515d1Szhijian Err = VecParmsTypeOrError.takeError();
12807ed515d1Szhijian else
12817ed515d1Szhijian VecParmsInfo = VecParmsTypeOrError.get();
12827ed515d1Szhijian }
12837ed515d1Szhijian
getNumberOfVRSaved() const128485177965Sdiggerlin uint8_t TBVectorExt::getNumberOfVRSaved() const {
1285ab77fa51Sdiggerlin return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift);
1286ab77fa51Sdiggerlin }
1287ab77fa51Sdiggerlin
isVRSavedOnStack() const1288ab77fa51Sdiggerlin bool TBVectorExt::isVRSavedOnStack() const {
1289ab77fa51Sdiggerlin return GETVALUEWITHMASK(IsVRSavedOnStackMask);
1290ab77fa51Sdiggerlin }
1291ab77fa51Sdiggerlin
hasVarArgs() const1292ab77fa51Sdiggerlin bool TBVectorExt::hasVarArgs() const {
1293ab77fa51Sdiggerlin return GETVALUEWITHMASK(HasVarArgsMask);
1294ab77fa51Sdiggerlin }
12957ed515d1Szhijian
getNumberOfVectorParms() const1296ab77fa51Sdiggerlin uint8_t TBVectorExt::getNumberOfVectorParms() const {
1297ab77fa51Sdiggerlin return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask,
1298ab77fa51Sdiggerlin NumberOfVectorParmsShift);
1299ab77fa51Sdiggerlin }
1300ab77fa51Sdiggerlin
hasVMXInstruction() const1301ab77fa51Sdiggerlin bool TBVectorExt::hasVMXInstruction() const {
1302ab77fa51Sdiggerlin return GETVALUEWITHMASK(HasVMXInstructionMask);
1303ab77fa51Sdiggerlin }
1304ab77fa51Sdiggerlin #undef GETVALUEWITHMASK
1305ab77fa51Sdiggerlin #undef GETVALUEWITHMASKSHIFT
1306ab77fa51Sdiggerlin
create(const uint8_t * Ptr,uint64_t & Size)13072f0d755dSdiggerlin Expected<XCOFFTracebackTable> XCOFFTracebackTable::create(const uint8_t *Ptr,
13082f0d755dSdiggerlin uint64_t &Size) {
13092f0d755dSdiggerlin Error Err = Error::success();
13102f0d755dSdiggerlin XCOFFTracebackTable TBT(Ptr, Size, Err);
13112f0d755dSdiggerlin if (Err)
13122f0d755dSdiggerlin return std::move(Err);
13132f0d755dSdiggerlin return TBT;
13142f0d755dSdiggerlin }
13152f0d755dSdiggerlin
XCOFFTracebackTable(const uint8_t * Ptr,uint64_t & Size,Error & Err)13162f0d755dSdiggerlin XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size,
13172f0d755dSdiggerlin Error &Err)
13182f0d755dSdiggerlin : TBPtr(Ptr) {
13192f0d755dSdiggerlin ErrorAsOutParameter EAO(&Err);
13202f0d755dSdiggerlin DataExtractor DE(ArrayRef<uint8_t>(Ptr, Size), /*IsLittleEndian=*/false,
13212f0d755dSdiggerlin /*AddressSize=*/0);
13222f0d755dSdiggerlin DataExtractor::Cursor Cur(/*Offset=*/0);
13232f0d755dSdiggerlin
13242f0d755dSdiggerlin // Skip 8 bytes of mandatory fields.
13252f0d755dSdiggerlin DE.getU64(Cur);
13262f0d755dSdiggerlin
13277ed515d1Szhijian unsigned FixedParmsNum = getNumberOfFixedParms();
13287ed515d1Szhijian unsigned FloatingParmsNum = getNumberOfFPParms();
13297ed515d1Szhijian uint32_t ParamsTypeValue = 0;
13302f0d755dSdiggerlin
13317ed515d1Szhijian // Begin to parse optional fields.
13327ed515d1Szhijian if (Cur && (FixedParmsNum + FloatingParmsNum) > 0)
13337ed515d1Szhijian ParamsTypeValue = DE.getU32(Cur);
13342f0d755dSdiggerlin
13352f0d755dSdiggerlin if (Cur && hasTraceBackTableOffset())
13362f0d755dSdiggerlin TraceBackTableOffset = DE.getU32(Cur);
13372f0d755dSdiggerlin
13382f0d755dSdiggerlin if (Cur && isInterruptHandler())
13392f0d755dSdiggerlin HandlerMask = DE.getU32(Cur);
13402f0d755dSdiggerlin
13412f0d755dSdiggerlin if (Cur && hasControlledStorage()) {
13422f0d755dSdiggerlin NumOfCtlAnchors = DE.getU32(Cur);
13432f0d755dSdiggerlin if (Cur && NumOfCtlAnchors) {
13442f0d755dSdiggerlin SmallVector<uint32_t, 8> Disp;
1345*7a47ee51SKazu Hirata Disp.reserve(*NumOfCtlAnchors);
13462f0d755dSdiggerlin for (uint32_t I = 0; I < NumOfCtlAnchors && Cur; ++I)
13472f0d755dSdiggerlin Disp.push_back(DE.getU32(Cur));
13482f0d755dSdiggerlin if (Cur)
13492f0d755dSdiggerlin ControlledStorageInfoDisp = std::move(Disp);
13502f0d755dSdiggerlin }
13512f0d755dSdiggerlin }
13522f0d755dSdiggerlin
13532f0d755dSdiggerlin if (Cur && isFuncNamePresent()) {
13542f0d755dSdiggerlin uint16_t FunctionNameLen = DE.getU16(Cur);
13552f0d755dSdiggerlin if (Cur)
13562f0d755dSdiggerlin FunctionName = DE.getBytes(Cur, FunctionNameLen);
13572f0d755dSdiggerlin }
13582f0d755dSdiggerlin
13592f0d755dSdiggerlin if (Cur && isAllocaUsed())
13602f0d755dSdiggerlin AllocaRegister = DE.getU8(Cur);
13612f0d755dSdiggerlin
13627ed515d1Szhijian unsigned VectorParmsNum = 0;
1363ab77fa51Sdiggerlin if (Cur && hasVectorInfo()) {
1364ab77fa51Sdiggerlin StringRef VectorExtRef = DE.getBytes(Cur, 6);
13657ed515d1Szhijian if (Cur) {
13667ed515d1Szhijian Expected<TBVectorExt> TBVecExtOrErr = TBVectorExt::create(VectorExtRef);
13677ed515d1Szhijian if (!TBVecExtOrErr) {
13687ed515d1Szhijian Err = TBVecExtOrErr.takeError();
13697ed515d1Szhijian return;
13707ed515d1Szhijian }
13717ed515d1Szhijian VecExt = TBVecExtOrErr.get();
1372*7a47ee51SKazu Hirata VectorParmsNum = VecExt->getNumberOfVectorParms();
13737ed515d1Szhijian }
13747ed515d1Szhijian }
13757ed515d1Szhijian
13767ed515d1Szhijian // As long as there is no fixed-point or floating-point parameter, this
13777ed515d1Szhijian // field remains not present even when hasVectorInfo gives true and
13787ed515d1Szhijian // indicates the presence of vector parameters.
13797ed515d1Szhijian if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) {
13807ed515d1Szhijian Expected<SmallString<32>> ParmsTypeOrError =
13817ed515d1Szhijian hasVectorInfo()
13827ed515d1Szhijian ? parseParmsTypeWithVecInfo(ParamsTypeValue, FixedParmsNum,
13837ed515d1Szhijian FloatingParmsNum, VectorParmsNum)
13847ed515d1Szhijian : parseParmsType(ParamsTypeValue, FixedParmsNum, FloatingParmsNum);
13857ed515d1Szhijian
13867ed515d1Szhijian if (!ParmsTypeOrError) {
13877ed515d1Szhijian Err = ParmsTypeOrError.takeError();
13887ed515d1Szhijian return;
13897ed515d1Szhijian }
13907ed515d1Szhijian ParmsType = ParmsTypeOrError.get();
1391ab77fa51Sdiggerlin }
1392ab77fa51Sdiggerlin
1393ab77fa51Sdiggerlin if (Cur && hasExtensionTable())
1394ab77fa51Sdiggerlin ExtensionTable = DE.getU8(Cur);
13952f0d755dSdiggerlin
13962f0d755dSdiggerlin if (!Cur)
13972f0d755dSdiggerlin Err = Cur.takeError();
13987ed515d1Szhijian
13992f0d755dSdiggerlin Size = Cur.tell();
14002f0d755dSdiggerlin }
14012f0d755dSdiggerlin
14022f0d755dSdiggerlin #define GETBITWITHMASK(P, X) \
14032f0d755dSdiggerlin (support::endian::read32be(TBPtr + (P)) & (TracebackTable::X))
14042f0d755dSdiggerlin #define GETBITWITHMASKSHIFT(P, X, S) \
14052f0d755dSdiggerlin ((support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) >> \
14062f0d755dSdiggerlin (TracebackTable::S))
14072f0d755dSdiggerlin
getVersion() const14082f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getVersion() const {
14092f0d755dSdiggerlin return GETBITWITHMASKSHIFT(0, VersionMask, VersionShift);
14102f0d755dSdiggerlin }
14112f0d755dSdiggerlin
getLanguageID() const14122f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getLanguageID() const {
14132f0d755dSdiggerlin return GETBITWITHMASKSHIFT(0, LanguageIdMask, LanguageIdShift);
14142f0d755dSdiggerlin }
14152f0d755dSdiggerlin
isGlobalLinkage() const14162f0d755dSdiggerlin bool XCOFFTracebackTable::isGlobalLinkage() const {
14172f0d755dSdiggerlin return GETBITWITHMASK(0, IsGlobaLinkageMask);
14182f0d755dSdiggerlin }
14192f0d755dSdiggerlin
isOutOfLineEpilogOrPrologue() const14202f0d755dSdiggerlin bool XCOFFTracebackTable::isOutOfLineEpilogOrPrologue() const {
14212f0d755dSdiggerlin return GETBITWITHMASK(0, IsOutOfLineEpilogOrPrologueMask);
14222f0d755dSdiggerlin }
14232f0d755dSdiggerlin
hasTraceBackTableOffset() const14242f0d755dSdiggerlin bool XCOFFTracebackTable::hasTraceBackTableOffset() const {
14252f0d755dSdiggerlin return GETBITWITHMASK(0, HasTraceBackTableOffsetMask);
14262f0d755dSdiggerlin }
14272f0d755dSdiggerlin
isInternalProcedure() const14282f0d755dSdiggerlin bool XCOFFTracebackTable::isInternalProcedure() const {
14292f0d755dSdiggerlin return GETBITWITHMASK(0, IsInternalProcedureMask);
14302f0d755dSdiggerlin }
14312f0d755dSdiggerlin
hasControlledStorage() const14322f0d755dSdiggerlin bool XCOFFTracebackTable::hasControlledStorage() const {
14332f0d755dSdiggerlin return GETBITWITHMASK(0, HasControlledStorageMask);
14342f0d755dSdiggerlin }
14352f0d755dSdiggerlin
isTOCless() const14362f0d755dSdiggerlin bool XCOFFTracebackTable::isTOCless() const {
14372f0d755dSdiggerlin return GETBITWITHMASK(0, IsTOClessMask);
14382f0d755dSdiggerlin }
14392f0d755dSdiggerlin
isFloatingPointPresent() const14402f0d755dSdiggerlin bool XCOFFTracebackTable::isFloatingPointPresent() const {
14412f0d755dSdiggerlin return GETBITWITHMASK(0, IsFloatingPointPresentMask);
14422f0d755dSdiggerlin }
14432f0d755dSdiggerlin
isFloatingPointOperationLogOrAbortEnabled() const14442f0d755dSdiggerlin bool XCOFFTracebackTable::isFloatingPointOperationLogOrAbortEnabled() const {
14452f0d755dSdiggerlin return GETBITWITHMASK(0, IsFloatingPointOperationLogOrAbortEnabledMask);
14462f0d755dSdiggerlin }
14472f0d755dSdiggerlin
isInterruptHandler() const14482f0d755dSdiggerlin bool XCOFFTracebackTable::isInterruptHandler() const {
14492f0d755dSdiggerlin return GETBITWITHMASK(0, IsInterruptHandlerMask);
14502f0d755dSdiggerlin }
14512f0d755dSdiggerlin
isFuncNamePresent() const14522f0d755dSdiggerlin bool XCOFFTracebackTable::isFuncNamePresent() const {
14532f0d755dSdiggerlin return GETBITWITHMASK(0, IsFunctionNamePresentMask);
14542f0d755dSdiggerlin }
14552f0d755dSdiggerlin
isAllocaUsed() const14562f0d755dSdiggerlin bool XCOFFTracebackTable::isAllocaUsed() const {
14572f0d755dSdiggerlin return GETBITWITHMASK(0, IsAllocaUsedMask);
14582f0d755dSdiggerlin }
14592f0d755dSdiggerlin
getOnConditionDirective() const14602f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getOnConditionDirective() const {
14612f0d755dSdiggerlin return GETBITWITHMASKSHIFT(0, OnConditionDirectiveMask,
14622f0d755dSdiggerlin OnConditionDirectiveShift);
14632f0d755dSdiggerlin }
14642f0d755dSdiggerlin
isCRSaved() const14652f0d755dSdiggerlin bool XCOFFTracebackTable::isCRSaved() const {
14662f0d755dSdiggerlin return GETBITWITHMASK(0, IsCRSavedMask);
14672f0d755dSdiggerlin }
14682f0d755dSdiggerlin
isLRSaved() const14692f0d755dSdiggerlin bool XCOFFTracebackTable::isLRSaved() const {
14702f0d755dSdiggerlin return GETBITWITHMASK(0, IsLRSavedMask);
14712f0d755dSdiggerlin }
14722f0d755dSdiggerlin
isBackChainStored() const14732f0d755dSdiggerlin bool XCOFFTracebackTable::isBackChainStored() const {
14742f0d755dSdiggerlin return GETBITWITHMASK(4, IsBackChainStoredMask);
14752f0d755dSdiggerlin }
14762f0d755dSdiggerlin
isFixup() const14772f0d755dSdiggerlin bool XCOFFTracebackTable::isFixup() const {
14782f0d755dSdiggerlin return GETBITWITHMASK(4, IsFixupMask);
14792f0d755dSdiggerlin }
14802f0d755dSdiggerlin
getNumOfFPRsSaved() const14812f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getNumOfFPRsSaved() const {
14822f0d755dSdiggerlin return GETBITWITHMASKSHIFT(4, FPRSavedMask, FPRSavedShift);
14832f0d755dSdiggerlin }
14842f0d755dSdiggerlin
hasExtensionTable() const14852f0d755dSdiggerlin bool XCOFFTracebackTable::hasExtensionTable() const {
14862f0d755dSdiggerlin return GETBITWITHMASK(4, HasExtensionTableMask);
14872f0d755dSdiggerlin }
14882f0d755dSdiggerlin
hasVectorInfo() const14892f0d755dSdiggerlin bool XCOFFTracebackTable::hasVectorInfo() const {
14902f0d755dSdiggerlin return GETBITWITHMASK(4, HasVectorInfoMask);
14912f0d755dSdiggerlin }
14922f0d755dSdiggerlin
getNumOfGPRsSaved() const1493c80fbdf2Sdiggerlin uint8_t XCOFFTracebackTable::getNumOfGPRsSaved() const {
14942f0d755dSdiggerlin return GETBITWITHMASKSHIFT(4, GPRSavedMask, GPRSavedShift);
14952f0d755dSdiggerlin }
14962f0d755dSdiggerlin
getNumberOfFixedParms() const14972f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getNumberOfFixedParms() const {
14982f0d755dSdiggerlin return GETBITWITHMASKSHIFT(4, NumberOfFixedParmsMask,
14992f0d755dSdiggerlin NumberOfFixedParmsShift);
15002f0d755dSdiggerlin }
15012f0d755dSdiggerlin
getNumberOfFPParms() const15022f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getNumberOfFPParms() const {
15032f0d755dSdiggerlin return GETBITWITHMASKSHIFT(4, NumberOfFloatingPointParmsMask,
15042f0d755dSdiggerlin NumberOfFloatingPointParmsShift);
15052f0d755dSdiggerlin }
15062f0d755dSdiggerlin
hasParmsOnStack() const15072f0d755dSdiggerlin bool XCOFFTracebackTable::hasParmsOnStack() const {
15082f0d755dSdiggerlin return GETBITWITHMASK(4, HasParmsOnStackMask);
15092f0d755dSdiggerlin }
15102f0d755dSdiggerlin
15112f0d755dSdiggerlin #undef GETBITWITHMASK
15122f0d755dSdiggerlin #undef GETBITWITHMASKSHIFT
1513ab2eb2bfSHubert Tong } // namespace object
1514ab2eb2bfSHubert Tong } // namespace llvm
1515