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 25 using namespace llvm; 26 using namespace object; 27 28 namespace llvm { 29 30 typedef MachOObject::LoadCommandInfo LoadCommandInfo; 31 32 class MachOObjectFile : public ObjectFile { 33 public: 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 48 protected: 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 63 private: 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 74 ObjectFile *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 84 void 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 100 void 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 116 SymbolRef MachOObjectFile::getSymbolNext(DataRefImpl DRI) const { 117 DRI.d.b++; 118 moveToNextSymbol(DRI); 119 return SymbolRef(DRI, this); 120 } 121 122 StringRef MachOObjectFile::getSymbolName(DataRefImpl DRI) const { 123 InMemoryStruct<macho::SymbolTableEntry> Entry; 124 getSymbolTableEntry(DRI, Entry); 125 return MachOObj->getStringAtIndex(Entry->StringIndex); 126 } 127 128 uint64_t MachOObjectFile::getSymbolAddress(DataRefImpl DRI) const { 129 InMemoryStruct<macho::SymbolTableEntry> Entry; 130 getSymbolTableEntry(DRI, Entry); 131 return Entry->Value; 132 } 133 134 uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const { 135 return UnknownAddressOrSize; 136 } 137 138 char 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 161 bool MachOObjectFile::isSymbolInternal(DataRefImpl DRI) const { 162 InMemoryStruct<macho::SymbolTableEntry> Entry; 163 getSymbolTableEntry(DRI, Entry); 164 return Entry->Flags & macho::STF_StabsEntryMask; 165 } 166 167 ObjectFile::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 175 ObjectFile::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 185 void 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 206 SectionRef MachOObjectFile::getSectionNext(DataRefImpl DRI) const { 207 DRI.d.b++; 208 moveToNextSection(DRI); 209 return SectionRef(DRI, this); 210 } 211 212 void 213 MachOObjectFile::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 221 StringRef 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 235 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl DRI) const { 236 InMemoryStruct<macho::Section> Sect; 237 getSection(DRI, Sect); 238 return Sect->Address; 239 } 240 241 uint64_t MachOObjectFile::getSectionSize(DataRefImpl DRI) const { 242 InMemoryStruct<macho::Section> Sect; 243 getSection(DRI, Sect); 244 return Sect->Size; 245 } 246 247 StringRef MachOObjectFile::getSectionContents(DataRefImpl DRI) const { 248 InMemoryStruct<macho::Section> Sect; 249 getSection(DRI, Sect); 250 return MachOObj->getData(Sect->Offset, Sect->Size); 251 } 252 253 bool 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 260 ObjectFile::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 267 ObjectFile::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 276 uint8_t MachOObjectFile::getBytesInAddress() const { 277 return MachOObj->is64Bit() ? 8 : 4; 278 } 279 280 StringRef MachOObjectFile::getFileFormatName() const { 281 if (!MachOObj->is64Bit()) { 282 switch (MachOObj->getHeader().CPUType) { 283 case 0x00000007: 284 return "Mach-O 32-bit i386"; 285 case 0x0000000c: 286 return "Mach-O arm"; 287 case 0x00000012: 288 return "Mach-O 32-bit ppc"; 289 default: 290 assert((MachOObj->getHeader().CPUType & 0x01000000) == 0 && 291 "64-bit object file when we're not 64-bit?"); 292 return "Mach-O 32-bit unknown"; 293 } 294 } 295 296 switch (MachOObj->getHeader().CPUType) { 297 case 0x01000007: 298 return "Mach-O 64-bit x86-64"; 299 case 0x01000012: 300 return "Mach-O 64-bit ppc64"; 301 default: 302 assert((MachOObj->getHeader().CPUType & 0x01000000) == 1 && 303 "32-bit object file when we're 64-bit?"); 304 return "Mach-O 64-bit unknown"; 305 } 306 } 307 308 unsigned MachOObjectFile::getArch() const { 309 switch (MachOObj->getHeader().CPUType) { 310 case 0x00000007: 311 return Triple::x86; 312 case 0x01000007: 313 return Triple::x86_64; 314 case 0x0000000c: 315 return Triple::arm; 316 case 0x00000012: 317 return Triple::ppc; 318 case 0x01000012: 319 return Triple::ppc64; 320 default: 321 return Triple::UnknownArch; 322 } 323 } 324 325 } // end namespace llvm 326 327