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