1 //===- ObjectFile.h - File format independent object file -------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file declares a file format independent ObjectFile class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_OBJECT_OBJECTFILE_H 15 #define LLVM_OBJECT_OBJECTFILE_H 16 17 #include "llvm/ADT/StringRef.h" 18 #include "llvm/Object/SymbolicFile.h" 19 #include "llvm/Support/DataTypes.h" 20 #include "llvm/Support/ErrorHandling.h" 21 #include "llvm/Support/FileSystem.h" 22 #include "llvm/Support/MemoryBuffer.h" 23 #include <cstring> 24 #include <vector> 25 26 namespace llvm { 27 namespace object { 28 29 class ObjectFile; 30 class COFFObjectFile; 31 class MachOObjectFile; 32 33 class SymbolRef; 34 class symbol_iterator; 35 36 /// RelocationRef - This is a value type class that represents a single 37 /// relocation in the list of relocations in the object file. 38 class RelocationRef { 39 DataRefImpl RelocationPimpl; 40 const ObjectFile *OwningObject; 41 42 public: 43 RelocationRef() : OwningObject(nullptr) { } 44 45 RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner); 46 47 bool operator==(const RelocationRef &Other) const; 48 49 void moveNext(); 50 51 std::error_code getAddress(uint64_t &Result) const; 52 std::error_code getOffset(uint64_t &Result) const; 53 symbol_iterator getSymbol() const; 54 std::error_code getType(uint64_t &Result) const; 55 56 /// @brief Indicates whether this relocation should hidden when listing 57 /// relocations, usually because it is the trailing part of a multipart 58 /// relocation that will be printed as part of the leading relocation. 59 std::error_code getHidden(bool &Result) const; 60 61 /// @brief Get a string that represents the type of this relocation. 62 /// 63 /// This is for display purposes only. 64 std::error_code getTypeName(SmallVectorImpl<char> &Result) const; 65 66 /// @brief Get a string that represents the calculation of the value of this 67 /// relocation. 68 /// 69 /// This is for display purposes only. 70 std::error_code getValueString(SmallVectorImpl<char> &Result) const; 71 72 DataRefImpl getRawDataRefImpl() const; 73 const ObjectFile *getObjectFile() const; 74 }; 75 typedef content_iterator<RelocationRef> relocation_iterator; 76 77 /// SectionRef - This is a value type class that represents a single section in 78 /// the list of sections in the object file. 79 class SectionRef; 80 typedef content_iterator<SectionRef> section_iterator; 81 class SectionRef { 82 friend class SymbolRef; 83 DataRefImpl SectionPimpl; 84 const ObjectFile *OwningObject; 85 86 public: 87 SectionRef() : OwningObject(nullptr) { } 88 89 SectionRef(DataRefImpl SectionP, const ObjectFile *Owner); 90 91 bool operator==(const SectionRef &Other) const; 92 bool operator!=(const SectionRef &Other) const; 93 bool operator<(const SectionRef &Other) const; 94 95 void moveNext(); 96 97 std::error_code getName(StringRef &Result) const; 98 uint64_t getAddress() const; 99 uint64_t getSize() const; 100 std::error_code getContents(StringRef &Result) const; 101 102 /// @brief Get the alignment of this section as the actual value (not log 2). 103 uint64_t getAlignment() const; 104 105 bool isText() const; 106 bool isData() const; 107 bool isBSS() const; 108 bool isVirtual() const; 109 110 bool containsSymbol(SymbolRef S) const; 111 112 relocation_iterator relocation_begin() const; 113 relocation_iterator relocation_end() const; 114 iterator_range<relocation_iterator> relocations() const { 115 return iterator_range<relocation_iterator>(relocation_begin(), 116 relocation_end()); 117 } 118 section_iterator getRelocatedSection() const; 119 120 DataRefImpl getRawDataRefImpl() const; 121 const ObjectFile *getObject() const; 122 }; 123 124 /// SymbolRef - This is a value type class that represents a single symbol in 125 /// the list of symbols in the object file. 126 class SymbolRef : public BasicSymbolRef { 127 friend class SectionRef; 128 129 public: 130 SymbolRef() : BasicSymbolRef() {} 131 132 enum Type { 133 ST_Unknown, // Type not specified 134 ST_Data, 135 ST_Debug, 136 ST_File, 137 ST_Function, 138 ST_Other 139 }; 140 141 SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner); 142 143 std::error_code getName(StringRef &Result) const; 144 /// Returns the symbol virtual address (i.e. address at which it will be 145 /// mapped). 146 std::error_code getAddress(uint64_t &Result) const; 147 /// @brief Get the alignment of this symbol as the actual value (not log 2). 148 std::error_code getAlignment(uint32_t &Result) const; 149 std::error_code getSize(uint64_t &Result) const; 150 std::error_code getType(SymbolRef::Type &Result) const; 151 std::error_code getOther(uint8_t &Result) const; 152 153 /// @brief Get section this symbol is defined in reference to. Result is 154 /// end_sections() if it is undefined or is an absolute symbol. 155 std::error_code getSection(section_iterator &Result) const; 156 157 const ObjectFile *getObject() const; 158 }; 159 160 class symbol_iterator : public basic_symbol_iterator { 161 public: 162 symbol_iterator(SymbolRef Sym) : basic_symbol_iterator(Sym) {} 163 symbol_iterator(const basic_symbol_iterator &B) 164 : basic_symbol_iterator(SymbolRef(B->getRawDataRefImpl(), 165 cast<ObjectFile>(B->getObject()))) {} 166 167 const SymbolRef *operator->() const { 168 const BasicSymbolRef &P = basic_symbol_iterator::operator *(); 169 return static_cast<const SymbolRef*>(&P); 170 } 171 172 const SymbolRef &operator*() const { 173 const BasicSymbolRef &P = basic_symbol_iterator::operator *(); 174 return static_cast<const SymbolRef&>(P); 175 } 176 }; 177 178 /// ObjectFile - This class is the base class for all object file types. 179 /// Concrete instances of this object are created by createObjectFile, which 180 /// figures out which type to create. 181 class ObjectFile : public SymbolicFile { 182 virtual void anchor(); 183 ObjectFile() = delete; 184 ObjectFile(const ObjectFile &other) = delete; 185 186 protected: 187 ObjectFile(unsigned int Type, MemoryBufferRef Source); 188 189 const uint8_t *base() const { 190 return reinterpret_cast<const uint8_t *>(Data.getBufferStart()); 191 } 192 193 // These functions are for SymbolRef to call internally. The main goal of 194 // this is to allow SymbolRef::SymbolPimpl to point directly to the symbol 195 // entry in the memory mapped object file. SymbolPimpl cannot contain any 196 // virtual functions because then it could not point into the memory mapped 197 // file. 198 // 199 // Implementations assume that the DataRefImpl is valid and has not been 200 // modified externally. It's UB otherwise. 201 friend class SymbolRef; 202 virtual std::error_code getSymbolName(DataRefImpl Symb, 203 StringRef &Res) const = 0; 204 std::error_code printSymbolName(raw_ostream &OS, 205 DataRefImpl Symb) const override; 206 virtual std::error_code getSymbolAddress(DataRefImpl Symb, 207 uint64_t &Res) const = 0; 208 virtual std::error_code getSymbolAlignment(DataRefImpl Symb, 209 uint32_t &Res) const; 210 virtual std::error_code getSymbolSize(DataRefImpl Symb, 211 uint64_t &Res) const = 0; 212 virtual std::error_code getSymbolType(DataRefImpl Symb, 213 SymbolRef::Type &Res) const = 0; 214 virtual std::error_code getSymbolSection(DataRefImpl Symb, 215 section_iterator &Res) const = 0; 216 virtual std::error_code getSymbolOther(DataRefImpl Symb, 217 uint8_t &Res) const { 218 return object_error::invalid_file_type; 219 } 220 221 // Same as above for SectionRef. 222 friend class SectionRef; 223 virtual void moveSectionNext(DataRefImpl &Sec) const = 0; 224 virtual std::error_code getSectionName(DataRefImpl Sec, 225 StringRef &Res) const = 0; 226 virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0; 227 virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0; 228 virtual std::error_code getSectionContents(DataRefImpl Sec, 229 StringRef &Res) const = 0; 230 virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0; 231 virtual bool isSectionText(DataRefImpl Sec) const = 0; 232 virtual bool isSectionData(DataRefImpl Sec) const = 0; 233 virtual bool isSectionBSS(DataRefImpl Sec) const = 0; 234 // A section is 'virtual' if its contents aren't present in the object image. 235 virtual bool isSectionVirtual(DataRefImpl Sec) const = 0; 236 virtual bool sectionContainsSymbol(DataRefImpl Sec, 237 DataRefImpl Symb) const = 0; 238 virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; 239 virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0; 240 virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; 241 242 // Same as above for RelocationRef. 243 friend class RelocationRef; 244 virtual void moveRelocationNext(DataRefImpl &Rel) const = 0; 245 virtual std::error_code getRelocationAddress(DataRefImpl Rel, 246 uint64_t &Res) const = 0; 247 virtual std::error_code getRelocationOffset(DataRefImpl Rel, 248 uint64_t &Res) const = 0; 249 virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0; 250 virtual std::error_code getRelocationType(DataRefImpl Rel, 251 uint64_t &Res) const = 0; 252 virtual std::error_code 253 getRelocationTypeName(DataRefImpl Rel, 254 SmallVectorImpl<char> &Result) const = 0; 255 virtual std::error_code 256 getRelocationValueString(DataRefImpl Rel, 257 SmallVectorImpl<char> &Result) const = 0; 258 virtual std::error_code getRelocationHidden(DataRefImpl Rel, 259 bool &Result) const { 260 Result = false; 261 return object_error::success; 262 } 263 264 public: 265 typedef iterator_range<symbol_iterator> symbol_iterator_range; 266 symbol_iterator_range symbols() const { 267 return symbol_iterator_range(symbol_begin(), symbol_end()); 268 } 269 270 virtual section_iterator section_begin() const = 0; 271 virtual section_iterator section_end() const = 0; 272 273 typedef iterator_range<section_iterator> section_iterator_range; 274 section_iterator_range sections() const { 275 return section_iterator_range(section_begin(), section_end()); 276 } 277 278 /// @brief The number of bytes used to represent an address in this object 279 /// file format. 280 virtual uint8_t getBytesInAddress() const = 0; 281 282 virtual StringRef getFileFormatName() const = 0; 283 virtual /* Triple::ArchType */ unsigned getArch() const = 0; 284 285 /// Returns platform-specific object flags, if any. 286 virtual std::error_code getPlatformFlags(unsigned &Result) const { 287 Result = 0; 288 return object_error::invalid_file_type; 289 } 290 291 /// True if this is a relocatable object (.o/.obj). 292 virtual bool isRelocatableObject() const = 0; 293 294 /// @returns Pointer to ObjectFile subclass to handle this type of object. 295 /// @param ObjectPath The path to the object file. ObjectPath.isObject must 296 /// return true. 297 /// @brief Create ObjectFile from path. 298 static ErrorOr<OwningBinary<ObjectFile>> 299 createObjectFile(StringRef ObjectPath); 300 301 static ErrorOr<std::unique_ptr<ObjectFile>> 302 createObjectFile(MemoryBufferRef Object, sys::fs::file_magic Type); 303 static ErrorOr<std::unique_ptr<ObjectFile>> 304 createObjectFile(MemoryBufferRef Object) { 305 return createObjectFile(Object, sys::fs::file_magic::unknown); 306 } 307 308 309 static inline bool classof(const Binary *v) { 310 return v->isObject(); 311 } 312 313 static ErrorOr<std::unique_ptr<COFFObjectFile>> 314 createCOFFObjectFile(MemoryBufferRef Object); 315 316 static ErrorOr<std::unique_ptr<ObjectFile>> 317 createELFObjectFile(MemoryBufferRef Object); 318 319 static ErrorOr<std::unique_ptr<MachOObjectFile>> 320 createMachOObjectFile(MemoryBufferRef Object); 321 }; 322 323 // Inline function definitions. 324 inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner) 325 : BasicSymbolRef(SymbolP, Owner) {} 326 327 inline std::error_code SymbolRef::getName(StringRef &Result) const { 328 return getObject()->getSymbolName(getRawDataRefImpl(), Result); 329 } 330 331 inline std::error_code SymbolRef::getAddress(uint64_t &Result) const { 332 return getObject()->getSymbolAddress(getRawDataRefImpl(), Result); 333 } 334 335 inline std::error_code SymbolRef::getAlignment(uint32_t &Result) const { 336 return getObject()->getSymbolAlignment(getRawDataRefImpl(), Result); 337 } 338 339 inline std::error_code SymbolRef::getSize(uint64_t &Result) const { 340 return getObject()->getSymbolSize(getRawDataRefImpl(), Result); 341 } 342 343 inline std::error_code SymbolRef::getSection(section_iterator &Result) const { 344 return getObject()->getSymbolSection(getRawDataRefImpl(), Result); 345 } 346 347 inline std::error_code SymbolRef::getType(SymbolRef::Type &Result) const { 348 return getObject()->getSymbolType(getRawDataRefImpl(), Result); 349 } 350 351 inline std::error_code SymbolRef::getOther(uint8_t &Result) const { 352 return getObject()->getSymbolOther(getRawDataRefImpl(), Result); 353 } 354 355 inline const ObjectFile *SymbolRef::getObject() const { 356 const SymbolicFile *O = BasicSymbolRef::getObject(); 357 return cast<ObjectFile>(O); 358 } 359 360 361 /// SectionRef 362 inline SectionRef::SectionRef(DataRefImpl SectionP, 363 const ObjectFile *Owner) 364 : SectionPimpl(SectionP) 365 , OwningObject(Owner) {} 366 367 inline bool SectionRef::operator==(const SectionRef &Other) const { 368 return SectionPimpl == Other.SectionPimpl; 369 } 370 371 inline bool SectionRef::operator!=(const SectionRef &Other) const { 372 return SectionPimpl != Other.SectionPimpl; 373 } 374 375 inline bool SectionRef::operator<(const SectionRef &Other) const { 376 return SectionPimpl < Other.SectionPimpl; 377 } 378 379 inline void SectionRef::moveNext() { 380 return OwningObject->moveSectionNext(SectionPimpl); 381 } 382 383 inline std::error_code SectionRef::getName(StringRef &Result) const { 384 return OwningObject->getSectionName(SectionPimpl, Result); 385 } 386 387 inline uint64_t SectionRef::getAddress() const { 388 return OwningObject->getSectionAddress(SectionPimpl); 389 } 390 391 inline uint64_t SectionRef::getSize() const { 392 return OwningObject->getSectionSize(SectionPimpl); 393 } 394 395 inline std::error_code SectionRef::getContents(StringRef &Result) const { 396 return OwningObject->getSectionContents(SectionPimpl, Result); 397 } 398 399 inline uint64_t SectionRef::getAlignment() const { 400 return OwningObject->getSectionAlignment(SectionPimpl); 401 } 402 403 inline bool SectionRef::isText() const { 404 return OwningObject->isSectionText(SectionPimpl); 405 } 406 407 inline bool SectionRef::isData() const { 408 return OwningObject->isSectionData(SectionPimpl); 409 } 410 411 inline bool SectionRef::isBSS() const { 412 return OwningObject->isSectionBSS(SectionPimpl); 413 } 414 415 inline bool SectionRef::isVirtual() const { 416 return OwningObject->isSectionVirtual(SectionPimpl); 417 } 418 419 inline bool SectionRef::containsSymbol(SymbolRef S) const { 420 return OwningObject->sectionContainsSymbol(SectionPimpl, 421 S.getRawDataRefImpl()); 422 } 423 424 inline relocation_iterator SectionRef::relocation_begin() const { 425 return OwningObject->section_rel_begin(SectionPimpl); 426 } 427 428 inline relocation_iterator SectionRef::relocation_end() const { 429 return OwningObject->section_rel_end(SectionPimpl); 430 } 431 432 inline section_iterator SectionRef::getRelocatedSection() const { 433 return OwningObject->getRelocatedSection(SectionPimpl); 434 } 435 436 inline DataRefImpl SectionRef::getRawDataRefImpl() const { 437 return SectionPimpl; 438 } 439 440 inline const ObjectFile *SectionRef::getObject() const { 441 return OwningObject; 442 } 443 444 /// RelocationRef 445 inline RelocationRef::RelocationRef(DataRefImpl RelocationP, 446 const ObjectFile *Owner) 447 : RelocationPimpl(RelocationP) 448 , OwningObject(Owner) {} 449 450 inline bool RelocationRef::operator==(const RelocationRef &Other) const { 451 return RelocationPimpl == Other.RelocationPimpl; 452 } 453 454 inline void RelocationRef::moveNext() { 455 return OwningObject->moveRelocationNext(RelocationPimpl); 456 } 457 458 inline std::error_code RelocationRef::getAddress(uint64_t &Result) const { 459 return OwningObject->getRelocationAddress(RelocationPimpl, Result); 460 } 461 462 inline std::error_code RelocationRef::getOffset(uint64_t &Result) const { 463 return OwningObject->getRelocationOffset(RelocationPimpl, Result); 464 } 465 466 inline symbol_iterator RelocationRef::getSymbol() const { 467 return OwningObject->getRelocationSymbol(RelocationPimpl); 468 } 469 470 inline std::error_code RelocationRef::getType(uint64_t &Result) const { 471 return OwningObject->getRelocationType(RelocationPimpl, Result); 472 } 473 474 inline std::error_code 475 RelocationRef::getTypeName(SmallVectorImpl<char> &Result) const { 476 return OwningObject->getRelocationTypeName(RelocationPimpl, Result); 477 } 478 479 inline std::error_code 480 RelocationRef::getValueString(SmallVectorImpl<char> &Result) const { 481 return OwningObject->getRelocationValueString(RelocationPimpl, Result); 482 } 483 484 inline std::error_code RelocationRef::getHidden(bool &Result) const { 485 return OwningObject->getRelocationHidden(RelocationPimpl, Result); 486 } 487 488 inline DataRefImpl RelocationRef::getRawDataRefImpl() const { 489 return RelocationPimpl; 490 } 491 492 inline const ObjectFile *RelocationRef::getObjectFile() const { 493 return OwningObject; 494 } 495 496 497 } // end namespace object 498 } // end namespace llvm 499 500 #endif 501