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