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 "llvm/ADT/ArrayRef.h"
15ab2eb2bfSHubert Tong #include "llvm/Support/BinaryStreamReader.h"
16ab2eb2bfSHubert Tong #include "llvm/Support/Endian.h"
17ab2eb2bfSHubert Tong #include "llvm/Support/ErrorHandling.h"
18ab2eb2bfSHubert Tong #include "llvm/Support/MathExtras.h"
19ab2eb2bfSHubert Tong #include <cstddef>
20ab2eb2bfSHubert Tong #include <cstring>
21ab2eb2bfSHubert Tong 
22ab2eb2bfSHubert Tong namespace llvm {
23ab2eb2bfSHubert Tong namespace object {
24ab2eb2bfSHubert Tong 
25*a93a33cbSSean Fertile enum { XCOFF32FileHeaderSize = 20 };
26*a93a33cbSSean Fertile static_assert(sizeof(XCOFFFileHeader) == XCOFF32FileHeaderSize,
27*a93a33cbSSean Fertile               "Wrong size for XCOFF file header.");
28*a93a33cbSSean Fertile 
29ab2eb2bfSHubert Tong // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
30ab2eb2bfSHubert Tong // Returns unexpected_eof on error.
31ab2eb2bfSHubert Tong template <typename T>
32ab2eb2bfSHubert Tong static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
33ab2eb2bfSHubert Tong                                  const void *Ptr,
34ab2eb2bfSHubert Tong                                  const uint64_t Size = sizeof(T)) {
35ab2eb2bfSHubert Tong   uintptr_t Addr = uintptr_t(Ptr);
36ab2eb2bfSHubert Tong   if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
37ab2eb2bfSHubert Tong     return EC;
38ab2eb2bfSHubert Tong   Obj = reinterpret_cast<const T *>(Addr);
39ab2eb2bfSHubert Tong   return std::error_code();
40ab2eb2bfSHubert Tong }
41ab2eb2bfSHubert Tong 
42*a93a33cbSSean Fertile template <typename T> static const T *viewAs(uintptr_t in) {
43*a93a33cbSSean Fertile   return reinterpret_cast<const T *>(in);
44*a93a33cbSSean Fertile }
45*a93a33cbSSean Fertile 
46*a93a33cbSSean Fertile const XCOFFSectionHeader *XCOFFObjectFile::toSection(DataRefImpl Ref) const {
47*a93a33cbSSean Fertile   auto Sec = viewAs<XCOFFSectionHeader>(Ref.p);
48*a93a33cbSSean Fertile #ifndef NDEBUG
49*a93a33cbSSean Fertile   if (Sec < SectionHdrTablePtr ||
50*a93a33cbSSean Fertile       Sec >= (SectionHdrTablePtr + getNumberOfSections()))
51*a93a33cbSSean Fertile     report_fatal_error("Section header outside of section header table.");
52*a93a33cbSSean Fertile 
53*a93a33cbSSean Fertile   uintptr_t Offset = uintptr_t(Sec) - uintptr_t(SectionHdrTablePtr);
54*a93a33cbSSean Fertile   if (Offset % getSectionHeaderSize() != 0)
55*a93a33cbSSean Fertile     report_fatal_error(
56*a93a33cbSSean Fertile         "Section header pointer does not point to a valid section header.");
57*a93a33cbSSean Fertile #endif
58*a93a33cbSSean Fertile   return Sec;
59*a93a33cbSSean Fertile }
60*a93a33cbSSean Fertile 
61*a93a33cbSSean Fertile // The next 2 functions are not exactly necessary yet, but they are useful to
62*a93a33cbSSean Fertile // abstract over the size difference between XCOFF32 and XCOFF64 structure
63*a93a33cbSSean Fertile // definitions.
64*a93a33cbSSean Fertile size_t XCOFFObjectFile::getFileHeaderSize() const {
65*a93a33cbSSean Fertile   return sizeof(XCOFFFileHeader);
66*a93a33cbSSean Fertile }
67*a93a33cbSSean Fertile 
68*a93a33cbSSean Fertile size_t XCOFFObjectFile::getSectionHeaderSize() const {
69*a93a33cbSSean Fertile   return sizeof(XCOFFSectionHeader);
70*a93a33cbSSean Fertile }
71*a93a33cbSSean Fertile 
72*a93a33cbSSean Fertile uint16_t XCOFFObjectFile::getNumberOfSections() const {
73*a93a33cbSSean Fertile   return FileHdrPtr->NumberOfSections;
74*a93a33cbSSean Fertile }
75*a93a33cbSSean Fertile 
76ab2eb2bfSHubert Tong void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
77ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
78ab2eb2bfSHubert Tong   return;
79ab2eb2bfSHubert Tong }
80ab2eb2bfSHubert Tong 
81ab2eb2bfSHubert Tong Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
82ab2eb2bfSHubert Tong   StringRef Result;
83ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
84ab2eb2bfSHubert Tong   return Result;
85ab2eb2bfSHubert Tong }
86ab2eb2bfSHubert Tong 
87ab2eb2bfSHubert Tong Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
88ab2eb2bfSHubert Tong   uint64_t Result = 0;
89ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
90ab2eb2bfSHubert Tong   return Result;
91ab2eb2bfSHubert Tong }
92ab2eb2bfSHubert Tong 
93ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
94ab2eb2bfSHubert Tong   uint64_t Result = 0;
95ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
96ab2eb2bfSHubert Tong   return Result;
97ab2eb2bfSHubert Tong }
98ab2eb2bfSHubert Tong 
99ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
100ab2eb2bfSHubert Tong   uint64_t Result = 0;
101ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
102ab2eb2bfSHubert Tong   return Result;
103ab2eb2bfSHubert Tong }
104ab2eb2bfSHubert Tong 
105ab2eb2bfSHubert Tong Expected<SymbolRef::Type>
106ab2eb2bfSHubert Tong XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
107ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
108ab2eb2bfSHubert Tong   return SymbolRef::ST_Other;
109ab2eb2bfSHubert Tong }
110ab2eb2bfSHubert Tong 
111ab2eb2bfSHubert Tong Expected<section_iterator>
112ab2eb2bfSHubert Tong XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
113ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
114ab2eb2bfSHubert Tong   return section_iterator(SectionRef());
115ab2eb2bfSHubert Tong }
116ab2eb2bfSHubert Tong 
117ab2eb2bfSHubert Tong void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
118*a93a33cbSSean Fertile   const char *Ptr = reinterpret_cast<const char *>(Sec.p);
119*a93a33cbSSean Fertile   Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize());
120ab2eb2bfSHubert Tong }
121ab2eb2bfSHubert Tong 
122ab2eb2bfSHubert Tong std::error_code XCOFFObjectFile::getSectionName(DataRefImpl Sec,
123ab2eb2bfSHubert Tong                                                 StringRef &Res) const {
124*a93a33cbSSean Fertile   const char *Name = toSection(Sec)->Name;
125*a93a33cbSSean Fertile   auto NulCharPtr =
126*a93a33cbSSean Fertile       static_cast<const char *>(memchr(Name, '\0', XCOFF::SectionNameSize));
127*a93a33cbSSean Fertile   Res = NulCharPtr ? StringRef(Name, NulCharPtr - Name)
128*a93a33cbSSean Fertile                    : StringRef(Name, XCOFF::SectionNameSize);
129ab2eb2bfSHubert Tong   return std::error_code();
130ab2eb2bfSHubert Tong }
131ab2eb2bfSHubert Tong 
132ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
133*a93a33cbSSean Fertile   return toSection(Sec)->VirtualAddress;
134ab2eb2bfSHubert Tong }
135ab2eb2bfSHubert Tong 
136ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
137*a93a33cbSSean Fertile   // Section numbers in XCOFF are numbered beginning at 1. A section number of
138*a93a33cbSSean Fertile   // zero is used to indicate that a symbol is being imported or is undefined.
139*a93a33cbSSean Fertile   return toSection(Sec) - SectionHdrTablePtr + 1;
140ab2eb2bfSHubert Tong }
141ab2eb2bfSHubert Tong 
142ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
143*a93a33cbSSean Fertile   return toSection(Sec)->SectionSize;
144ab2eb2bfSHubert Tong }
145ab2eb2bfSHubert Tong 
146ab2eb2bfSHubert Tong std::error_code XCOFFObjectFile::getSectionContents(DataRefImpl Sec,
147ab2eb2bfSHubert Tong                                                     StringRef &Res) const {
148ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
149ab2eb2bfSHubert Tong   return std::error_code();
150ab2eb2bfSHubert Tong }
151ab2eb2bfSHubert Tong 
152ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
153ab2eb2bfSHubert Tong   uint64_t Result = 0;
154ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
155ab2eb2bfSHubert Tong   return Result;
156ab2eb2bfSHubert Tong }
157ab2eb2bfSHubert Tong 
158ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
159ab2eb2bfSHubert Tong   bool Result = false;
160ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
161ab2eb2bfSHubert Tong   return Result;
162ab2eb2bfSHubert Tong }
163ab2eb2bfSHubert Tong 
164ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const {
165*a93a33cbSSean Fertile   return toSection(Sec)->Flags & XCOFF::STYP_TEXT;
166ab2eb2bfSHubert Tong }
167ab2eb2bfSHubert Tong 
168ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const {
169*a93a33cbSSean Fertile   unsigned Flags = toSection(Sec)->Flags;
170*a93a33cbSSean Fertile   return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA);
171ab2eb2bfSHubert Tong }
172ab2eb2bfSHubert Tong 
173ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const {
174*a93a33cbSSean Fertile   unsigned Flags = toSection(Sec)->Flags;
175*a93a33cbSSean Fertile   return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS);
176ab2eb2bfSHubert Tong }
177ab2eb2bfSHubert Tong 
178ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const {
179ab2eb2bfSHubert Tong   bool Result = false;
180ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
181ab2eb2bfSHubert Tong   return Result;
182ab2eb2bfSHubert Tong }
183ab2eb2bfSHubert Tong 
184ab2eb2bfSHubert Tong relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const {
185ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
186ab2eb2bfSHubert Tong   return relocation_iterator(RelocationRef());
187ab2eb2bfSHubert Tong }
188ab2eb2bfSHubert Tong 
189ab2eb2bfSHubert Tong relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const {
190ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
191ab2eb2bfSHubert Tong   return relocation_iterator(RelocationRef());
192ab2eb2bfSHubert Tong }
193ab2eb2bfSHubert Tong 
194ab2eb2bfSHubert Tong void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
195ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
196ab2eb2bfSHubert Tong   return;
197ab2eb2bfSHubert Tong }
198ab2eb2bfSHubert Tong 
199ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
200ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
201ab2eb2bfSHubert Tong   uint64_t Result = 0;
202ab2eb2bfSHubert Tong   return Result;
203ab2eb2bfSHubert Tong }
204ab2eb2bfSHubert Tong 
205ab2eb2bfSHubert Tong symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
206ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
207ab2eb2bfSHubert Tong   return symbol_iterator(SymbolRef());
208ab2eb2bfSHubert Tong }
209ab2eb2bfSHubert Tong 
210ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const {
211ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
212ab2eb2bfSHubert Tong   uint64_t Result = 0;
213ab2eb2bfSHubert Tong   return Result;
214ab2eb2bfSHubert Tong }
215ab2eb2bfSHubert Tong 
216ab2eb2bfSHubert Tong void XCOFFObjectFile::getRelocationTypeName(
217ab2eb2bfSHubert Tong     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
218ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
219ab2eb2bfSHubert Tong   return;
220ab2eb2bfSHubert Tong }
221ab2eb2bfSHubert Tong 
222ab2eb2bfSHubert Tong uint32_t XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
223ab2eb2bfSHubert Tong   uint32_t Result = 0;
224ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
225ab2eb2bfSHubert Tong   return Result;
226ab2eb2bfSHubert Tong }
227ab2eb2bfSHubert Tong 
228ab2eb2bfSHubert Tong basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
229ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
230ab2eb2bfSHubert Tong   return basic_symbol_iterator(SymbolRef());
231ab2eb2bfSHubert Tong }
232ab2eb2bfSHubert Tong 
233ab2eb2bfSHubert Tong basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
234ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
235ab2eb2bfSHubert Tong   return basic_symbol_iterator(SymbolRef());
236ab2eb2bfSHubert Tong }
237ab2eb2bfSHubert Tong 
238ab2eb2bfSHubert Tong section_iterator XCOFFObjectFile::section_begin() const {
239*a93a33cbSSean Fertile   DataRefImpl DRI;
240*a93a33cbSSean Fertile   DRI.p = reinterpret_cast<uintptr_t>(SectionHdrTablePtr);
241*a93a33cbSSean Fertile   return section_iterator(SectionRef(DRI, this));
242ab2eb2bfSHubert Tong }
243ab2eb2bfSHubert Tong 
244ab2eb2bfSHubert Tong section_iterator XCOFFObjectFile::section_end() const {
245*a93a33cbSSean Fertile   DataRefImpl DRI;
246*a93a33cbSSean Fertile   DRI.p =
247*a93a33cbSSean Fertile       reinterpret_cast<uintptr_t>(SectionHdrTablePtr + getNumberOfSections());
248*a93a33cbSSean Fertile   return section_iterator(SectionRef(DRI, this));
249ab2eb2bfSHubert Tong }
250ab2eb2bfSHubert Tong 
251ab2eb2bfSHubert Tong uint8_t XCOFFObjectFile::getBytesInAddress() const {
252ab2eb2bfSHubert Tong   uint8_t Result = 0;
253ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
254ab2eb2bfSHubert Tong   return Result;
255ab2eb2bfSHubert Tong }
256ab2eb2bfSHubert Tong 
257ab2eb2bfSHubert Tong StringRef XCOFFObjectFile::getFileFormatName() const {
258*a93a33cbSSean Fertile   assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
259*a93a33cbSSean Fertile   return "aixcoff-rs6000";
260ab2eb2bfSHubert Tong }
261ab2eb2bfSHubert Tong 
262ab2eb2bfSHubert Tong Triple::ArchType XCOFFObjectFile::getArch() const {
263*a93a33cbSSean Fertile   assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
264*a93a33cbSSean Fertile   return Triple::ppc;
265ab2eb2bfSHubert Tong }
266ab2eb2bfSHubert Tong 
267ab2eb2bfSHubert Tong SubtargetFeatures XCOFFObjectFile::getFeatures() const {
268ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
269ab2eb2bfSHubert Tong   return SubtargetFeatures();
270ab2eb2bfSHubert Tong }
271ab2eb2bfSHubert Tong 
272ab2eb2bfSHubert Tong bool XCOFFObjectFile::isRelocatableObject() const {
273ab2eb2bfSHubert Tong   bool Result = false;
274ab2eb2bfSHubert Tong   llvm_unreachable("Not yet implemented!");
275ab2eb2bfSHubert Tong   return Result;
276ab2eb2bfSHubert Tong }
277ab2eb2bfSHubert Tong 
278*a93a33cbSSean Fertile Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
279*a93a33cbSSean Fertile   // TODO FIXME Should get from auxiliary_header->o_entry when support for the
280*a93a33cbSSean Fertile   // auxiliary_header is added.
281*a93a33cbSSean Fertile   return 0;
282*a93a33cbSSean Fertile }
283*a93a33cbSSean Fertile 
284ab2eb2bfSHubert Tong XCOFFObjectFile::XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
285ab2eb2bfSHubert Tong     : ObjectFile(Binary::ID_XCOFF32, Object) {
286ab2eb2bfSHubert Tong 
287ab2eb2bfSHubert Tong   // Current location within the file.
288ab2eb2bfSHubert Tong   uint64_t CurPtr = 0;
289ab2eb2bfSHubert Tong 
290ab2eb2bfSHubert Tong   if ((EC = getObject(FileHdrPtr, Data, base() + CurPtr)))
291ab2eb2bfSHubert Tong     return;
292*a93a33cbSSean Fertile 
293*a93a33cbSSean Fertile   CurPtr += getFileHeaderSize();
294*a93a33cbSSean Fertile   // TODO FIXME we don't have support for an optional header yet, so just skip
295*a93a33cbSSean Fertile   // past it.
296*a93a33cbSSean Fertile   CurPtr += FileHdrPtr->AuxHeaderSize;
297*a93a33cbSSean Fertile 
298*a93a33cbSSean Fertile   if (getNumberOfSections() != 0) {
299*a93a33cbSSean Fertile     if ((EC = getObject(SectionHdrTablePtr, Data, base() + CurPtr,
300*a93a33cbSSean Fertile                         getNumberOfSections() * getSectionHeaderSize())))
301*a93a33cbSSean Fertile       return;
302*a93a33cbSSean Fertile   }
303ab2eb2bfSHubert Tong }
304ab2eb2bfSHubert Tong 
305ab2eb2bfSHubert Tong Expected<std::unique_ptr<ObjectFile>>
306ab2eb2bfSHubert Tong ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object) {
307ab2eb2bfSHubert Tong   StringRef Data = Object.getBuffer();
308ab2eb2bfSHubert Tong   file_magic Type = identify_magic(Data);
309ab2eb2bfSHubert Tong   std::error_code EC;
310ab2eb2bfSHubert Tong   std::unique_ptr<ObjectFile> Ret;
311ab2eb2bfSHubert Tong 
312ab2eb2bfSHubert Tong   if (Type == file_magic::xcoff_object_32) {
313ab2eb2bfSHubert Tong     Ret.reset(new XCOFFObjectFile(Object, EC));
314ab2eb2bfSHubert Tong   } else {
315ab2eb2bfSHubert Tong     llvm_unreachable("Encountered an unexpected binary file type!");
316ab2eb2bfSHubert Tong   }
317ab2eb2bfSHubert Tong 
318ab2eb2bfSHubert Tong   if (EC)
319ab2eb2bfSHubert Tong     return errorCodeToError(EC);
320ab2eb2bfSHubert Tong   return std::move(Ret);
321ab2eb2bfSHubert Tong }
322ab2eb2bfSHubert Tong 
323ab2eb2bfSHubert Tong } // namespace object
324ab2eb2bfSHubert Tong } // namespace llvm
325