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