MachOObjectFile.cpp revision 5f4e02cbf1d0fa0d8048369264201c258f2ad717
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/MachO.h" 17#include "llvm/Object/MachOFormat.h" 18#include "llvm/Support/MemoryBuffer.h" 19 20#include <cctype> 21#include <cstring> 22#include <limits> 23 24using namespace llvm; 25using namespace object; 26 27namespace llvm { 28namespace object { 29 30MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, 31 error_code &ec) 32 : ObjectFile(Binary::isMachO, Object, ec), 33 MachOObj(MOO), 34 RegisteredStringTable(std::numeric_limits<uint32_t>::max()) { 35 DataRefImpl DRI; 36 DRI.d.a = DRI.d.b = 0; 37 moveToNextSection(DRI); 38 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 39 while (DRI.d.a < LoadCommandCount) { 40 Sections.push_back(DRI); 41 DRI.d.b++; 42 moveToNextSection(DRI); 43 } 44} 45 46 47ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { 48 error_code ec; 49 std::string Err; 50 MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err); 51 if (!MachOObj) 52 return NULL; 53 return new MachOObjectFile(Buffer, MachOObj, ec); 54} 55 56/*===-- Symbols -----------------------------------------------------------===*/ 57 58void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { 59 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 60 while (DRI.d.a < LoadCommandCount) { 61 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 62 if (LCI.Command.Type == macho::LCT_Symtab) { 63 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd; 64 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); 65 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries) 66 return; 67 } 68 69 DRI.d.a++; 70 DRI.d.b = 0; 71 } 72} 73 74void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, 75 InMemoryStruct<macho::SymbolTableEntry> &Res) const { 76 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd; 77 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 78 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); 79 80 if (RegisteredStringTable != DRI.d.a) { 81 MachOObj->RegisterStringTable(*SymtabLoadCmd); 82 RegisteredStringTable = DRI.d.a; 83 } 84 85 MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b, 86 Res); 87} 88 89void MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI, 90 InMemoryStruct<macho::Symbol64TableEntry> &Res) const { 91 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd; 92 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 93 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); 94 95 if (RegisteredStringTable != DRI.d.a) { 96 MachOObj->RegisterStringTable(*SymtabLoadCmd); 97 RegisteredStringTable = DRI.d.a; 98 } 99 100 MachOObj->ReadSymbol64TableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b, 101 Res); 102} 103 104 105error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI, 106 SymbolRef &Result) const { 107 DRI.d.b++; 108 moveToNextSymbol(DRI); 109 Result = SymbolRef(DRI, this); 110 return object_error::success; 111} 112 113error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, 114 StringRef &Result) const { 115 if (MachOObj->is64Bit()) { 116 InMemoryStruct<macho::Symbol64TableEntry> Entry; 117 getSymbol64TableEntry(DRI, Entry); 118 Result = MachOObj->getStringAtIndex(Entry->StringIndex); 119 } else { 120 InMemoryStruct<macho::SymbolTableEntry> Entry; 121 getSymbolTableEntry(DRI, Entry); 122 Result = MachOObj->getStringAtIndex(Entry->StringIndex); 123 } 124 return object_error::success; 125} 126 127error_code MachOObjectFile::getSymbolOffset(DataRefImpl DRI, 128 uint64_t &Result) const { 129 uint64_t SectionOffset; 130 uint8_t SectionIndex; 131 if (MachOObj->is64Bit()) { 132 InMemoryStruct<macho::Symbol64TableEntry> Entry; 133 getSymbol64TableEntry(DRI, Entry); 134 Result = Entry->Value; 135 SectionIndex = Entry->SectionIndex; 136 } else { 137 InMemoryStruct<macho::SymbolTableEntry> Entry; 138 getSymbolTableEntry(DRI, Entry); 139 Result = Entry->Value; 140 SectionIndex = Entry->SectionIndex; 141 } 142 getSectionAddress(Sections[SectionIndex-1], SectionOffset); 143 Result -= SectionOffset; 144 145 return object_error::success; 146} 147 148error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI, 149 uint64_t &Result) const { 150 if (MachOObj->is64Bit()) { 151 InMemoryStruct<macho::Symbol64TableEntry> Entry; 152 getSymbol64TableEntry(DRI, Entry); 153 Result = Entry->Value; 154 } else { 155 InMemoryStruct<macho::SymbolTableEntry> Entry; 156 getSymbolTableEntry(DRI, Entry); 157 Result = Entry->Value; 158 } 159 return object_error::success; 160} 161 162error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, 163 uint64_t &Result) const { 164 Result = UnknownAddressOrSize; 165 return object_error::success; 166} 167 168error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, 169 char &Result) const { 170 uint8_t Type, Flags; 171 if (MachOObj->is64Bit()) { 172 InMemoryStruct<macho::Symbol64TableEntry> Entry; 173 getSymbol64TableEntry(DRI, Entry); 174 Type = Entry->Type; 175 Flags = Entry->Flags; 176 } else { 177 InMemoryStruct<macho::SymbolTableEntry> Entry; 178 getSymbolTableEntry(DRI, Entry); 179 Type = Entry->Type; 180 Flags = Entry->Flags; 181 } 182 183 char Char; 184 switch (Type & macho::STF_TypeMask) { 185 case macho::STT_Undefined: 186 Char = 'u'; 187 break; 188 case macho::STT_Absolute: 189 case macho::STT_Section: 190 Char = 's'; 191 break; 192 default: 193 Char = '?'; 194 break; 195 } 196 197 if (Flags & (macho::STF_External | macho::STF_PrivateExtern)) 198 Char = toupper(Char); 199 Result = Char; 200 return object_error::success; 201} 202 203error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI, 204 bool &Result) const { 205 if (MachOObj->is64Bit()) { 206 InMemoryStruct<macho::Symbol64TableEntry> Entry; 207 getSymbol64TableEntry(DRI, Entry); 208 Result = Entry->Flags & macho::STF_StabsEntryMask; 209 } else { 210 InMemoryStruct<macho::SymbolTableEntry> Entry; 211 getSymbolTableEntry(DRI, Entry); 212 Result = Entry->Flags & macho::STF_StabsEntryMask; 213 } 214 return object_error::success; 215} 216 217error_code MachOObjectFile::isSymbolGlobal(DataRefImpl Symb, bool &Res) const { 218 219 if (MachOObj->is64Bit()) { 220 InMemoryStruct<macho::Symbol64TableEntry> Entry; 221 getSymbol64TableEntry(Symb, Entry); 222 Res = Entry->Type & MachO::NlistMaskExternal; 223 } else { 224 InMemoryStruct<macho::SymbolTableEntry> Entry; 225 getSymbolTableEntry(Symb, Entry); 226 Res = Entry->Type & MachO::NlistMaskExternal; 227 } 228 return object_error::success; 229} 230 231error_code MachOObjectFile::isSymbolWeak(DataRefImpl Symb, bool &Res) const { 232 233 if (MachOObj->is64Bit()) { 234 InMemoryStruct<macho::Symbol64TableEntry> Entry; 235 getSymbol64TableEntry(Symb, Entry); 236 Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef); 237 } else { 238 InMemoryStruct<macho::SymbolTableEntry> Entry; 239 getSymbolTableEntry(Symb, Entry); 240 Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef); 241 } 242 return object_error::success; 243} 244 245error_code MachOObjectFile::isSymbolAbsolute(DataRefImpl Symb, bool &Res) const{ 246 uint8_t n_type; 247 if (MachOObj->is64Bit()) { 248 InMemoryStruct<macho::Symbol64TableEntry> Entry; 249 getSymbol64TableEntry(Symb, Entry); 250 n_type = Entry->Type; 251 } else { 252 InMemoryStruct<macho::SymbolTableEntry> Entry; 253 getSymbolTableEntry(Symb, Entry); 254 n_type = Entry->Type; 255 } 256 257 Res = (n_type & MachO::NlistMaskType) == MachO::NListTypeAbsolute; 258 return object_error::success; 259} 260 261error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, 262 section_iterator &Res) const { 263 uint8_t index; 264 if (MachOObj->is64Bit()) { 265 InMemoryStruct<macho::Symbol64TableEntry> Entry; 266 getSymbol64TableEntry(Symb, Entry); 267 index = Entry->SectionIndex; 268 } else { 269 InMemoryStruct<macho::SymbolTableEntry> Entry; 270 getSymbolTableEntry(Symb, Entry); 271 index = Entry->SectionIndex; 272 } 273 274 if (index == 0) 275 Res = end_sections(); 276 else 277 Res = section_iterator(SectionRef(Sections[index], this)); 278 279 return object_error::success; 280} 281 282error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, 283 SymbolRef::Type &Res) const { 284 uint8_t n_type; 285 if (MachOObj->is64Bit()) { 286 InMemoryStruct<macho::Symbol64TableEntry> Entry; 287 getSymbol64TableEntry(Symb, Entry); 288 n_type = Entry->Type; 289 } else { 290 InMemoryStruct<macho::SymbolTableEntry> Entry; 291 getSymbolTableEntry(Symb, Entry); 292 n_type = Entry->Type; 293 } 294 Res = SymbolRef::ST_Other; 295 296 // If this is a STAB debugging symbol, we can do nothing more. 297 if (n_type & MachO::NlistMaskStab) { 298 Res = SymbolRef::ST_Debug; 299 return object_error::success; 300 } 301 302 switch (n_type & MachO::NlistMaskType) { 303 case MachO::NListTypeUndefined : 304 Res = SymbolRef::ST_External; 305 break; 306 case MachO::NListTypeSection : 307 Res = SymbolRef::ST_Function; 308 break; 309 } 310 return object_error::success; 311} 312 313 314symbol_iterator MachOObjectFile::begin_symbols() const { 315 // DRI.d.a = segment number; DRI.d.b = symbol index. 316 DataRefImpl DRI; 317 DRI.d.a = DRI.d.b = 0; 318 moveToNextSymbol(DRI); 319 return symbol_iterator(SymbolRef(DRI, this)); 320} 321 322symbol_iterator MachOObjectFile::end_symbols() const { 323 DataRefImpl DRI; 324 DRI.d.a = MachOObj->getHeader().NumLoadCommands; 325 DRI.d.b = 0; 326 return symbol_iterator(SymbolRef(DRI, this)); 327} 328 329 330/*===-- Sections ----------------------------------------------------------===*/ 331 332void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { 333 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 334 while (DRI.d.a < LoadCommandCount) { 335 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 336 if (LCI.Command.Type == macho::LCT_Segment) { 337 InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd; 338 MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd); 339 if (DRI.d.b < SegmentLoadCmd->NumSections) 340 return; 341 } else if (LCI.Command.Type == macho::LCT_Segment64) { 342 InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd; 343 MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd); 344 if (DRI.d.b < Segment64LoadCmd->NumSections) 345 return; 346 } 347 348 DRI.d.a++; 349 DRI.d.b = 0; 350 } 351} 352 353error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, 354 SectionRef &Result) const { 355 DRI.d.b++; 356 moveToNextSection(DRI); 357 Result = SectionRef(DRI, this); 358 return object_error::success; 359} 360 361void 362MachOObjectFile::getSection(DataRefImpl DRI, 363 InMemoryStruct<macho::Section> &Res) const { 364 InMemoryStruct<macho::SegmentLoadCommand> SLC; 365 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 366 MachOObj->ReadSegmentLoadCommand(LCI, SLC); 367 MachOObj->ReadSection(LCI, DRI.d.b, Res); 368} 369 370std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { 371 SectionList::const_iterator loc = 372 std::find(Sections.begin(), Sections.end(), Sec); 373 assert(loc != Sections.end() && "Sec is not a valid section!"); 374 return std::distance(Sections.begin(), loc); 375} 376 377void 378MachOObjectFile::getSection64(DataRefImpl DRI, 379 InMemoryStruct<macho::Section64> &Res) const { 380 InMemoryStruct<macho::Segment64LoadCommand> SLC; 381 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 382 MachOObj->ReadSegment64LoadCommand(LCI, SLC); 383 MachOObj->ReadSection64(LCI, DRI.d.b, Res); 384} 385 386static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) { 387 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 388 if (LCI.Command.Type == macho::LCT_Segment64) 389 return true; 390 assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type."); 391 return false; 392} 393 394error_code MachOObjectFile::getSectionName(DataRefImpl DRI, 395 StringRef &Result) const { 396 // FIXME: thread safety. 397 static char result[34]; 398 if (is64BitLoadCommand(MachOObj, DRI)) { 399 InMemoryStruct<macho::Segment64LoadCommand> SLC; 400 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 401 MachOObj->ReadSegment64LoadCommand(LCI, SLC); 402 InMemoryStruct<macho::Section64> Sect; 403 MachOObj->ReadSection64(LCI, DRI.d.b, Sect); 404 405 strcpy(result, Sect->SegmentName); 406 strcat(result, ","); 407 strcat(result, Sect->Name); 408 } else { 409 InMemoryStruct<macho::SegmentLoadCommand> SLC; 410 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 411 MachOObj->ReadSegmentLoadCommand(LCI, SLC); 412 InMemoryStruct<macho::Section> Sect; 413 MachOObj->ReadSection(LCI, DRI.d.b, Sect); 414 415 strcpy(result, Sect->SegmentName); 416 strcat(result, ","); 417 strcat(result, Sect->Name); 418 } 419 Result = StringRef(result); 420 return object_error::success; 421} 422 423error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, 424 uint64_t &Result) const { 425 if (is64BitLoadCommand(MachOObj, DRI)) { 426 InMemoryStruct<macho::Section64> Sect; 427 getSection64(DRI, Sect); 428 Result = Sect->Address; 429 } else { 430 InMemoryStruct<macho::Section> Sect; 431 getSection(DRI, Sect); 432 Result = Sect->Address; 433 } 434 return object_error::success; 435} 436 437error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, 438 uint64_t &Result) const { 439 if (is64BitLoadCommand(MachOObj, DRI)) { 440 InMemoryStruct<macho::Section64> Sect; 441 getSection64(DRI, Sect); 442 Result = Sect->Size; 443 } else { 444 InMemoryStruct<macho::Section> Sect; 445 getSection(DRI, Sect); 446 Result = Sect->Size; 447 } 448 return object_error::success; 449} 450 451error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, 452 StringRef &Result) const { 453 if (is64BitLoadCommand(MachOObj, DRI)) { 454 InMemoryStruct<macho::Section64> Sect; 455 getSection64(DRI, Sect); 456 Result = MachOObj->getData(Sect->Offset, Sect->Size); 457 } else { 458 InMemoryStruct<macho::Section> Sect; 459 getSection(DRI, Sect); 460 Result = MachOObj->getData(Sect->Offset, Sect->Size); 461 } 462 return object_error::success; 463} 464 465error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, 466 uint64_t &Result) const { 467 if (is64BitLoadCommand(MachOObj, DRI)) { 468 InMemoryStruct<macho::Section64> Sect; 469 getSection64(DRI, Sect); 470 Result = uint64_t(1) << Sect->Align; 471 } else { 472 InMemoryStruct<macho::Section> Sect; 473 getSection(DRI, Sect); 474 Result = uint64_t(1) << Sect->Align; 475 } 476 return object_error::success; 477} 478 479error_code MachOObjectFile::isSectionText(DataRefImpl DRI, 480 bool &Result) const { 481 if (is64BitLoadCommand(MachOObj, DRI)) { 482 InMemoryStruct<macho::Section64> Sect; 483 getSection64(DRI, Sect); 484 Result = !strcmp(Sect->Name, "__text"); 485 } else { 486 InMemoryStruct<macho::Section> Sect; 487 getSection(DRI, Sect); 488 Result = !strcmp(Sect->Name, "__text"); 489 } 490 return object_error::success; 491} 492 493error_code MachOObjectFile::isSectionData(DataRefImpl DRI, 494 bool &Result) const { 495 // FIXME: Unimplemented. 496 Result = false; 497 return object_error::success; 498} 499 500error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, 501 bool &Result) const { 502 // FIXME: Unimplemented. 503 Result = false; 504 return object_error::success; 505} 506 507error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, 508 DataRefImpl Symb, 509 bool &Result) const { 510 SymbolRef::Type ST; 511 getSymbolType(Symb, ST); 512 if (ST == SymbolRef::ST_External) { 513 Result = false; 514 return object_error::success; 515 } 516 517 uint64_t SectBegin, SectEnd; 518 getSectionAddress(Sec, SectBegin); 519 getSectionSize(Sec, SectEnd); 520 SectEnd += SectBegin; 521 522 if (MachOObj->is64Bit()) { 523 InMemoryStruct<macho::Symbol64TableEntry> Entry; 524 getSymbol64TableEntry(Symb, Entry); 525 uint64_t SymAddr= Entry->Value; 526 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 527 } else { 528 InMemoryStruct<macho::SymbolTableEntry> Entry; 529 getSymbolTableEntry(Symb, Entry); 530 uint64_t SymAddr= Entry->Value; 531 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 532 } 533 534 return object_error::success; 535} 536 537relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { 538 DataRefImpl ret; 539 ret.d.a = 0; 540 ret.d.b = getSectionIndex(Sec); 541 return relocation_iterator(RelocationRef(ret, this)); 542} 543relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { 544 uint32_t last_reloc; 545 if (is64BitLoadCommand(MachOObj, Sec)) { 546 InMemoryStruct<macho::Section64> Sect; 547 getSection64(Sec, Sect); 548 last_reloc = Sect->NumRelocationTableEntries; 549 } else { 550 InMemoryStruct<macho::Section> Sect; 551 getSection(Sec, Sect); 552 last_reloc = Sect->NumRelocationTableEntries; 553 } 554 DataRefImpl ret; 555 ret.d.a = last_reloc; 556 ret.d.b = getSectionIndex(Sec); 557 return relocation_iterator(RelocationRef(ret, this)); 558} 559 560section_iterator MachOObjectFile::begin_sections() const { 561 DataRefImpl DRI; 562 DRI.d.a = DRI.d.b = 0; 563 moveToNextSection(DRI); 564 return section_iterator(SectionRef(DRI, this)); 565} 566 567section_iterator MachOObjectFile::end_sections() const { 568 DataRefImpl DRI; 569 DRI.d.a = MachOObj->getHeader().NumLoadCommands; 570 DRI.d.b = 0; 571 return section_iterator(SectionRef(DRI, this)); 572} 573 574/*===-- Relocations -------------------------------------------------------===*/ 575 576void MachOObjectFile:: 577getRelocation(DataRefImpl Rel, 578 InMemoryStruct<macho::RelocationEntry> &Res) const { 579 uint32_t relOffset; 580 if (MachOObj->is64Bit()) { 581 InMemoryStruct<macho::Section64> Sect; 582 getSection64(Sections[Rel.d.b], Sect); 583 relOffset = Sect->RelocationTableOffset; 584 } else { 585 InMemoryStruct<macho::Section> Sect; 586 getSection(Sections[Rel.d.b], Sect); 587 relOffset = Sect->RelocationTableOffset; 588 } 589 MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res); 590} 591error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, 592 RelocationRef &Res) const { 593 ++Rel.d.a; 594 Res = RelocationRef(Rel, this); 595 return object_error::success; 596} 597error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, 598 uint64_t &Res) const { 599 const uint8_t* sectAddress = base(); 600 if (MachOObj->is64Bit()) { 601 InMemoryStruct<macho::Section64> Sect; 602 getSection64(Sections[Rel.d.b], Sect); 603 sectAddress += Sect->Offset; 604 } else { 605 InMemoryStruct<macho::Section> Sect; 606 getSection(Sections[Rel.d.b], Sect); 607 sectAddress += Sect->Offset; 608 } 609 InMemoryStruct<macho::RelocationEntry> RE; 610 getRelocation(Rel, RE); 611 Res = reinterpret_cast<uintptr_t>(sectAddress + RE->Word0); 612 return object_error::success; 613} 614error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, 615 SymbolRef &Res) const { 616 InMemoryStruct<macho::RelocationEntry> RE; 617 getRelocation(Rel, RE); 618 uint32_t SymbolIdx = RE->Word1 & 0xffffff; 619 bool isExtern = (RE->Word1 >> 27) & 1; 620 621 DataRefImpl Sym; 622 Sym.d.a = Sym.d.b = 0; 623 moveToNextSymbol(Sym); 624 if (isExtern) { 625 for (unsigned i = 0; i < SymbolIdx; i++) { 626 Sym.d.b++; 627 moveToNextSymbol(Sym); 628 assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands && 629 "Relocation symbol index out of range!"); 630 } 631 } 632 Res = SymbolRef(Sym, this); 633 return object_error::success; 634} 635error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, 636 uint32_t &Res) const { 637 InMemoryStruct<macho::RelocationEntry> RE; 638 getRelocation(Rel, RE); 639 Res = RE->Word1; 640 return object_error::success; 641} 642error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, 643 SmallVectorImpl<char> &Result) const { 644 StringRef res = "Unknown"; 645 Result.append(res.begin(), res.end()); 646 return object_error::success; 647} 648error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, 649 int64_t &Res) const { 650 InMemoryStruct<macho::RelocationEntry> RE; 651 getRelocation(Rel, RE); 652 bool isExtern = (RE->Word1 >> 27) & 1; 653 Res = 0; 654 if (!isExtern) { 655 const uint8_t* sectAddress = base(); 656 if (MachOObj->is64Bit()) { 657 InMemoryStruct<macho::Section64> Sect; 658 getSection64(Sections[Rel.d.b], Sect); 659 sectAddress += Sect->Offset; 660 } else { 661 InMemoryStruct<macho::Section> Sect; 662 getSection(Sections[Rel.d.b], Sect); 663 sectAddress += Sect->Offset; 664 } 665 Res = reinterpret_cast<uintptr_t>(sectAddress); 666 } 667 return object_error::success; 668} 669error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, 670 SmallVectorImpl<char> &Result) const { 671 StringRef res = "Unknown"; 672 Result.append(res.begin(), res.end()); 673 return object_error::success; 674} 675 676/*===-- Miscellaneous -----------------------------------------------------===*/ 677 678uint8_t MachOObjectFile::getBytesInAddress() const { 679 return MachOObj->is64Bit() ? 8 : 4; 680} 681 682StringRef MachOObjectFile::getFileFormatName() const { 683 if (!MachOObj->is64Bit()) { 684 switch (MachOObj->getHeader().CPUType) { 685 case llvm::MachO::CPUTypeI386: 686 return "Mach-O 32-bit i386"; 687 case llvm::MachO::CPUTypeARM: 688 return "Mach-O arm"; 689 case llvm::MachO::CPUTypePowerPC: 690 return "Mach-O 32-bit ppc"; 691 default: 692 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 && 693 "64-bit object file when we're not 64-bit?"); 694 return "Mach-O 32-bit unknown"; 695 } 696 } 697 698 switch (MachOObj->getHeader().CPUType) { 699 case llvm::MachO::CPUTypeX86_64: 700 return "Mach-O 64-bit x86-64"; 701 case llvm::MachO::CPUTypePowerPC64: 702 return "Mach-O 64-bit ppc64"; 703 default: 704 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 && 705 "32-bit object file when we're 64-bit?"); 706 return "Mach-O 64-bit unknown"; 707 } 708} 709 710unsigned MachOObjectFile::getArch() const { 711 switch (MachOObj->getHeader().CPUType) { 712 case llvm::MachO::CPUTypeI386: 713 return Triple::x86; 714 case llvm::MachO::CPUTypeX86_64: 715 return Triple::x86_64; 716 case llvm::MachO::CPUTypeARM: 717 return Triple::arm; 718 case llvm::MachO::CPUTypePowerPC: 719 return Triple::ppc; 720 case llvm::MachO::CPUTypePowerPC64: 721 return Triple::ppc64; 722 default: 723 return Triple::UnknownArch; 724 } 725} 726 727} // end namespace object 728} // end namespace llvm 729