ObjectFile.h revision ac241fe9f0d73c6f632e4f7f89e06b698d39da54
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_OBJECT_FILE_H 15#define LLVM_OBJECT_OBJECT_FILE_H 16 17#include "llvm/Object/Binary.h" 18#include "llvm/ADT/StringRef.h" 19#include "llvm/Support/DataTypes.h" 20#include "llvm/Support/ErrorHandling.h" 21#include "llvm/Support/MemoryBuffer.h" 22#include <cstring> 23 24namespace llvm { 25namespace object { 26 27class ObjectFile; 28 29union DataRefImpl { 30 struct { 31 uint32_t a, b; 32 } d; 33 uintptr_t p; 34}; 35 36static bool operator ==(const DataRefImpl &a, const DataRefImpl &b) { 37 // Check bitwise identical. This is the only legal way to compare a union w/o 38 // knowing which member is in use. 39 return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; 40} 41 42/// SymbolRef - This is a value type class that represents a single symbol in 43/// the list of symbols in the object file. 44class SymbolRef { 45 friend class SectionRef; 46 DataRefImpl SymbolPimpl; 47 const ObjectFile *OwningObject; 48 49public: 50 SymbolRef() : OwningObject(NULL) { 51 std::memset(&SymbolPimpl, 0, sizeof(SymbolPimpl)); 52 } 53 54 enum SymbolType { 55 ST_Function, 56 ST_Data, 57 ST_External, // Defined in another object file 58 ST_Other 59 }; 60 61 SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner); 62 63 bool operator==(const SymbolRef &Other) const; 64 65 error_code getNext(SymbolRef &Result) const; 66 67 error_code getName(StringRef &Result) const; 68 error_code getAddress(uint64_t &Result) const; 69 error_code getOffset(uint64_t &Result) const; 70 error_code getSize(uint64_t &Result) const; 71 error_code getSymbolType(SymbolRef::SymbolType &Result) const; 72 73 /// Returns the ascii char that should be displayed in a symbol table dump via 74 /// nm for this symbol. 75 error_code getNMTypeChar(char &Result) const; 76 77 /// Returns true for symbols that are internal to the object file format such 78 /// as section symbols. 79 error_code isInternal(bool &Result) const; 80 81 /// Returns true for symbols that can be used in another objects, 82 /// such as library functions 83 error_code isGlobal(bool &Result) const; 84}; 85 86/// RelocationRef - This is a value type class that represents a single 87/// relocation in the list of relocations in the object file. 88class RelocationRef { 89 DataRefImpl RelocationPimpl; 90 const ObjectFile *OwningObject; 91 92public: 93 RelocationRef() : OwningObject(NULL) { 94 std::memset(&RelocationPimpl, 0, sizeof(RelocationPimpl)); 95 } 96 97 RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner); 98 99 bool operator==(const RelocationRef &Other) const; 100 101 error_code getNext(RelocationRef &Result) const; 102 103 error_code getAddress(uint64_t &Result) const; 104 error_code getSymbol(SymbolRef &Result) const; 105 error_code getType(uint32_t &Result) const; 106 error_code getAdditionalInfo(int64_t &Result) const; 107}; 108 109/// SectionRef - This is a value type class that represents a single section in 110/// the list of sections in the object file. 111class SectionRef { 112 friend class SymbolRef; 113 DataRefImpl SectionPimpl; 114 const ObjectFile *OwningObject; 115 116public: 117 SectionRef() : OwningObject(NULL) { 118 std::memset(&SectionPimpl, 0, sizeof(SectionPimpl)); 119 } 120 121 SectionRef(DataRefImpl SectionP, const ObjectFile *Owner); 122 123 bool operator==(const SectionRef &Other) const; 124 125 error_code getNext(SectionRef &Result) const; 126 127 error_code getName(StringRef &Result) const; 128 error_code getAddress(uint64_t &Result) const; 129 error_code getSize(uint64_t &Result) const; 130 error_code getContents(StringRef &Result) const; 131 132 // FIXME: Move to the normalization layer when it's created. 133 error_code isText(bool &Result) const; 134 135 error_code containsSymbol(SymbolRef S, bool &Result) const; 136}; 137 138const uint64_t UnknownAddressOrSize = ~0ULL; 139 140/// ObjectFile - This class is the base class for all object file types. 141/// Concrete instances of this object are created by createObjectFile, which 142/// figure out which type to create. 143class ObjectFile : public Binary { 144private: 145 ObjectFile(); // = delete 146 ObjectFile(const ObjectFile &other); // = delete 147 148protected: 149 ObjectFile(unsigned int Type, MemoryBuffer *source, error_code &ec); 150 151 const uint8_t *base() const { 152 return reinterpret_cast<const uint8_t *>(Data->getBufferStart()); 153 } 154 155 // These functions are for SymbolRef to call internally. The main goal of 156 // this is to allow SymbolRef::SymbolPimpl to point directly to the symbol 157 // entry in the memory mapped object file. SymbolPimpl cannot contain any 158 // virtual functions because then it could not point into the memory mapped 159 // file. 160 // 161 // Implementations assume that the DataRefImpl is valid and has not been 162 // modified externally. It's UB otherwise. 163 friend class SymbolRef; 164 virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const = 0; 165 virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const = 0; 166 virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const =0; 167 virtual error_code getSymbolOffset(DataRefImpl Symb, uint64_t &Res) const =0; 168 virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const = 0; 169 virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const = 0; 170 virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const = 0; 171 virtual error_code isSymbolGlobal(DataRefImpl Symb, bool &Res) const = 0; 172 virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::SymbolType &Res) const = 0; 173 174 // Same as above for SectionRef. 175 friend class SectionRef; 176 virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const = 0; 177 virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const = 0; 178 virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const =0; 179 virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const = 0; 180 virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res)const=0; 181 virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const = 0; 182 virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, 183 bool &Result) const = 0; 184 185 186 // Same as above for RelocationRef. 187 friend class RelocationRef; 188 virtual error_code getRelocationNext(DataRefImpl Rel, 189 RelocationRef &Res) const = 0; 190 virtual error_code getRelocationAddress(DataRefImpl Rel, 191 uint64_t &Res) const =0; 192 virtual error_code getRelocationSymbol(DataRefImpl Rel, 193 SymbolRef &Res) const = 0; 194 virtual error_code getRelocationType(DataRefImpl Rel, 195 uint32_t &Res) const = 0; 196 virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, 197 int64_t &Res) const = 0; 198 199public: 200 template<class content_type> 201 class content_iterator { 202 content_type Current; 203 public: 204 content_iterator(content_type symb) 205 : Current(symb) {} 206 207 const content_type* operator->() const { 208 return &Current; 209 } 210 211 const content_type &operator*() const { 212 return Current; 213 } 214 215 bool operator==(const content_iterator &other) const { 216 return Current == other.Current; 217 } 218 219 bool operator!=(const content_iterator &other) const { 220 return !(*this == other); 221 } 222 223 content_iterator& increment(error_code &err) { 224 content_type next; 225 if (error_code ec = Current.getNext(next)) 226 err = ec; 227 else 228 Current = next; 229 return *this; 230 } 231 }; 232 233 typedef content_iterator<SymbolRef> symbol_iterator; 234 typedef content_iterator<SectionRef> section_iterator; 235 typedef content_iterator<RelocationRef> relocation_iterator; 236 237 virtual symbol_iterator begin_symbols() const = 0; 238 virtual symbol_iterator end_symbols() const = 0; 239 240 virtual section_iterator begin_sections() const = 0; 241 virtual section_iterator end_sections() const = 0; 242 243 virtual relocation_iterator begin_relocations() const = 0; 244 virtual relocation_iterator end_relocations() const = 0; 245 246 /// @brief The number of bytes used to represent an address in this object 247 /// file format. 248 virtual uint8_t getBytesInAddress() const = 0; 249 250 virtual StringRef getFileFormatName() const = 0; 251 virtual /* Triple::ArchType */ unsigned getArch() const = 0; 252 253 /// @returns Pointer to ObjectFile subclass to handle this type of object. 254 /// @param ObjectPath The path to the object file. ObjectPath.isObject must 255 /// return true. 256 /// @brief Create ObjectFile from path. 257 static ObjectFile *createObjectFile(StringRef ObjectPath); 258 static ObjectFile *createObjectFile(MemoryBuffer *Object); 259 260 static inline bool classof(const Binary *v) { 261 return v->getType() >= isObject && 262 v->getType() < lastObject; 263 } 264 static inline bool classof(const ObjectFile *v) { return true; } 265 266public: 267 static ObjectFile *createCOFFObjectFile(MemoryBuffer *Object); 268 static ObjectFile *createELFObjectFile(MemoryBuffer *Object); 269 static ObjectFile *createMachOObjectFile(MemoryBuffer *Object); 270}; 271 272// Inline function definitions. 273inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner) 274 : SymbolPimpl(SymbolP) 275 , OwningObject(Owner) {} 276 277inline bool SymbolRef::operator==(const SymbolRef &Other) const { 278 return SymbolPimpl == Other.SymbolPimpl; 279} 280 281inline error_code SymbolRef::getNext(SymbolRef &Result) const { 282 return OwningObject->getSymbolNext(SymbolPimpl, Result); 283} 284 285inline error_code SymbolRef::getName(StringRef &Result) const { 286 return OwningObject->getSymbolName(SymbolPimpl, Result); 287} 288 289inline error_code SymbolRef::getAddress(uint64_t &Result) const { 290 return OwningObject->getSymbolAddress(SymbolPimpl, Result); 291} 292 293inline error_code SymbolRef::getOffset(uint64_t &Result) const { 294 return OwningObject->getSymbolOffset(SymbolPimpl, Result); 295} 296 297inline error_code SymbolRef::getSize(uint64_t &Result) const { 298 return OwningObject->getSymbolSize(SymbolPimpl, Result); 299} 300 301inline error_code SymbolRef::getNMTypeChar(char &Result) const { 302 return OwningObject->getSymbolNMTypeChar(SymbolPimpl, Result); 303} 304 305inline error_code SymbolRef::isInternal(bool &Result) const { 306 return OwningObject->isSymbolInternal(SymbolPimpl, Result); 307} 308 309inline error_code SymbolRef::isGlobal(bool &Result) const { 310 return OwningObject->isSymbolGlobal(SymbolPimpl, Result); 311} 312 313inline error_code SymbolRef::getSymbolType(SymbolRef::SymbolType &Result) const { 314 return OwningObject->getSymbolType(SymbolPimpl, Result); 315} 316 317 318/// SectionRef 319inline SectionRef::SectionRef(DataRefImpl SectionP, 320 const ObjectFile *Owner) 321 : SectionPimpl(SectionP) 322 , OwningObject(Owner) {} 323 324inline bool SectionRef::operator==(const SectionRef &Other) const { 325 return SectionPimpl == Other.SectionPimpl; 326} 327 328inline error_code SectionRef::getNext(SectionRef &Result) const { 329 return OwningObject->getSectionNext(SectionPimpl, Result); 330} 331 332inline error_code SectionRef::getName(StringRef &Result) const { 333 return OwningObject->getSectionName(SectionPimpl, Result); 334} 335 336inline error_code SectionRef::getAddress(uint64_t &Result) const { 337 return OwningObject->getSectionAddress(SectionPimpl, Result); 338} 339 340inline error_code SectionRef::getSize(uint64_t &Result) const { 341 return OwningObject->getSectionSize(SectionPimpl, Result); 342} 343 344inline error_code SectionRef::getContents(StringRef &Result) const { 345 return OwningObject->getSectionContents(SectionPimpl, Result); 346} 347 348inline error_code SectionRef::isText(bool &Result) const { 349 return OwningObject->isSectionText(SectionPimpl, Result); 350} 351 352inline error_code SectionRef::containsSymbol(SymbolRef S, bool &Result) const { 353 return OwningObject->sectionContainsSymbol(SectionPimpl, S.SymbolPimpl, 354 Result); 355} 356 357 358/// RelocationRef 359inline RelocationRef::RelocationRef(DataRefImpl RelocationP, 360 const ObjectFile *Owner) 361 : RelocationPimpl(RelocationP) 362 , OwningObject(Owner) {} 363 364inline bool RelocationRef::operator==(const RelocationRef &Other) const { 365 return RelocationPimpl == Other.RelocationPimpl; 366} 367 368inline error_code RelocationRef::getNext(RelocationRef &Result) const { 369 return OwningObject->getRelocationNext(RelocationPimpl, Result); 370} 371 372inline error_code RelocationRef::getAddress(uint64_t &Result) const { 373 return OwningObject->getRelocationAddress(RelocationPimpl, Result); 374} 375 376inline error_code RelocationRef::getSymbol(SymbolRef &Result) const { 377 return OwningObject->getRelocationSymbol(RelocationPimpl, Result); 378} 379 380inline error_code RelocationRef::getType(uint32_t &Result) const { 381 return OwningObject->getRelocationType(RelocationPimpl, Result); 382} 383 384inline error_code RelocationRef::getAdditionalInfo(int64_t &Result) const { 385 return OwningObject->getRelocationAdditionalInfo(RelocationPimpl, Result); 386} 387 388} // end namespace object 389} // end namespace llvm 390 391#endif 392