blob: db57fbad00235433271a5d8fbbfd040104f20c9a [file] [log] [blame]
Hubert Tongab2eb2b2019-04-04 00:53:21 +00001//===--- XCOFFObjectFile.cpp - XCOFF object file implementation -----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the XCOFFObjectFile class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/Object/XCOFFObjectFile.h"
14#include "llvm/ADT/ArrayRef.h"
15#include "llvm/Support/BinaryStreamReader.h"
16#include "llvm/Support/Endian.h"
17#include "llvm/Support/ErrorHandling.h"
18#include "llvm/Support/MathExtras.h"
19#include <cstddef>
20#include <cstring>
21
22namespace llvm {
23namespace object {
24
Sean Fertilea93a33c2019-04-25 21:36:04 +000025enum { XCOFF32FileHeaderSize = 20 };
26static_assert(sizeof(XCOFFFileHeader) == XCOFF32FileHeaderSize,
27 "Wrong size for XCOFF file header.");
28
Hubert Tongab2eb2b2019-04-04 00:53:21 +000029// Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
30// Returns unexpected_eof on error.
31template <typename T>
32static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
33 const void *Ptr,
34 const uint64_t Size = sizeof(T)) {
35 uintptr_t Addr = uintptr_t(Ptr);
36 if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
37 return EC;
38 Obj = reinterpret_cast<const T *>(Addr);
39 return std::error_code();
40}
41
Sean Fertilea93a33c2019-04-25 21:36:04 +000042template <typename T> static const T *viewAs(uintptr_t in) {
43 return reinterpret_cast<const T *>(in);
44}
45
46const XCOFFSectionHeader *XCOFFObjectFile::toSection(DataRefImpl Ref) const {
47 auto Sec = viewAs<XCOFFSectionHeader>(Ref.p);
48#ifndef NDEBUG
49 if (Sec < SectionHdrTablePtr ||
50 Sec >= (SectionHdrTablePtr + getNumberOfSections()))
51 report_fatal_error("Section header outside of section header table.");
52
53 uintptr_t Offset = uintptr_t(Sec) - uintptr_t(SectionHdrTablePtr);
54 if (Offset % getSectionHeaderSize() != 0)
55 report_fatal_error(
56 "Section header pointer does not point to a valid section header.");
57#endif
58 return Sec;
59}
60
61// The next 2 functions are not exactly necessary yet, but they are useful to
62// abstract over the size difference between XCOFF32 and XCOFF64 structure
63// definitions.
64size_t XCOFFObjectFile::getFileHeaderSize() const {
65 return sizeof(XCOFFFileHeader);
66}
67
68size_t XCOFFObjectFile::getSectionHeaderSize() const {
69 return sizeof(XCOFFSectionHeader);
70}
71
Hubert Tongab2eb2b2019-04-04 00:53:21 +000072void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
73 llvm_unreachable("Not yet implemented!");
74 return;
75}
76
77Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
78 StringRef Result;
79 llvm_unreachable("Not yet implemented!");
80 return Result;
81}
82
83Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
84 uint64_t Result = 0;
85 llvm_unreachable("Not yet implemented!");
86 return Result;
87}
88
89uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
90 uint64_t Result = 0;
91 llvm_unreachable("Not yet implemented!");
92 return Result;
93}
94
95uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
96 uint64_t Result = 0;
97 llvm_unreachable("Not yet implemented!");
98 return Result;
99}
100
101Expected<SymbolRef::Type>
102XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
103 llvm_unreachable("Not yet implemented!");
104 return SymbolRef::ST_Other;
105}
106
107Expected<section_iterator>
108XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
109 llvm_unreachable("Not yet implemented!");
110 return section_iterator(SectionRef());
111}
112
113void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Sean Fertilea93a33c2019-04-25 21:36:04 +0000114 const char *Ptr = reinterpret_cast<const char *>(Sec.p);
115 Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize());
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000116}
117
Fangrui Song8be28cd2019-05-02 10:32:03 +0000118Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const {
Sean Fertilea93a33c2019-04-25 21:36:04 +0000119 const char *Name = toSection(Sec)->Name;
120 auto NulCharPtr =
121 static_cast<const char *>(memchr(Name, '\0', XCOFF::SectionNameSize));
Fangrui Song8be28cd2019-05-02 10:32:03 +0000122 return NulCharPtr ? StringRef(Name, NulCharPtr - Name)
123 : StringRef(Name, XCOFF::SectionNameSize);
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000124}
125
126uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
Sean Fertilea93a33c2019-04-25 21:36:04 +0000127 return toSection(Sec)->VirtualAddress;
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000128}
129
130uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
Sean Fertilea93a33c2019-04-25 21:36:04 +0000131 // Section numbers in XCOFF are numbered beginning at 1. A section number of
132 // zero is used to indicate that a symbol is being imported or is undefined.
133 return toSection(Sec) - SectionHdrTablePtr + 1;
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000134}
135
136uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
Sean Fertilea93a33c2019-04-25 21:36:04 +0000137 return toSection(Sec)->SectionSize;
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000138}
139
Fangrui Songe1cb2c02019-05-14 04:22:51 +0000140Expected<ArrayRef<uint8_t>>
141XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000142 llvm_unreachable("Not yet implemented!");
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000143}
144
145uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
146 uint64_t Result = 0;
147 llvm_unreachable("Not yet implemented!");
148 return Result;
149}
150
151bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
152 bool Result = false;
153 llvm_unreachable("Not yet implemented!");
154 return Result;
155}
156
157bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const {
Sean Fertilea93a33c2019-04-25 21:36:04 +0000158 return toSection(Sec)->Flags & XCOFF::STYP_TEXT;
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000159}
160
161bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const {
Sean Fertilea93a33c2019-04-25 21:36:04 +0000162 unsigned Flags = toSection(Sec)->Flags;
163 return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA);
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000164}
165
166bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const {
Sean Fertilea93a33c2019-04-25 21:36:04 +0000167 unsigned Flags = toSection(Sec)->Flags;
168 return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS);
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000169}
170
171bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const {
172 bool Result = false;
173 llvm_unreachable("Not yet implemented!");
174 return Result;
175}
176
177relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const {
178 llvm_unreachable("Not yet implemented!");
179 return relocation_iterator(RelocationRef());
180}
181
182relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const {
183 llvm_unreachable("Not yet implemented!");
184 return relocation_iterator(RelocationRef());
185}
186
187void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
188 llvm_unreachable("Not yet implemented!");
189 return;
190}
191
192uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
193 llvm_unreachable("Not yet implemented!");
194 uint64_t Result = 0;
195 return Result;
196}
197
198symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
199 llvm_unreachable("Not yet implemented!");
200 return symbol_iterator(SymbolRef());
201}
202
203uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const {
204 llvm_unreachable("Not yet implemented!");
205 uint64_t Result = 0;
206 return Result;
207}
208
209void XCOFFObjectFile::getRelocationTypeName(
210 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
211 llvm_unreachable("Not yet implemented!");
212 return;
213}
214
215uint32_t XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
216 uint32_t Result = 0;
217 llvm_unreachable("Not yet implemented!");
218 return Result;
219}
220
221basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
222 llvm_unreachable("Not yet implemented!");
223 return basic_symbol_iterator(SymbolRef());
224}
225
226basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
227 llvm_unreachable("Not yet implemented!");
228 return basic_symbol_iterator(SymbolRef());
229}
230
231section_iterator XCOFFObjectFile::section_begin() const {
Sean Fertilea93a33c2019-04-25 21:36:04 +0000232 DataRefImpl DRI;
233 DRI.p = reinterpret_cast<uintptr_t>(SectionHdrTablePtr);
234 return section_iterator(SectionRef(DRI, this));
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000235}
236
237section_iterator XCOFFObjectFile::section_end() const {
Sean Fertilea93a33c2019-04-25 21:36:04 +0000238 DataRefImpl DRI;
239 DRI.p =
240 reinterpret_cast<uintptr_t>(SectionHdrTablePtr + getNumberOfSections());
241 return section_iterator(SectionRef(DRI, this));
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000242}
243
244uint8_t XCOFFObjectFile::getBytesInAddress() const {
Sean Fertilefd75ee92019-05-03 12:57:07 +0000245 // Only support 32-bit object files for now ...
246 assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
247 return 4;
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000248}
249
250StringRef XCOFFObjectFile::getFileFormatName() const {
Sean Fertilea93a33c2019-04-25 21:36:04 +0000251 assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
252 return "aixcoff-rs6000";
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000253}
254
255Triple::ArchType XCOFFObjectFile::getArch() const {
Sean Fertilea93a33c2019-04-25 21:36:04 +0000256 assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
257 return Triple::ppc;
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000258}
259
260SubtargetFeatures XCOFFObjectFile::getFeatures() const {
261 llvm_unreachable("Not yet implemented!");
262 return SubtargetFeatures();
263}
264
265bool XCOFFObjectFile::isRelocatableObject() const {
266 bool Result = false;
267 llvm_unreachable("Not yet implemented!");
268 return Result;
269}
270
Sean Fertilea93a33c2019-04-25 21:36:04 +0000271Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
272 // TODO FIXME Should get from auxiliary_header->o_entry when support for the
273 // auxiliary_header is added.
274 return 0;
275}
276
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000277XCOFFObjectFile::XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
278 : ObjectFile(Binary::ID_XCOFF32, Object) {
279
280 // Current location within the file.
281 uint64_t CurPtr = 0;
282
283 if ((EC = getObject(FileHdrPtr, Data, base() + CurPtr)))
284 return;
Sean Fertilea93a33c2019-04-25 21:36:04 +0000285
286 CurPtr += getFileHeaderSize();
287 // TODO FIXME we don't have support for an optional header yet, so just skip
288 // past it.
289 CurPtr += FileHdrPtr->AuxHeaderSize;
290
291 if (getNumberOfSections() != 0) {
292 if ((EC = getObject(SectionHdrTablePtr, Data, base() + CurPtr,
293 getNumberOfSections() * getSectionHeaderSize())))
294 return;
295 }
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000296}
297
Sean Fertilefd75ee92019-05-03 12:57:07 +0000298uint16_t XCOFFObjectFile::getMagic() const {
299 return FileHdrPtr->Magic;
300}
301
302uint16_t XCOFFObjectFile::getNumberOfSections() const {
303 return FileHdrPtr->NumberOfSections;
304}
305
306int32_t XCOFFObjectFile::getTimeStamp() const {
307 return FileHdrPtr->TimeStamp;
308}
309
310uint32_t XCOFFObjectFile::getSymbolTableOffset() const {
311 return FileHdrPtr->SymbolTableOffset;
312}
313
314int32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const {
315 // As far as symbol table size is concerned, if this field is negative it is
316 // to be treated as a 0. However since this field is also used for printing we
317 // don't want to truncate any negative values.
318 return FileHdrPtr->NumberOfSymTableEntries;
319}
320
321uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
322 return FileHdrPtr->AuxHeaderSize;
323}
324
325uint16_t XCOFFObjectFile::getFlags() const {
326 return FileHdrPtr->Flags;
327}
328
Hubert Tongab2eb2b2019-04-04 00:53:21 +0000329Expected<std::unique_ptr<ObjectFile>>
330ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object) {
331 StringRef Data = Object.getBuffer();
332 file_magic Type = identify_magic(Data);
333 std::error_code EC;
334 std::unique_ptr<ObjectFile> Ret;
335
336 if (Type == file_magic::xcoff_object_32) {
337 Ret.reset(new XCOFFObjectFile(Object, EC));
338 } else {
339 llvm_unreachable("Encountered an unexpected binary file type!");
340 }
341
342 if (EC)
343 return errorCodeToError(EC);
344 return std::move(Ret);
345}
346
347} // namespace object
348} // namespace llvm