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"
14ab2eb2bfSHubert Tong #include <cstddef>
15ab2eb2bfSHubert Tong #include <cstring>
16ab2eb2bfSHubert Tong 
17ab2eb2bfSHubert Tong namespace llvm {
18ab2eb2bfSHubert Tong namespace object {
19ab2eb2bfSHubert Tong 
20837ae69fSSean Fertile // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer
21837ae69fSSean Fertile // 'M'. Returns a pointer to the underlying object on success.
22ab2eb2bfSHubert Tong template <typename T>
23837ae69fSSean Fertile static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr,
24ab2eb2bfSHubert Tong                                      const uint64_t Size = sizeof(T)) {
25ab2eb2bfSHubert Tong   uintptr_t Addr = uintptr_t(Ptr);
26ab2eb2bfSHubert Tong   if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
27837ae69fSSean Fertile     return errorCodeToError(EC);
28837ae69fSSean Fertile   return reinterpret_cast<const T *>(Addr);
29837ae69fSSean Fertile }
30837ae69fSSean Fertile 
31837ae69fSSean Fertile static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) {
32837ae69fSSean Fertile   return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) +
33837ae69fSSean Fertile                                      Offset);
34ab2eb2bfSHubert Tong }
35ab2eb2bfSHubert Tong 
36a93a33cbSSean Fertile template <typename T> static const T *viewAs(uintptr_t in) {
37a93a33cbSSean Fertile   return reinterpret_cast<const T *>(in);
38a93a33cbSSean Fertile }
39a93a33cbSSean Fertile 
4029141da7SSean Fertile static StringRef generateStringRef(const char *Name) {
4129141da7SSean Fertile   auto NulCharPtr =
4229141da7SSean Fertile       static_cast<const char *>(memchr(Name, '\0', XCOFF::NameSize));
439212206dSJason Liu   return NulCharPtr ? StringRef(Name, NulCharPtr - Name)
4429141da7SSean Fertile                     : StringRef(Name, XCOFF::NameSize);
459212206dSJason Liu }
469212206dSJason Liu 
47837ae69fSSean Fertile void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr,
48837ae69fSSean Fertile                                           uintptr_t TableAddress) const {
49837ae69fSSean Fertile   if (Addr < TableAddress)
50a93a33cbSSean Fertile     report_fatal_error("Section header outside of section header table.");
51a93a33cbSSean Fertile 
52837ae69fSSean Fertile   uintptr_t Offset = Addr - TableAddress;
53837ae69fSSean Fertile   if (Offset >= getSectionHeaderSize() * getNumberOfSections())
54837ae69fSSean Fertile     report_fatal_error("Section header outside of section header table.");
55837ae69fSSean Fertile 
56a93a33cbSSean Fertile   if (Offset % getSectionHeaderSize() != 0)
57a93a33cbSSean Fertile     report_fatal_error(
58a93a33cbSSean Fertile         "Section header pointer does not point to a valid section header.");
59837ae69fSSean Fertile }
60837ae69fSSean Fertile 
61837ae69fSSean Fertile const XCOFFSectionHeader32 *
62837ae69fSSean Fertile XCOFFObjectFile::toSection32(DataRefImpl Ref) const {
63837ae69fSSean Fertile   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
64837ae69fSSean Fertile #ifndef NDEBUG
65837ae69fSSean Fertile   checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
66a93a33cbSSean Fertile #endif
67837ae69fSSean Fertile   return viewAs<XCOFFSectionHeader32>(Ref.p);
68837ae69fSSean Fertile }
69837ae69fSSean Fertile 
70837ae69fSSean Fertile const XCOFFSectionHeader64 *
71837ae69fSSean Fertile XCOFFObjectFile::toSection64(DataRefImpl Ref) const {
72837ae69fSSean Fertile   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
73837ae69fSSean Fertile #ifndef NDEBUG
74837ae69fSSean Fertile   checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
75837ae69fSSean Fertile #endif
76837ae69fSSean Fertile   return viewAs<XCOFFSectionHeader64>(Ref.p);
77a93a33cbSSean Fertile }
78a93a33cbSSean Fertile 
799212206dSJason Liu const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref) const {
80837ae69fSSean Fertile   assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
819212206dSJason Liu   assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!");
829212206dSJason Liu   auto SymEntPtr = viewAs<XCOFFSymbolEntry>(Ref.p);
839212206dSJason Liu   return SymEntPtr;
849212206dSJason Liu }
859212206dSJason Liu 
86837ae69fSSean Fertile const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const {
87837ae69fSSean Fertile   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
88837ae69fSSean Fertile   return static_cast<const XCOFFFileHeader32 *>(FileHeader);
89a93a33cbSSean Fertile }
90a93a33cbSSean Fertile 
91837ae69fSSean Fertile const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const {
92837ae69fSSean Fertile   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
93837ae69fSSean Fertile   return static_cast<const XCOFFFileHeader64 *>(FileHeader);
94a93a33cbSSean Fertile }
95a93a33cbSSean Fertile 
96837ae69fSSean Fertile const XCOFFSectionHeader32 *
97837ae69fSSean Fertile XCOFFObjectFile::sectionHeaderTable32() const {
98837ae69fSSean Fertile   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
99837ae69fSSean Fertile   return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable);
100837ae69fSSean Fertile }
101837ae69fSSean Fertile 
102837ae69fSSean Fertile const XCOFFSectionHeader64 *
103837ae69fSSean Fertile XCOFFObjectFile::sectionHeaderTable64() const {
104837ae69fSSean Fertile   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
105837ae69fSSean Fertile   return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable);
106837ae69fSSean Fertile }
1079212206dSJason Liu 
108ab2eb2bfSHubert Tong void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
1099212206dSJason Liu   const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
1109212206dSJason Liu   SymEntPtr += SymEntPtr->NumberOfAuxEntries + 1;
1119212206dSJason Liu   Symb.p = reinterpret_cast<uintptr_t>(SymEntPtr);
112ab2eb2bfSHubert Tong }
113ab2eb2bfSHubert Tong 
114ab2eb2bfSHubert Tong Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
1159212206dSJason Liu   const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
1169212206dSJason Liu 
1179212206dSJason Liu   if (SymEntPtr->NameInStrTbl.Magic != XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC)
11829141da7SSean Fertile     return generateStringRef(SymEntPtr->SymbolName);
1199212206dSJason Liu 
1209212206dSJason Liu   // A storage class value with the high-order bit on indicates that the name is
1219212206dSJason Liu   // a symbolic debugger stabstring.
1229212206dSJason Liu   if (SymEntPtr->StorageClass & 0x80)
1239212206dSJason Liu     return StringRef("Unimplemented Debug Name");
1249212206dSJason Liu 
1259212206dSJason Liu   uint32_t Offset = SymEntPtr->NameInStrTbl.Offset;
1269212206dSJason Liu   // The byte offset is relative to the start of the string table
1279212206dSJason Liu   // or .debug section. A byte offset value of 0 is a null or zero-length symbol
1289212206dSJason Liu   // name. A byte offset in the range 1 to 3 (inclusive) points into the length
1299212206dSJason Liu   // field; as a soft-error recovery mechanism, we treat such cases as having an
1309212206dSJason Liu   // offset of 0.
1319212206dSJason Liu   if (Offset < 4)
1329212206dSJason Liu     return StringRef(nullptr, 0);
1339212206dSJason Liu 
1349212206dSJason Liu   if (StringTable.Data != nullptr && StringTable.Size > Offset)
1359212206dSJason Liu     return (StringTable.Data + Offset);
1369212206dSJason Liu 
1379212206dSJason Liu   return make_error<GenericBinaryError>("Symbol Name parse failed",
1389212206dSJason Liu                                         object_error::parse_failed);
139ab2eb2bfSHubert Tong }
140ab2eb2bfSHubert Tong 
141ab2eb2bfSHubert Tong Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
142ab2eb2bfSHubert Tong   uint64_t Result = 0;
143ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
144ab2eb2bfSHubert Tong   return Result;
145ab2eb2bfSHubert Tong }
146ab2eb2bfSHubert Tong 
147ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
1489212206dSJason Liu   return toSymbolEntry(Symb)->Value;
149ab2eb2bfSHubert Tong }
150ab2eb2bfSHubert Tong 
151ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
152ab2eb2bfSHubert Tong   uint64_t Result = 0;
153ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
154ab2eb2bfSHubert Tong   return Result;
155ab2eb2bfSHubert Tong }
156ab2eb2bfSHubert Tong 
157ab2eb2bfSHubert Tong Expected<SymbolRef::Type>
158ab2eb2bfSHubert Tong XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
159ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
160ab2eb2bfSHubert Tong   return SymbolRef::ST_Other;
161ab2eb2bfSHubert Tong }
162ab2eb2bfSHubert Tong 
163ab2eb2bfSHubert Tong Expected<section_iterator>
164ab2eb2bfSHubert Tong XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
1659212206dSJason Liu   const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
1669212206dSJason Liu   int16_t SectNum = SymEntPtr->SectionNumber;
1679212206dSJason Liu 
1689212206dSJason Liu   if (isReservedSectionNumber(SectNum))
1699212206dSJason Liu     return section_end();
1709212206dSJason Liu 
171837ae69fSSean Fertile   Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum);
172837ae69fSSean Fertile   if (!ExpSec)
173837ae69fSSean Fertile     return ExpSec.takeError();
1749212206dSJason Liu 
175837ae69fSSean Fertile   return section_iterator(SectionRef(ExpSec.get(), this));
176ab2eb2bfSHubert Tong }
177ab2eb2bfSHubert Tong 
178ab2eb2bfSHubert Tong void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
179a93a33cbSSean Fertile   const char *Ptr = reinterpret_cast<const char *>(Sec.p);
180a93a33cbSSean Fertile   Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize());
181ab2eb2bfSHubert Tong }
182ab2eb2bfSHubert Tong 
1838be28cdcSFangrui Song Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const {
18429141da7SSean Fertile   return generateStringRef(getSectionNameInternal(Sec));
185ab2eb2bfSHubert Tong }
186ab2eb2bfSHubert Tong 
187ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
188210314aeSSean Fertile   // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
189210314aeSSean Fertile   // with MSVC.
190210314aeSSean Fertile   if (is64Bit())
191210314aeSSean Fertile     return toSection64(Sec)->VirtualAddress;
192210314aeSSean Fertile 
193210314aeSSean Fertile   return toSection32(Sec)->VirtualAddress;
194ab2eb2bfSHubert Tong }
195ab2eb2bfSHubert Tong 
196ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
197a93a33cbSSean Fertile   // Section numbers in XCOFF are numbered beginning at 1. A section number of
198a93a33cbSSean Fertile   // zero is used to indicate that a symbol is being imported or is undefined.
199837ae69fSSean Fertile   if (is64Bit())
200837ae69fSSean Fertile     return toSection64(Sec) - sectionHeaderTable64() + 1;
201837ae69fSSean Fertile   else
202837ae69fSSean Fertile     return toSection32(Sec) - sectionHeaderTable32() + 1;
203ab2eb2bfSHubert Tong }
204ab2eb2bfSHubert Tong 
205ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
206210314aeSSean Fertile   // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
207210314aeSSean Fertile   // with MSVC.
208210314aeSSean Fertile   if (is64Bit())
209210314aeSSean Fertile     return toSection64(Sec)->SectionSize;
210210314aeSSean Fertile 
211210314aeSSean Fertile   return toSection32(Sec)->SectionSize;
212ab2eb2bfSHubert Tong }
213ab2eb2bfSHubert Tong 
214e1cb2c0fSFangrui Song Expected<ArrayRef<uint8_t>>
215e1cb2c0fSFangrui Song XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
216ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
217ab2eb2bfSHubert Tong }
218ab2eb2bfSHubert Tong 
219ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
220ab2eb2bfSHubert Tong   uint64_t Result = 0;
221ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
222ab2eb2bfSHubert Tong   return Result;
223ab2eb2bfSHubert Tong }
224ab2eb2bfSHubert Tong 
225ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
226ab2eb2bfSHubert Tong   bool Result = false;
227ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
228ab2eb2bfSHubert Tong   return Result;
229ab2eb2bfSHubert Tong }
230ab2eb2bfSHubert Tong 
231ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const {
232837ae69fSSean Fertile   return getSectionFlags(Sec) & XCOFF::STYP_TEXT;
233ab2eb2bfSHubert Tong }
234ab2eb2bfSHubert Tong 
235ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const {
236837ae69fSSean Fertile   uint32_t Flags = getSectionFlags(Sec);
237a93a33cbSSean Fertile   return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA);
238ab2eb2bfSHubert Tong }
239ab2eb2bfSHubert Tong 
240ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const {
241837ae69fSSean Fertile   uint32_t Flags = getSectionFlags(Sec);
242a93a33cbSSean Fertile   return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS);
243ab2eb2bfSHubert Tong }
244ab2eb2bfSHubert Tong 
245ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const {
246ab2eb2bfSHubert Tong   bool Result = false;
247ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
248ab2eb2bfSHubert Tong   return Result;
249ab2eb2bfSHubert Tong }
250ab2eb2bfSHubert Tong 
251ab2eb2bfSHubert Tong relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const {
252ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
253ab2eb2bfSHubert Tong   return relocation_iterator(RelocationRef());
254ab2eb2bfSHubert Tong }
255ab2eb2bfSHubert Tong 
256ab2eb2bfSHubert Tong relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const {
257ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
258ab2eb2bfSHubert Tong   return relocation_iterator(RelocationRef());
259ab2eb2bfSHubert Tong }
260ab2eb2bfSHubert Tong 
261ab2eb2bfSHubert Tong void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
262ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
263ab2eb2bfSHubert Tong   return;
264ab2eb2bfSHubert Tong }
265ab2eb2bfSHubert Tong 
266ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
267ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
268ab2eb2bfSHubert Tong   uint64_t Result = 0;
269ab2eb2bfSHubert Tong   return Result;
270ab2eb2bfSHubert Tong }
271ab2eb2bfSHubert Tong 
272ab2eb2bfSHubert Tong symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
273ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
274ab2eb2bfSHubert Tong   return symbol_iterator(SymbolRef());
275ab2eb2bfSHubert Tong }
276ab2eb2bfSHubert Tong 
277ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const {
278ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
279ab2eb2bfSHubert Tong   uint64_t Result = 0;
280ab2eb2bfSHubert Tong   return Result;
281ab2eb2bfSHubert Tong }
282ab2eb2bfSHubert Tong 
283ab2eb2bfSHubert Tong void XCOFFObjectFile::getRelocationTypeName(
284ab2eb2bfSHubert Tong     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
285ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
286ab2eb2bfSHubert Tong   return;
287ab2eb2bfSHubert Tong }
288ab2eb2bfSHubert Tong 
289ab2eb2bfSHubert Tong uint32_t XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
290ab2eb2bfSHubert Tong   uint32_t Result = 0;
291ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
292ab2eb2bfSHubert Tong   return Result;
293ab2eb2bfSHubert Tong }
294ab2eb2bfSHubert Tong 
295ab2eb2bfSHubert Tong basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
296837ae69fSSean Fertile   assert(!is64Bit() && "64-bit support not implemented yet.");
2979212206dSJason Liu   DataRefImpl SymDRI;
2989212206dSJason Liu   SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr);
2999212206dSJason Liu   return basic_symbol_iterator(SymbolRef(SymDRI, this));
300ab2eb2bfSHubert Tong }
301ab2eb2bfSHubert Tong 
302ab2eb2bfSHubert Tong basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
303837ae69fSSean Fertile   assert(!is64Bit() && "64-bit support not implemented yet.");
3049212206dSJason Liu   DataRefImpl SymDRI;
3059212206dSJason Liu   SymDRI.p = reinterpret_cast<uintptr_t>(
306837ae69fSSean Fertile       SymbolTblPtr + getLogicalNumberOfSymbolTableEntries32());
3079212206dSJason Liu   return basic_symbol_iterator(SymbolRef(SymDRI, this));
308ab2eb2bfSHubert Tong }
309ab2eb2bfSHubert Tong 
310ab2eb2bfSHubert Tong section_iterator XCOFFObjectFile::section_begin() const {
311a93a33cbSSean Fertile   DataRefImpl DRI;
312837ae69fSSean Fertile   DRI.p = getSectionHeaderTableAddress();
313a93a33cbSSean Fertile   return section_iterator(SectionRef(DRI, this));
314ab2eb2bfSHubert Tong }
315ab2eb2bfSHubert Tong 
316ab2eb2bfSHubert Tong section_iterator XCOFFObjectFile::section_end() const {
317a93a33cbSSean Fertile   DataRefImpl DRI;
318837ae69fSSean Fertile   DRI.p = getWithOffset(getSectionHeaderTableAddress(),
319837ae69fSSean Fertile                         getNumberOfSections() * getSectionHeaderSize());
320a93a33cbSSean Fertile   return section_iterator(SectionRef(DRI, this));
321ab2eb2bfSHubert Tong }
322ab2eb2bfSHubert Tong 
323837ae69fSSean Fertile uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; }
324ab2eb2bfSHubert Tong 
325ab2eb2bfSHubert Tong StringRef XCOFFObjectFile::getFileFormatName() const {
326837ae69fSSean Fertile   return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000";
327ab2eb2bfSHubert Tong }
328ab2eb2bfSHubert Tong 
329ab2eb2bfSHubert Tong Triple::ArchType XCOFFObjectFile::getArch() const {
330837ae69fSSean Fertile   return is64Bit() ? Triple::ppc64 : Triple::ppc;
331ab2eb2bfSHubert Tong }
332ab2eb2bfSHubert Tong 
333ab2eb2bfSHubert Tong SubtargetFeatures XCOFFObjectFile::getFeatures() const {
334ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
335ab2eb2bfSHubert Tong   return SubtargetFeatures();
336ab2eb2bfSHubert Tong }
337ab2eb2bfSHubert Tong 
338ab2eb2bfSHubert Tong bool XCOFFObjectFile::isRelocatableObject() const {
339ab2eb2bfSHubert Tong   bool Result = false;
340ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
341ab2eb2bfSHubert Tong   return Result;
342ab2eb2bfSHubert Tong }
343ab2eb2bfSHubert Tong 
344a93a33cbSSean Fertile Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
345a93a33cbSSean Fertile   // TODO FIXME Should get from auxiliary_header->o_entry when support for the
346a93a33cbSSean Fertile   // auxiliary_header is added.
347a93a33cbSSean Fertile   return 0;
348a93a33cbSSean Fertile }
349a93a33cbSSean Fertile 
350837ae69fSSean Fertile size_t XCOFFObjectFile::getFileHeaderSize() const {
351837ae69fSSean Fertile   return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32);
3529212206dSJason Liu }
3539212206dSJason Liu 
354837ae69fSSean Fertile size_t XCOFFObjectFile::getSectionHeaderSize() const {
355837ae69fSSean Fertile   return is64Bit() ? sizeof(XCOFFSectionHeader64) :
356837ae69fSSean Fertile                      sizeof(XCOFFSectionHeader32);
357837ae69fSSean Fertile }
358837ae69fSSean Fertile 
359837ae69fSSean Fertile bool XCOFFObjectFile::is64Bit() const {
360837ae69fSSean Fertile   return Binary::ID_XCOFF64 == getType();
361837ae69fSSean Fertile }
362837ae69fSSean Fertile 
363837ae69fSSean Fertile uint16_t XCOFFObjectFile::getMagic() const {
364837ae69fSSean Fertile   return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic;
365837ae69fSSean Fertile }
366837ae69fSSean Fertile 
367837ae69fSSean Fertile Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
368837ae69fSSean Fertile   if (Num <= 0 || Num > getNumberOfSections())
369837ae69fSSean Fertile     return errorCodeToError(object_error::invalid_section_index);
370837ae69fSSean Fertile 
371837ae69fSSean Fertile   DataRefImpl DRI;
372837ae69fSSean Fertile   DRI.p = getWithOffset(getSectionHeaderTableAddress(),
373837ae69fSSean Fertile                         getSectionHeaderSize() * (Num - 1));
374837ae69fSSean Fertile   return DRI;
3759212206dSJason Liu }
3769212206dSJason Liu 
3779212206dSJason Liu Expected<StringRef>
3789212206dSJason Liu XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const {
379837ae69fSSean Fertile   assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
3809212206dSJason Liu   int16_t SectionNum = SymEntPtr->SectionNumber;
3819212206dSJason Liu 
3829212206dSJason Liu   switch (SectionNum) {
3839212206dSJason Liu   case XCOFF::N_DEBUG:
3849212206dSJason Liu     return "N_DEBUG";
3859212206dSJason Liu   case XCOFF::N_ABS:
3869212206dSJason Liu     return "N_ABS";
3879212206dSJason Liu   case XCOFF::N_UNDEF:
3889212206dSJason Liu     return "N_UNDEF";
389837ae69fSSean Fertile   default:
390837ae69fSSean Fertile     Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum);
391837ae69fSSean Fertile     if (SecRef)
39229141da7SSean Fertile       return generateStringRef(getSectionNameInternal(SecRef.get()));
393837ae69fSSean Fertile     return SecRef.takeError();
3949212206dSJason Liu   }
3959212206dSJason Liu }
3969212206dSJason Liu 
3979212206dSJason Liu bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) {
3989212206dSJason Liu   return (SectionNumber <= 0 && SectionNumber >= -2);
3999212206dSJason Liu }
4009212206dSJason Liu 
4019212206dSJason Liu uint16_t XCOFFObjectFile::getNumberOfSections() const {
402837ae69fSSean Fertile   return is64Bit() ? fileHeader64()->NumberOfSections
403837ae69fSSean Fertile                    : fileHeader32()->NumberOfSections;
4049212206dSJason Liu }
4059212206dSJason Liu 
406837ae69fSSean Fertile int32_t XCOFFObjectFile::getTimeStamp() const {
407837ae69fSSean Fertile   return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp;
4089212206dSJason Liu }
4099212206dSJason Liu 
4109212206dSJason Liu uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
411837ae69fSSean Fertile   return is64Bit() ? fileHeader64()->AuxHeaderSize
412837ae69fSSean Fertile                    : fileHeader32()->AuxHeaderSize;
4139212206dSJason Liu }
4149212206dSJason Liu 
415837ae69fSSean Fertile uint32_t XCOFFObjectFile::getSymbolTableOffset32() const {
416837ae69fSSean Fertile   return fileHeader32()->SymbolTableOffset;
417837ae69fSSean Fertile }
418ab2eb2bfSHubert Tong 
419837ae69fSSean Fertile int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const {
420837ae69fSSean Fertile   // As far as symbol table size is concerned, if this field is negative it is
421837ae69fSSean Fertile   // to be treated as a 0. However since this field is also used for printing we
422837ae69fSSean Fertile   // don't want to truncate any negative values.
423837ae69fSSean Fertile   return fileHeader32()->NumberOfSymTableEntries;
424837ae69fSSean Fertile }
425ab2eb2bfSHubert Tong 
426837ae69fSSean Fertile uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const {
427837ae69fSSean Fertile   return (fileHeader32()->NumberOfSymTableEntries >= 0
428837ae69fSSean Fertile               ? fileHeader32()->NumberOfSymTableEntries
429837ae69fSSean Fertile               : 0);
430837ae69fSSean Fertile }
431a93a33cbSSean Fertile 
432837ae69fSSean Fertile uint64_t XCOFFObjectFile::getSymbolTableOffset64() const {
433837ae69fSSean Fertile   return fileHeader64()->SymbolTableOffset;
434837ae69fSSean Fertile }
435837ae69fSSean Fertile 
436837ae69fSSean Fertile uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
437837ae69fSSean Fertile   return fileHeader64()->NumberOfSymTableEntries;
438837ae69fSSean Fertile }
439837ae69fSSean Fertile 
440837ae69fSSean Fertile uint16_t XCOFFObjectFile::getFlags() const {
441837ae69fSSean Fertile   return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags;
442837ae69fSSean Fertile }
443837ae69fSSean Fertile 
444837ae69fSSean Fertile const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const {
445837ae69fSSean Fertile   return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name;
446837ae69fSSean Fertile }
447837ae69fSSean Fertile 
448837ae69fSSean Fertile uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const {
449837ae69fSSean Fertile   return reinterpret_cast<uintptr_t>(SectionHeaderTable);
450837ae69fSSean Fertile }
451837ae69fSSean Fertile 
452837ae69fSSean Fertile int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const {
453837ae69fSSean Fertile   return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags;
454837ae69fSSean Fertile }
455837ae69fSSean Fertile 
456837ae69fSSean Fertile XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object)
457837ae69fSSean Fertile     : ObjectFile(Type, Object) {
458837ae69fSSean Fertile   assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64);
459837ae69fSSean Fertile }
460837ae69fSSean Fertile 
461837ae69fSSean Fertile ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const {
462837ae69fSSean Fertile   assert(is64Bit() && "64-bit interface called for non 64-bit file.");
463837ae69fSSean Fertile   const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64();
464837ae69fSSean Fertile   return ArrayRef<XCOFFSectionHeader64>(TablePtr,
465837ae69fSSean Fertile                                         TablePtr + getNumberOfSections());
466837ae69fSSean Fertile }
467837ae69fSSean Fertile 
468837ae69fSSean Fertile ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const {
469837ae69fSSean Fertile   assert(!is64Bit() && "32-bit interface called for non 32-bit file.");
470837ae69fSSean Fertile   const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32();
471837ae69fSSean Fertile   return ArrayRef<XCOFFSectionHeader32>(TablePtr,
472837ae69fSSean Fertile                                         TablePtr + getNumberOfSections());
473837ae69fSSean Fertile }
474837ae69fSSean Fertile 
475837ae69fSSean Fertile Expected<XCOFFStringTable>
476837ae69fSSean Fertile XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
477837ae69fSSean Fertile   // If there is a string table, then the buffer must contain at least 4 bytes
478837ae69fSSean Fertile   // for the string table's size. Not having a string table is not an error.
479837ae69fSSean Fertile   if (auto EC = Binary::checkOffset(
480837ae69fSSean Fertile           Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4))
481837ae69fSSean Fertile     return XCOFFStringTable{0, nullptr};
482837ae69fSSean Fertile 
483837ae69fSSean Fertile   // Read the size out of the buffer.
484837ae69fSSean Fertile   uint32_t Size = support::endian::read32be(Obj->base() + Offset);
485837ae69fSSean Fertile 
486837ae69fSSean Fertile   // If the size is less then 4, then the string table is just a size and no
487837ae69fSSean Fertile   // string data.
488837ae69fSSean Fertile   if (Size <= 4)
489837ae69fSSean Fertile     return XCOFFStringTable{4, nullptr};
490837ae69fSSean Fertile 
491837ae69fSSean Fertile   auto StringTableOrErr =
492837ae69fSSean Fertile       getObject<char>(Obj->Data, Obj->base() + Offset, Size);
493837ae69fSSean Fertile   if (Error E = StringTableOrErr.takeError())
494837ae69fSSean Fertile     return std::move(E);
495837ae69fSSean Fertile 
496837ae69fSSean Fertile   const char *StringTablePtr = StringTableOrErr.get();
497837ae69fSSean Fertile   if (StringTablePtr[Size - 1] != '\0')
498837ae69fSSean Fertile     return errorCodeToError(object_error::string_table_non_null_end);
499837ae69fSSean Fertile 
500837ae69fSSean Fertile   return XCOFFStringTable{Size, StringTablePtr};
501837ae69fSSean Fertile }
502837ae69fSSean Fertile 
503837ae69fSSean Fertile Expected<std::unique_ptr<XCOFFObjectFile>>
504837ae69fSSean Fertile XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
505*0eaee545SJonas Devlieghere   // Can't use std::make_unique because of the private constructor.
506837ae69fSSean Fertile   std::unique_ptr<XCOFFObjectFile> Obj;
507837ae69fSSean Fertile   Obj.reset(new XCOFFObjectFile(Type, MBR));
508837ae69fSSean Fertile 
509837ae69fSSean Fertile   uint64_t CurOffset = 0;
510837ae69fSSean Fertile   const auto *Base = Obj->base();
511837ae69fSSean Fertile   MemoryBufferRef Data = Obj->Data;
512837ae69fSSean Fertile 
513837ae69fSSean Fertile   // Parse file header.
514837ae69fSSean Fertile   auto FileHeaderOrErr =
515837ae69fSSean Fertile       getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize());
516837ae69fSSean Fertile   if (Error E = FileHeaderOrErr.takeError())
517837ae69fSSean Fertile     return std::move(E);
518837ae69fSSean Fertile   Obj->FileHeader = FileHeaderOrErr.get();
519837ae69fSSean Fertile 
520837ae69fSSean Fertile   CurOffset += Obj->getFileHeaderSize();
521a93a33cbSSean Fertile   // TODO FIXME we don't have support for an optional header yet, so just skip
522a93a33cbSSean Fertile   // past it.
523837ae69fSSean Fertile   CurOffset += Obj->getOptionalHeaderSize();
524a93a33cbSSean Fertile 
525837ae69fSSean Fertile   // Parse the section header table if it is present.
526837ae69fSSean Fertile   if (Obj->getNumberOfSections()) {
527837ae69fSSean Fertile     auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset,
528837ae69fSSean Fertile                                            Obj->getNumberOfSections() *
529837ae69fSSean Fertile                                                Obj->getSectionHeaderSize());
530837ae69fSSean Fertile     if (Error E = SecHeadersOrErr.takeError())
531837ae69fSSean Fertile       return std::move(E);
532837ae69fSSean Fertile     Obj->SectionHeaderTable = SecHeadersOrErr.get();
533a93a33cbSSean Fertile   }
534ab2eb2bfSHubert Tong 
535837ae69fSSean Fertile   // 64-bit object supports only file header and section headers for now.
536837ae69fSSean Fertile   if (Obj->is64Bit())
537837ae69fSSean Fertile     return std::move(Obj);
538fd75ee91SSean Fertile 
539837ae69fSSean Fertile   // If there is no symbol table we are done parsing the memory buffer.
540837ae69fSSean Fertile   if (Obj->getLogicalNumberOfSymbolTableEntries32() == 0)
541837ae69fSSean Fertile     return std::move(Obj);
542837ae69fSSean Fertile 
543837ae69fSSean Fertile   // Parse symbol table.
544837ae69fSSean Fertile   CurOffset = Obj->fileHeader32()->SymbolTableOffset;
5459212206dSJason Liu   uint64_t SymbolTableSize = (uint64_t)(sizeof(XCOFFSymbolEntry)) *
546837ae69fSSean Fertile                              Obj->getLogicalNumberOfSymbolTableEntries32();
547837ae69fSSean Fertile   auto SymTableOrErr =
548837ae69fSSean Fertile       getObject<XCOFFSymbolEntry>(Data, Base + CurOffset, SymbolTableSize);
549837ae69fSSean Fertile   if (Error E = SymTableOrErr.takeError())
550837ae69fSSean Fertile     return std::move(E);
551837ae69fSSean Fertile   Obj->SymbolTblPtr = SymTableOrErr.get();
552837ae69fSSean Fertile   CurOffset += SymbolTableSize;
553fd75ee91SSean Fertile 
554837ae69fSSean Fertile   // Parse String table.
555837ae69fSSean Fertile   Expected<XCOFFStringTable> StringTableOrErr =
556837ae69fSSean Fertile       parseStringTable(Obj.get(), CurOffset);
557837ae69fSSean Fertile   if (Error E = StringTableOrErr.takeError())
558837ae69fSSean Fertile     return std::move(E);
559837ae69fSSean Fertile   Obj->StringTable = StringTableOrErr.get();
560fd75ee91SSean Fertile 
561837ae69fSSean Fertile   return std::move(Obj);
562fd75ee91SSean Fertile }
563fd75ee91SSean Fertile 
564ab2eb2bfSHubert Tong Expected<std::unique_ptr<ObjectFile>>
565837ae69fSSean Fertile ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
566837ae69fSSean Fertile                                   unsigned FileType) {
567837ae69fSSean Fertile   return XCOFFObjectFile::create(FileType, MemBufRef);
568ab2eb2bfSHubert Tong }
569ab2eb2bfSHubert Tong 
570837ae69fSSean Fertile StringRef XCOFFSectionHeader32::getName() const {
57129141da7SSean Fertile   return generateStringRef(Name);
572837ae69fSSean Fertile }
573837ae69fSSean Fertile 
574837ae69fSSean Fertile StringRef XCOFFSectionHeader64::getName() const {
57529141da7SSean Fertile   return generateStringRef(Name);
576ab2eb2bfSHubert Tong }
577ab2eb2bfSHubert Tong 
578ab2eb2bfSHubert Tong } // namespace object
579ab2eb2bfSHubert Tong } // namespace llvm
580