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