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