MachOObjectFile.cpp revision 6256b03674f4d50d1c035aa3ecba45df1345ea79
1//===- MachOObjectFile.cpp - Mach-O object file binding ---------*- 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 defines the MachOObjectFile class, which binds the MachOObject 11// class to the generic ObjectFile wrapper. 12// 13//===----------------------------------------------------------------------===// 14 15#include "llvm/ADT/Triple.h" 16#include "llvm/Object/MachOFormat.h" 17#include "llvm/Object/MachOObject.h" 18#include "llvm/Object/ObjectFile.h" 19#include "llvm/Support/MemoryBuffer.h" 20 21#include <cctype> 22#include <cstring> 23#include <limits> 24 25using namespace llvm; 26using namespace object; 27 28namespace llvm { 29 30typedef MachOObject::LoadCommandInfo LoadCommandInfo; 31 32class MachOObjectFile : public ObjectFile { 33public: 34 MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO) 35 : ObjectFile(Object), 36 MachOObj(MOO), 37 RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {} 38 39 virtual symbol_iterator begin_symbols() const; 40 virtual symbol_iterator end_symbols() const; 41 virtual section_iterator begin_sections() const; 42 virtual section_iterator end_sections() const; 43 44 virtual uint8_t getBytesInAddress() const; 45 virtual StringRef getFileFormatName() const; 46 virtual unsigned getArch() const; 47 48protected: 49 virtual SymbolRef getSymbolNext(DataRefImpl Symb) const; 50 virtual StringRef getSymbolName(DataRefImpl Symb) const; 51 virtual uint64_t getSymbolAddress(DataRefImpl Symb) const; 52 virtual uint64_t getSymbolSize(DataRefImpl Symb) const; 53 virtual char getSymbolNMTypeChar(DataRefImpl Symb) const; 54 virtual bool isSymbolInternal(DataRefImpl Symb) const; 55 56 virtual SectionRef getSectionNext(DataRefImpl Sec) const; 57 virtual StringRef getSectionName(DataRefImpl Sec) const; 58 virtual uint64_t getSectionAddress(DataRefImpl Sec) const; 59 virtual uint64_t getSectionSize(DataRefImpl Sec) const; 60 virtual StringRef getSectionContents(DataRefImpl Sec) const; 61 virtual bool isSectionText(DataRefImpl Sec) const; 62 63private: 64 MachOObject *MachOObj; 65 mutable uint32_t RegisteredStringTable; 66 67 void moveToNextSection(DataRefImpl &DRI) const; 68 void getSymbolTableEntry(DataRefImpl DRI, 69 InMemoryStruct<macho::SymbolTableEntry> &Res) const; 70 void moveToNextSymbol(DataRefImpl &DRI) const; 71 void getSection(DataRefImpl DRI, InMemoryStruct<macho::Section> &Res) const; 72}; 73 74ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { 75 std::string Err; 76 MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err); 77 if (!MachOObj) 78 return NULL; 79 return new MachOObjectFile(Buffer, MachOObj); 80} 81 82/*===-- Symbols -----------------------------------------------------------===*/ 83 84void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { 85 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 86 while (DRI.d.a < LoadCommandCount) { 87 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 88 if (LCI.Command.Type == macho::LCT_Symtab) { 89 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd; 90 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); 91 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries) 92 return; 93 } 94 95 DRI.d.a++; 96 DRI.d.b = 0; 97 } 98} 99 100void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, 101 InMemoryStruct<macho::SymbolTableEntry> &Res) const { 102 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd; 103 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 104 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); 105 106 if (RegisteredStringTable != DRI.d.a) { 107 MachOObj->RegisterStringTable(*SymtabLoadCmd); 108 RegisteredStringTable = DRI.d.a; 109 } 110 111 MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b, 112 Res); 113} 114 115 116SymbolRef MachOObjectFile::getSymbolNext(DataRefImpl DRI) const { 117 DRI.d.b++; 118 moveToNextSymbol(DRI); 119 return SymbolRef(DRI, this); 120} 121 122StringRef MachOObjectFile::getSymbolName(DataRefImpl DRI) const { 123 InMemoryStruct<macho::SymbolTableEntry> Entry; 124 getSymbolTableEntry(DRI, Entry); 125 return MachOObj->getStringAtIndex(Entry->StringIndex); 126} 127 128uint64_t MachOObjectFile::getSymbolAddress(DataRefImpl DRI) const { 129 InMemoryStruct<macho::SymbolTableEntry> Entry; 130 getSymbolTableEntry(DRI, Entry); 131 return Entry->Value; 132} 133 134uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const { 135 return UnknownAddressOrSize; 136} 137 138char MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI) const { 139 InMemoryStruct<macho::SymbolTableEntry> Entry; 140 getSymbolTableEntry(DRI, Entry); 141 142 char Char; 143 switch (Entry->Type & macho::STF_TypeMask) { 144 case macho::STT_Undefined: 145 Char = 'u'; 146 break; 147 case macho::STT_Absolute: 148 case macho::STT_Section: 149 Char = 's'; 150 break; 151 default: 152 Char = '?'; 153 break; 154 } 155 156 if (Entry->Flags & (macho::STF_External | macho::STF_PrivateExtern)) 157 Char = toupper(Char); 158 return Char; 159} 160 161bool MachOObjectFile::isSymbolInternal(DataRefImpl DRI) const { 162 InMemoryStruct<macho::SymbolTableEntry> Entry; 163 getSymbolTableEntry(DRI, Entry); 164 return Entry->Flags & macho::STF_StabsEntryMask; 165} 166 167ObjectFile::symbol_iterator MachOObjectFile::begin_symbols() const { 168 // DRI.d.a = segment number; DRI.d.b = symbol index. 169 DataRefImpl DRI; 170 DRI.d.a = DRI.d.b = 0; 171 moveToNextSymbol(DRI); 172 return symbol_iterator(SymbolRef(DRI, this)); 173} 174 175ObjectFile::symbol_iterator MachOObjectFile::end_symbols() const { 176 DataRefImpl DRI; 177 DRI.d.a = MachOObj->getHeader().NumLoadCommands; 178 DRI.d.b = 0; 179 return symbol_iterator(SymbolRef(DRI, this)); 180} 181 182 183/*===-- Sections ----------------------------------------------------------===*/ 184 185void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { 186 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 187 while (DRI.d.a < LoadCommandCount) { 188 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 189 if (LCI.Command.Type == macho::LCT_Segment) { 190 InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd; 191 MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd); 192 if (DRI.d.b < SegmentLoadCmd->NumSections) 193 return; 194 } else if (LCI.Command.Type == macho::LCT_Segment64) { 195 InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd; 196 MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd); 197 if (DRI.d.b < Segment64LoadCmd->NumSections) 198 return; 199 } 200 201 DRI.d.a++; 202 DRI.d.b = 0; 203 } 204} 205 206SectionRef MachOObjectFile::getSectionNext(DataRefImpl DRI) const { 207 DRI.d.b++; 208 moveToNextSection(DRI); 209 return SectionRef(DRI, this); 210} 211 212void 213MachOObjectFile::getSection(DataRefImpl DRI, 214 InMemoryStruct<macho::Section> &Res) const { 215 InMemoryStruct<macho::SegmentLoadCommand> SLC; 216 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 217 MachOObj->ReadSegmentLoadCommand(LCI, SLC); 218 MachOObj->ReadSection(LCI, DRI.d.b, Res); 219} 220 221StringRef MachOObjectFile::getSectionName(DataRefImpl DRI) const { 222 InMemoryStruct<macho::SegmentLoadCommand> SLC; 223 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 224 MachOObj->ReadSegmentLoadCommand(LCI, SLC); 225 InMemoryStruct<macho::Section> Sect; 226 MachOObj->ReadSection(LCI, DRI.d.b, Sect); 227 228 static char Result[34]; 229 strcpy(Result, SLC->Name); 230 strcat(Result, ","); 231 strcat(Result, Sect->Name); 232 return StringRef(Result); 233} 234 235uint64_t MachOObjectFile::getSectionAddress(DataRefImpl DRI) const { 236 InMemoryStruct<macho::Section> Sect; 237 getSection(DRI, Sect); 238 return Sect->Address; 239} 240 241uint64_t MachOObjectFile::getSectionSize(DataRefImpl DRI) const { 242 InMemoryStruct<macho::Section> Sect; 243 getSection(DRI, Sect); 244 return Sect->Size; 245} 246 247StringRef MachOObjectFile::getSectionContents(DataRefImpl DRI) const { 248 InMemoryStruct<macho::Section> Sect; 249 getSection(DRI, Sect); 250 return MachOObj->getData(Sect->Offset, Sect->Size); 251} 252 253bool MachOObjectFile::isSectionText(DataRefImpl DRI) const { 254 InMemoryStruct<macho::SegmentLoadCommand> SLC; 255 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 256 MachOObj->ReadSegmentLoadCommand(LCI, SLC); 257 return !strcmp(SLC->Name, "__TEXT"); 258} 259 260ObjectFile::section_iterator MachOObjectFile::begin_sections() const { 261 DataRefImpl DRI; 262 DRI.d.a = DRI.d.b = 0; 263 moveToNextSection(DRI); 264 return section_iterator(SectionRef(DRI, this)); 265} 266 267ObjectFile::section_iterator MachOObjectFile::end_sections() const { 268 DataRefImpl DRI; 269 DRI.d.a = MachOObj->getHeader().NumLoadCommands; 270 DRI.d.b = 0; 271 return section_iterator(SectionRef(DRI, this)); 272} 273 274/*===-- Miscellaneous -----------------------------------------------------===*/ 275 276uint8_t MachOObjectFile::getBytesInAddress() const { 277 return MachOObj->is64Bit() ? 8 : 4; 278} 279 280StringRef MachOObjectFile::getFileFormatName() const { 281 if (!MachOObj->is64Bit()) { 282 switch (MachOObj->getHeader().CPUType) { 283 case 0x00000007: 284 return "MACHO32-i386"; 285 case 0x01000007: 286 return "MACHO32-x86-64"; 287 case 0x0000000c: 288 return "MACHO32-arm"; 289 case 0x00000012: 290 return "MACHO32-ppc"; 291 case 0x01000012: 292 return "MACHO32-ppc64"; 293 } 294 } 295 296 switch (MachOObj->getHeader().CPUType) { 297 case 0x00000007: 298 return "MACHO64-i386"; 299 case 0x01000007: 300 return "MACHO64-x86-64"; 301 case 0x0000000c: 302 return "MACHO64-arm"; 303 case 0x00000012: 304 return "MACHO64-ppc"; 305 case 0x01000012: 306 return "MACHO64-ppc64"; 307 default: 308 return "MACHO64-unknown"; 309 } 310} 311 312unsigned MachOObjectFile::getArch() const { 313 switch (MachOObj->getHeader().CPUType) { 314 case 0x00000007: 315 return Triple::x86; 316 case 0x01000007: 317 return Triple::x86_64; 318 case 0x0000000c: 319 return Triple::arm; 320 case 0x00000012: 321 return Triple::ppc; 322 case 0x01000012: 323 return Triple::ppc64; 324 default: 325 return Triple::UnknownArch; 326 } 327} 328 329} // end namespace llvm 330 331