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 void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 73 llvm_unreachable("Not yet implemented!"); 74 return; 75 } 76 77 Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const { 78 StringRef Result; 79 llvm_unreachable("Not yet implemented!"); 80 return Result; 81 } 82 83 Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { 84 uint64_t Result = 0; 85 llvm_unreachable("Not yet implemented!"); 86 return Result; 87 } 88 89 uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 90 uint64_t Result = 0; 91 llvm_unreachable("Not yet implemented!"); 92 return Result; 93 } 94 95 uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 96 uint64_t Result = 0; 97 llvm_unreachable("Not yet implemented!"); 98 return Result; 99 } 100 101 Expected<SymbolRef::Type> 102 XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const { 103 llvm_unreachable("Not yet implemented!"); 104 return SymbolRef::ST_Other; 105 } 106 107 Expected<section_iterator> 108 XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { 109 llvm_unreachable("Not yet implemented!"); 110 return section_iterator(SectionRef()); 111 } 112 113 void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const { 114 const char *Ptr = reinterpret_cast<const char *>(Sec.p); 115 Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize()); 116 } 117 118 Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const { 119 const char *Name = toSection(Sec)->Name; 120 auto NulCharPtr = 121 static_cast<const char *>(memchr(Name, '\0', XCOFF::SectionNameSize)); 122 return NulCharPtr ? StringRef(Name, NulCharPtr - Name) 123 : StringRef(Name, XCOFF::SectionNameSize); 124 } 125 126 uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const { 127 return toSection(Sec)->VirtualAddress; 128 } 129 130 uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const { 131 // 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; 134 } 135 136 uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const { 137 return toSection(Sec)->SectionSize; 138 } 139 140 std::error_code XCOFFObjectFile::getSectionContents(DataRefImpl Sec, 141 StringRef &Res) const { 142 llvm_unreachable("Not yet implemented!"); 143 return std::error_code(); 144 } 145 146 uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { 147 uint64_t Result = 0; 148 llvm_unreachable("Not yet implemented!"); 149 return Result; 150 } 151 152 bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { 153 bool Result = false; 154 llvm_unreachable("Not yet implemented!"); 155 return Result; 156 } 157 158 bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const { 159 return toSection(Sec)->Flags & XCOFF::STYP_TEXT; 160 } 161 162 bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const { 163 unsigned Flags = toSection(Sec)->Flags; 164 return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA); 165 } 166 167 bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const { 168 unsigned Flags = toSection(Sec)->Flags; 169 return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS); 170 } 171 172 bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const { 173 bool Result = false; 174 llvm_unreachable("Not yet implemented!"); 175 return Result; 176 } 177 178 relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const { 179 llvm_unreachable("Not yet implemented!"); 180 return relocation_iterator(RelocationRef()); 181 } 182 183 relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const { 184 llvm_unreachable("Not yet implemented!"); 185 return relocation_iterator(RelocationRef()); 186 } 187 188 void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 189 llvm_unreachable("Not yet implemented!"); 190 return; 191 } 192 193 uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 194 llvm_unreachable("Not yet implemented!"); 195 uint64_t Result = 0; 196 return Result; 197 } 198 199 symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 200 llvm_unreachable("Not yet implemented!"); 201 return symbol_iterator(SymbolRef()); 202 } 203 204 uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const { 205 llvm_unreachable("Not yet implemented!"); 206 uint64_t Result = 0; 207 return Result; 208 } 209 210 void XCOFFObjectFile::getRelocationTypeName( 211 DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 212 llvm_unreachable("Not yet implemented!"); 213 return; 214 } 215 216 uint32_t XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { 217 uint32_t Result = 0; 218 llvm_unreachable("Not yet implemented!"); 219 return Result; 220 } 221 222 basic_symbol_iterator XCOFFObjectFile::symbol_begin() const { 223 llvm_unreachable("Not yet implemented!"); 224 return basic_symbol_iterator(SymbolRef()); 225 } 226 227 basic_symbol_iterator XCOFFObjectFile::symbol_end() const { 228 llvm_unreachable("Not yet implemented!"); 229 return basic_symbol_iterator(SymbolRef()); 230 } 231 232 section_iterator XCOFFObjectFile::section_begin() const { 233 DataRefImpl DRI; 234 DRI.p = reinterpret_cast<uintptr_t>(SectionHdrTablePtr); 235 return section_iterator(SectionRef(DRI, this)); 236 } 237 238 section_iterator XCOFFObjectFile::section_end() const { 239 DataRefImpl DRI; 240 DRI.p = 241 reinterpret_cast<uintptr_t>(SectionHdrTablePtr + getNumberOfSections()); 242 return section_iterator(SectionRef(DRI, this)); 243 } 244 245 uint8_t XCOFFObjectFile::getBytesInAddress() const { 246 // Only support 32-bit object files for now ... 247 assert(getFileHeaderSize() == XCOFF32FileHeaderSize); 248 return 4; 249 } 250 251 StringRef XCOFFObjectFile::getFileFormatName() const { 252 assert(getFileHeaderSize() == XCOFF32FileHeaderSize); 253 return "aixcoff-rs6000"; 254 } 255 256 Triple::ArchType XCOFFObjectFile::getArch() const { 257 assert(getFileHeaderSize() == XCOFF32FileHeaderSize); 258 return Triple::ppc; 259 } 260 261 SubtargetFeatures XCOFFObjectFile::getFeatures() const { 262 llvm_unreachable("Not yet implemented!"); 263 return SubtargetFeatures(); 264 } 265 266 bool XCOFFObjectFile::isRelocatableObject() const { 267 bool Result = false; 268 llvm_unreachable("Not yet implemented!"); 269 return Result; 270 } 271 272 Expected<uint64_t> XCOFFObjectFile::getStartAddress() const { 273 // TODO FIXME Should get from auxiliary_header->o_entry when support for the 274 // auxiliary_header is added. 275 return 0; 276 } 277 278 XCOFFObjectFile::XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC) 279 : ObjectFile(Binary::ID_XCOFF32, Object) { 280 281 // Current location within the file. 282 uint64_t CurPtr = 0; 283 284 if ((EC = getObject(FileHdrPtr, Data, base() + CurPtr))) 285 return; 286 287 CurPtr += getFileHeaderSize(); 288 // TODO FIXME we don't have support for an optional header yet, so just skip 289 // past it. 290 CurPtr += FileHdrPtr->AuxHeaderSize; 291 292 if (getNumberOfSections() != 0) { 293 if ((EC = getObject(SectionHdrTablePtr, Data, base() + CurPtr, 294 getNumberOfSections() * getSectionHeaderSize()))) 295 return; 296 } 297 } 298 299 uint16_t XCOFFObjectFile::getMagic() const { 300 return FileHdrPtr->Magic; 301 } 302 303 uint16_t XCOFFObjectFile::getNumberOfSections() const { 304 return FileHdrPtr->NumberOfSections; 305 } 306 307 int32_t XCOFFObjectFile::getTimeStamp() const { 308 return FileHdrPtr->TimeStamp; 309 } 310 311 uint32_t XCOFFObjectFile::getSymbolTableOffset() const { 312 return FileHdrPtr->SymbolTableOffset; 313 } 314 315 int32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const { 316 // As far as symbol table size is concerned, if this field is negative it is 317 // to be treated as a 0. However since this field is also used for printing we 318 // don't want to truncate any negative values. 319 return FileHdrPtr->NumberOfSymTableEntries; 320 } 321 322 uint16_t XCOFFObjectFile::getOptionalHeaderSize() const { 323 return FileHdrPtr->AuxHeaderSize; 324 } 325 326 uint16_t XCOFFObjectFile::getFlags() const { 327 return FileHdrPtr->Flags; 328 } 329 330 Expected<std::unique_ptr<ObjectFile>> 331 ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object) { 332 StringRef Data = Object.getBuffer(); 333 file_magic Type = identify_magic(Data); 334 std::error_code EC; 335 std::unique_ptr<ObjectFile> Ret; 336 337 if (Type == file_magic::xcoff_object_32) { 338 Ret.reset(new XCOFFObjectFile(Object, EC)); 339 } else { 340 llvm_unreachable("Encountered an unexpected binary file type!"); 341 } 342 343 if (EC) 344 return errorCodeToError(EC); 345 return std::move(Ret); 346 } 347 348 } // namespace object 349 } // namespace llvm 350