MachOObjectFile.cpp revision 790552c20fbd8daa77d343419f0f6ec4e7fa1457
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/Format.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 { 29namespace object { 30 31MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, 32 error_code &ec) 33 : ObjectFile(Binary::isMachO, Object, ec), 34 MachOObj(MOO), 35 RegisteredStringTable(std::numeric_limits<uint32_t>::max()) { 36 DataRefImpl DRI; 37 DRI.d.a = DRI.d.b = 0; 38 moveToNextSection(DRI); 39 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 40 while (DRI.d.a < LoadCommandCount) { 41 Sections.push_back(DRI); 42 DRI.d.b++; 43 moveToNextSection(DRI); 44 } 45} 46 47 48ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { 49 error_code ec; 50 std::string Err; 51 MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err); 52 if (!MachOObj) 53 return NULL; 54 return new MachOObjectFile(Buffer, MachOObj, ec); 55} 56 57/*===-- Symbols -----------------------------------------------------------===*/ 58 59void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { 60 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 61 while (DRI.d.a < LoadCommandCount) { 62 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 63 if (LCI.Command.Type == macho::LCT_Symtab) { 64 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd; 65 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); 66 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries) 67 return; 68 } 69 70 DRI.d.a++; 71 DRI.d.b = 0; 72 } 73} 74 75void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, 76 InMemoryStruct<macho::SymbolTableEntry> &Res) const { 77 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd; 78 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 79 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); 80 81 if (RegisteredStringTable != DRI.d.a) { 82 MachOObj->RegisterStringTable(*SymtabLoadCmd); 83 RegisteredStringTable = DRI.d.a; 84 } 85 86 MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b, 87 Res); 88} 89 90void MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI, 91 InMemoryStruct<macho::Symbol64TableEntry> &Res) const { 92 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd; 93 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 94 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); 95 96 if (RegisteredStringTable != DRI.d.a) { 97 MachOObj->RegisterStringTable(*SymtabLoadCmd); 98 RegisteredStringTable = DRI.d.a; 99 } 100 101 MachOObj->ReadSymbol64TableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b, 102 Res); 103} 104 105 106error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI, 107 SymbolRef &Result) const { 108 DRI.d.b++; 109 moveToNextSymbol(DRI); 110 Result = SymbolRef(DRI, this); 111 return object_error::success; 112} 113 114error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, 115 StringRef &Result) const { 116 if (MachOObj->is64Bit()) { 117 InMemoryStruct<macho::Symbol64TableEntry> Entry; 118 getSymbol64TableEntry(DRI, Entry); 119 Result = MachOObj->getStringAtIndex(Entry->StringIndex); 120 } else { 121 InMemoryStruct<macho::SymbolTableEntry> Entry; 122 getSymbolTableEntry(DRI, Entry); 123 Result = MachOObj->getStringAtIndex(Entry->StringIndex); 124 } 125 return object_error::success; 126} 127 128error_code MachOObjectFile::getSymbolOffset(DataRefImpl DRI, 129 uint64_t &Result) const { 130 uint64_t SectionOffset; 131 uint8_t SectionIndex; 132 if (MachOObj->is64Bit()) { 133 InMemoryStruct<macho::Symbol64TableEntry> Entry; 134 getSymbol64TableEntry(DRI, Entry); 135 Result = Entry->Value; 136 SectionIndex = Entry->SectionIndex; 137 } else { 138 InMemoryStruct<macho::SymbolTableEntry> Entry; 139 getSymbolTableEntry(DRI, Entry); 140 Result = Entry->Value; 141 SectionIndex = Entry->SectionIndex; 142 } 143 getSectionAddress(Sections[SectionIndex-1], SectionOffset); 144 Result -= SectionOffset; 145 146 return object_error::success; 147} 148 149error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI, 150 uint64_t &Result) const { 151 if (MachOObj->is64Bit()) { 152 InMemoryStruct<macho::Symbol64TableEntry> Entry; 153 getSymbol64TableEntry(DRI, Entry); 154 Result = Entry->Value; 155 } else { 156 InMemoryStruct<macho::SymbolTableEntry> Entry; 157 getSymbolTableEntry(DRI, Entry); 158 Result = Entry->Value; 159 } 160 return object_error::success; 161} 162 163error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, 164 uint64_t &Result) const { 165 Result = UnknownAddressOrSize; 166 return object_error::success; 167} 168 169error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, 170 char &Result) const { 171 uint8_t Type, Flags; 172 if (MachOObj->is64Bit()) { 173 InMemoryStruct<macho::Symbol64TableEntry> Entry; 174 getSymbol64TableEntry(DRI, Entry); 175 Type = Entry->Type; 176 Flags = Entry->Flags; 177 } else { 178 InMemoryStruct<macho::SymbolTableEntry> Entry; 179 getSymbolTableEntry(DRI, Entry); 180 Type = Entry->Type; 181 Flags = Entry->Flags; 182 } 183 184 char Char; 185 switch (Type & macho::STF_TypeMask) { 186 case macho::STT_Undefined: 187 Char = 'u'; 188 break; 189 case macho::STT_Absolute: 190 case macho::STT_Section: 191 Char = 's'; 192 break; 193 default: 194 Char = '?'; 195 break; 196 } 197 198 if (Flags & (macho::STF_External | macho::STF_PrivateExtern)) 199 Char = toupper(Char); 200 Result = Char; 201 return object_error::success; 202} 203 204error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI, 205 bool &Result) const { 206 if (MachOObj->is64Bit()) { 207 InMemoryStruct<macho::Symbol64TableEntry> Entry; 208 getSymbol64TableEntry(DRI, Entry); 209 Result = Entry->Flags & macho::STF_StabsEntryMask; 210 } else { 211 InMemoryStruct<macho::SymbolTableEntry> Entry; 212 getSymbolTableEntry(DRI, Entry); 213 Result = Entry->Flags & macho::STF_StabsEntryMask; 214 } 215 return object_error::success; 216} 217 218error_code MachOObjectFile::isSymbolGlobal(DataRefImpl Symb, bool &Res) const { 219 220 if (MachOObj->is64Bit()) { 221 InMemoryStruct<macho::Symbol64TableEntry> Entry; 222 getSymbol64TableEntry(Symb, Entry); 223 Res = Entry->Type & MachO::NlistMaskExternal; 224 } else { 225 InMemoryStruct<macho::SymbolTableEntry> Entry; 226 getSymbolTableEntry(Symb, Entry); 227 Res = Entry->Type & MachO::NlistMaskExternal; 228 } 229 return object_error::success; 230} 231 232error_code MachOObjectFile::isSymbolWeak(DataRefImpl Symb, bool &Res) const { 233 234 if (MachOObj->is64Bit()) { 235 InMemoryStruct<macho::Symbol64TableEntry> Entry; 236 getSymbol64TableEntry(Symb, Entry); 237 Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef); 238 } else { 239 InMemoryStruct<macho::SymbolTableEntry> Entry; 240 getSymbolTableEntry(Symb, Entry); 241 Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef); 242 } 243 return object_error::success; 244} 245 246error_code MachOObjectFile::isSymbolAbsolute(DataRefImpl Symb, bool &Res) const{ 247 uint8_t n_type; 248 if (MachOObj->is64Bit()) { 249 InMemoryStruct<macho::Symbol64TableEntry> Entry; 250 getSymbol64TableEntry(Symb, Entry); 251 n_type = Entry->Type; 252 } else { 253 InMemoryStruct<macho::SymbolTableEntry> Entry; 254 getSymbolTableEntry(Symb, Entry); 255 n_type = Entry->Type; 256 } 257 258 Res = (n_type & MachO::NlistMaskType) == MachO::NListTypeAbsolute; 259 return object_error::success; 260} 261 262error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, 263 section_iterator &Res) const { 264 uint8_t index; 265 if (MachOObj->is64Bit()) { 266 InMemoryStruct<macho::Symbol64TableEntry> Entry; 267 getSymbol64TableEntry(Symb, Entry); 268 index = Entry->SectionIndex; 269 } else { 270 InMemoryStruct<macho::SymbolTableEntry> Entry; 271 getSymbolTableEntry(Symb, Entry); 272 index = Entry->SectionIndex; 273 } 274 275 if (index == 0) 276 Res = end_sections(); 277 else 278 Res = section_iterator(SectionRef(Sections[index], this)); 279 280 return object_error::success; 281} 282 283error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, 284 SymbolRef::Type &Res) const { 285 uint8_t n_type; 286 if (MachOObj->is64Bit()) { 287 InMemoryStruct<macho::Symbol64TableEntry> Entry; 288 getSymbol64TableEntry(Symb, Entry); 289 n_type = Entry->Type; 290 } else { 291 InMemoryStruct<macho::SymbolTableEntry> Entry; 292 getSymbolTableEntry(Symb, Entry); 293 n_type = Entry->Type; 294 } 295 Res = SymbolRef::ST_Other; 296 297 // If this is a STAB debugging symbol, we can do nothing more. 298 if (n_type & MachO::NlistMaskStab) { 299 Res = SymbolRef::ST_Debug; 300 return object_error::success; 301 } 302 303 switch (n_type & MachO::NlistMaskType) { 304 case MachO::NListTypeUndefined : 305 Res = SymbolRef::ST_External; 306 break; 307 case MachO::NListTypeSection : 308 Res = SymbolRef::ST_Function; 309 break; 310 } 311 return object_error::success; 312} 313 314 315symbol_iterator MachOObjectFile::begin_symbols() const { 316 // DRI.d.a = segment number; DRI.d.b = symbol index. 317 DataRefImpl DRI; 318 DRI.d.a = DRI.d.b = 0; 319 moveToNextSymbol(DRI); 320 return symbol_iterator(SymbolRef(DRI, this)); 321} 322 323symbol_iterator MachOObjectFile::end_symbols() const { 324 DataRefImpl DRI; 325 DRI.d.a = MachOObj->getHeader().NumLoadCommands; 326 DRI.d.b = 0; 327 return symbol_iterator(SymbolRef(DRI, this)); 328} 329 330 331/*===-- Sections ----------------------------------------------------------===*/ 332 333void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { 334 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 335 while (DRI.d.a < LoadCommandCount) { 336 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 337 if (LCI.Command.Type == macho::LCT_Segment) { 338 InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd; 339 MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd); 340 if (DRI.d.b < SegmentLoadCmd->NumSections) 341 return; 342 } else if (LCI.Command.Type == macho::LCT_Segment64) { 343 InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd; 344 MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd); 345 if (DRI.d.b < Segment64LoadCmd->NumSections) 346 return; 347 } 348 349 DRI.d.a++; 350 DRI.d.b = 0; 351 } 352} 353 354error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, 355 SectionRef &Result) const { 356 DRI.d.b++; 357 moveToNextSection(DRI); 358 Result = SectionRef(DRI, this); 359 return object_error::success; 360} 361 362void 363MachOObjectFile::getSection(DataRefImpl DRI, 364 InMemoryStruct<macho::Section> &Res) const { 365 InMemoryStruct<macho::SegmentLoadCommand> SLC; 366 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 367 MachOObj->ReadSegmentLoadCommand(LCI, SLC); 368 MachOObj->ReadSection(LCI, DRI.d.b, Res); 369} 370 371std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { 372 SectionList::const_iterator loc = 373 std::find(Sections.begin(), Sections.end(), Sec); 374 assert(loc != Sections.end() && "Sec is not a valid section!"); 375 return std::distance(Sections.begin(), loc); 376} 377 378void 379MachOObjectFile::getSection64(DataRefImpl DRI, 380 InMemoryStruct<macho::Section64> &Res) const { 381 InMemoryStruct<macho::Segment64LoadCommand> SLC; 382 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 383 MachOObj->ReadSegment64LoadCommand(LCI, SLC); 384 MachOObj->ReadSection64(LCI, DRI.d.b, Res); 385} 386 387static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) { 388 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 389 if (LCI.Command.Type == macho::LCT_Segment64) 390 return true; 391 assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type."); 392 return false; 393} 394 395error_code MachOObjectFile::getSectionName(DataRefImpl DRI, 396 StringRef &Result) const { 397 // FIXME: thread safety. 398 static char result[34]; 399 if (is64BitLoadCommand(MachOObj, DRI)) { 400 InMemoryStruct<macho::Segment64LoadCommand> SLC; 401 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 402 MachOObj->ReadSegment64LoadCommand(LCI, SLC); 403 InMemoryStruct<macho::Section64> Sect; 404 MachOObj->ReadSection64(LCI, DRI.d.b, Sect); 405 406 strcpy(result, Sect->SegmentName); 407 strcat(result, ","); 408 strcat(result, Sect->Name); 409 } else { 410 InMemoryStruct<macho::SegmentLoadCommand> SLC; 411 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 412 MachOObj->ReadSegmentLoadCommand(LCI, SLC); 413 InMemoryStruct<macho::Section> Sect; 414 MachOObj->ReadSection(LCI, DRI.d.b, Sect); 415 416 strcpy(result, Sect->SegmentName); 417 strcat(result, ","); 418 strcat(result, Sect->Name); 419 } 420 Result = StringRef(result); 421 return object_error::success; 422} 423 424error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, 425 uint64_t &Result) const { 426 if (is64BitLoadCommand(MachOObj, DRI)) { 427 InMemoryStruct<macho::Section64> Sect; 428 getSection64(DRI, Sect); 429 Result = Sect->Address; 430 } else { 431 InMemoryStruct<macho::Section> Sect; 432 getSection(DRI, Sect); 433 Result = Sect->Address; 434 } 435 return object_error::success; 436} 437 438error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, 439 uint64_t &Result) const { 440 if (is64BitLoadCommand(MachOObj, DRI)) { 441 InMemoryStruct<macho::Section64> Sect; 442 getSection64(DRI, Sect); 443 Result = Sect->Size; 444 } else { 445 InMemoryStruct<macho::Section> Sect; 446 getSection(DRI, Sect); 447 Result = Sect->Size; 448 } 449 return object_error::success; 450} 451 452error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, 453 StringRef &Result) const { 454 if (is64BitLoadCommand(MachOObj, DRI)) { 455 InMemoryStruct<macho::Section64> Sect; 456 getSection64(DRI, Sect); 457 Result = MachOObj->getData(Sect->Offset, Sect->Size); 458 } else { 459 InMemoryStruct<macho::Section> Sect; 460 getSection(DRI, Sect); 461 Result = MachOObj->getData(Sect->Offset, Sect->Size); 462 } 463 return object_error::success; 464} 465 466error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, 467 uint64_t &Result) const { 468 if (is64BitLoadCommand(MachOObj, DRI)) { 469 InMemoryStruct<macho::Section64> Sect; 470 getSection64(DRI, Sect); 471 Result = uint64_t(1) << Sect->Align; 472 } else { 473 InMemoryStruct<macho::Section> Sect; 474 getSection(DRI, Sect); 475 Result = uint64_t(1) << Sect->Align; 476 } 477 return object_error::success; 478} 479 480error_code MachOObjectFile::isSectionText(DataRefImpl DRI, 481 bool &Result) const { 482 if (is64BitLoadCommand(MachOObj, DRI)) { 483 InMemoryStruct<macho::Section64> Sect; 484 getSection64(DRI, Sect); 485 Result = !strcmp(Sect->Name, "__text"); 486 } else { 487 InMemoryStruct<macho::Section> Sect; 488 getSection(DRI, Sect); 489 Result = !strcmp(Sect->Name, "__text"); 490 } 491 return object_error::success; 492} 493 494error_code MachOObjectFile::isSectionData(DataRefImpl DRI, 495 bool &Result) const { 496 // FIXME: Unimplemented. 497 Result = false; 498 return object_error::success; 499} 500 501error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, 502 bool &Result) const { 503 // FIXME: Unimplemented. 504 Result = false; 505 return object_error::success; 506} 507 508error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, 509 DataRefImpl Symb, 510 bool &Result) const { 511 SymbolRef::Type ST; 512 getSymbolType(Symb, ST); 513 if (ST == SymbolRef::ST_External) { 514 Result = false; 515 return object_error::success; 516 } 517 518 uint64_t SectBegin, SectEnd; 519 getSectionAddress(Sec, SectBegin); 520 getSectionSize(Sec, SectEnd); 521 SectEnd += SectBegin; 522 523 if (MachOObj->is64Bit()) { 524 InMemoryStruct<macho::Symbol64TableEntry> Entry; 525 getSymbol64TableEntry(Symb, Entry); 526 uint64_t SymAddr= Entry->Value; 527 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 528 } else { 529 InMemoryStruct<macho::SymbolTableEntry> Entry; 530 getSymbolTableEntry(Symb, Entry); 531 uint64_t SymAddr= Entry->Value; 532 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 533 } 534 535 return object_error::success; 536} 537 538relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { 539 DataRefImpl ret; 540 ret.d.a = 0; 541 ret.d.b = getSectionIndex(Sec); 542 return relocation_iterator(RelocationRef(ret, this)); 543} 544relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { 545 uint32_t last_reloc; 546 if (is64BitLoadCommand(MachOObj, Sec)) { 547 InMemoryStruct<macho::Section64> Sect; 548 getSection64(Sec, Sect); 549 last_reloc = Sect->NumRelocationTableEntries; 550 } else { 551 InMemoryStruct<macho::Section> Sect; 552 getSection(Sec, Sect); 553 last_reloc = Sect->NumRelocationTableEntries; 554 } 555 DataRefImpl ret; 556 ret.d.a = last_reloc; 557 ret.d.b = getSectionIndex(Sec); 558 return relocation_iterator(RelocationRef(ret, this)); 559} 560 561section_iterator MachOObjectFile::begin_sections() const { 562 DataRefImpl DRI; 563 DRI.d.a = DRI.d.b = 0; 564 moveToNextSection(DRI); 565 return section_iterator(SectionRef(DRI, this)); 566} 567 568section_iterator MachOObjectFile::end_sections() const { 569 DataRefImpl DRI; 570 DRI.d.a = MachOObj->getHeader().NumLoadCommands; 571 DRI.d.b = 0; 572 return section_iterator(SectionRef(DRI, this)); 573} 574 575/*===-- Relocations -------------------------------------------------------===*/ 576 577void MachOObjectFile:: 578getRelocation(DataRefImpl Rel, 579 InMemoryStruct<macho::RelocationEntry> &Res) const { 580 uint32_t relOffset; 581 if (MachOObj->is64Bit()) { 582 InMemoryStruct<macho::Section64> Sect; 583 getSection64(Sections[Rel.d.b], Sect); 584 relOffset = Sect->RelocationTableOffset; 585 } else { 586 InMemoryStruct<macho::Section> Sect; 587 getSection(Sections[Rel.d.b], Sect); 588 relOffset = Sect->RelocationTableOffset; 589 } 590 MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res); 591} 592error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, 593 RelocationRef &Res) const { 594 ++Rel.d.a; 595 Res = RelocationRef(Rel, this); 596 return object_error::success; 597} 598error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, 599 uint64_t &Res) const { 600 const uint8_t* sectAddress = 0; 601 if (MachOObj->is64Bit()) { 602 InMemoryStruct<macho::Section64> Sect; 603 getSection64(Sections[Rel.d.b], Sect); 604 sectAddress += Sect->Address; 605 } else { 606 InMemoryStruct<macho::Section> Sect; 607 getSection(Sections[Rel.d.b], Sect); 608 sectAddress += Sect->Address; 609 } 610 InMemoryStruct<macho::RelocationEntry> RE; 611 getRelocation(Rel, RE); 612 613 unsigned Arch = getArch(); 614 bool isScattered = (Arch != Triple::x86_64) && 615 (RE->Word0 & macho::RF_Scattered); 616 uint64_t RelAddr = 0; 617 if (isScattered) 618 RelAddr = RE->Word0 & 0xFFFFFF; 619 else 620 RelAddr = RE->Word0; 621 622 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr); 623 return object_error::success; 624} 625error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, 626 SymbolRef &Res) const { 627 InMemoryStruct<macho::RelocationEntry> RE; 628 getRelocation(Rel, RE); 629 uint32_t SymbolIdx = RE->Word1 & 0xffffff; 630 bool isExtern = (RE->Word1 >> 27) & 1; 631 632 DataRefImpl Sym; 633 Sym.d.a = Sym.d.b = 0; 634 moveToNextSymbol(Sym); 635 if (isExtern) { 636 for (unsigned i = 0; i < SymbolIdx; i++) { 637 Sym.d.b++; 638 moveToNextSymbol(Sym); 639 assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands && 640 "Relocation symbol index out of range!"); 641 } 642 } 643 Res = SymbolRef(Sym, this); 644 return object_error::success; 645} 646error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, 647 uint64_t &Res) const { 648 InMemoryStruct<macho::RelocationEntry> RE; 649 getRelocation(Rel, RE); 650 Res = RE->Word0; 651 Res <<= 32; 652 Res |= RE->Word1; 653 return object_error::success; 654} 655error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, 656 SmallVectorImpl<char> &Result) const { 657 // TODO: Support scattered relocations. 658 StringRef res; 659 InMemoryStruct<macho::RelocationEntry> RE; 660 getRelocation(Rel, RE); 661 662 unsigned Arch = getArch(); 663 bool isScattered = (Arch != Triple::x86_64) && 664 (RE->Word0 & macho::RF_Scattered); 665 666 unsigned r_type; 667 if (isScattered) 668 r_type = (RE->Word0 >> 24) & 0xF; 669 else 670 r_type = (RE->Word1 >> 28) & 0xF; 671 672 switch (Arch) { 673 case Triple::x86: { 674 const char* Table[] = { 675 "GENERIC_RELOC_VANILLA", 676 "GENERIC_RELOC_PAIR", 677 "GENERIC_RELOC_SECTDIFF", 678 "GENERIC_RELOC_PB_LA_PTR", 679 "GENERIC_RELOC_LOCAL_SECTDIFF", 680 "GENERIC_RELOC_TLV" }; 681 682 if (r_type > 6) 683 res = "Unknown"; 684 else 685 res = Table[r_type]; 686 break; 687 } 688 case Triple::x86_64: { 689 const char* Table[] = { 690 "X86_64_RELOC_UNSIGNED", 691 "X86_64_RELOC_SIGNED", 692 "X86_64_RELOC_BRANCH", 693 "X86_64_RELOC_GOT_LOAD", 694 "X86_64_RELOC_GOT", 695 "X86_64_RELOC_SUBTRACTOR", 696 "X86_64_RELOC_SIGNED_1", 697 "X86_64_RELOC_SIGNED_2", 698 "X86_64_RELOC_SIGNED_4", 699 "X86_64_RELOC_TLV" }; 700 701 if (r_type > 9) 702 res = "Unknown"; 703 else 704 res = Table[r_type]; 705 break; 706 } 707 case Triple::arm: { 708 const char* Table[] = { 709 "ARM_RELOC_VANILLA", 710 "ARM_RELOC_PAIR", 711 "ARM_RELOC_SECTDIFF", 712 "ARM_RELOC_LOCAL_SECTDIFF", 713 "ARM_RELOC_PB_LA_PTR", 714 "ARM_RELOC_BR24", 715 "ARM_THUMB_RELOC_BR22", 716 "ARM_THUMB_32BIT_BRANCH", 717 "ARM_RELOC_HALF", 718 "ARM_RELOC_HALF_SECTDIFF" }; 719 720 if (r_type > 9) 721 res = "Unknown"; 722 else 723 res = Table[r_type]; 724 break; 725 } 726 case Triple::ppc: { 727 const char* Table[] = { 728 "PPC_RELOC_VANILLA", 729 "PPC_RELOC_PAIR", 730 "PPC_RELOC_BR14", 731 "PPC_RELOC_BR24", 732 "PPC_RELOC_HI16", 733 "PPC_RELOC_LO16", 734 "PPC_RELOC_HA16", 735 "PPC_RELOC_LO14", 736 "PPC_RELOC_SECTDIFF", 737 "PPC_RELOC_PB_LA_PTR", 738 "PPC_RELOC_HI16_SECTDIFF", 739 "PPC_RELOC_LO16_SECTDIFF", 740 "PPC_RELOC_HA16_SECTDIFF", 741 "PPC_RELOC_JBSR", 742 "PPC_RELOC_LO14_SECTDIFF", 743 "PPC_RELOC_LOCAL_SECTDIFF" }; 744 745 res = Table[r_type]; 746 break; 747 } 748 case Triple::UnknownArch: 749 res = "Unknown"; 750 break; 751 } 752 Result.append(res.begin(), res.end()); 753 return object_error::success; 754} 755error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, 756 int64_t &Res) const { 757 InMemoryStruct<macho::RelocationEntry> RE; 758 getRelocation(Rel, RE); 759 bool isExtern = (RE->Word1 >> 27) & 1; 760 Res = 0; 761 if (!isExtern) { 762 const uint8_t* sectAddress = base(); 763 if (MachOObj->is64Bit()) { 764 InMemoryStruct<macho::Section64> Sect; 765 getSection64(Sections[Rel.d.b], Sect); 766 sectAddress += Sect->Offset; 767 } else { 768 InMemoryStruct<macho::Section> Sect; 769 getSection(Sections[Rel.d.b], Sect); 770 sectAddress += Sect->Offset; 771 } 772 Res = reinterpret_cast<uintptr_t>(sectAddress); 773 } 774 return object_error::success; 775} 776 777// Helper to advance a section or symbol iterator multiple increments at a time. 778template<class T> 779error_code advance(T &it, size_t Val) { 780 error_code ec; 781 while (Val--) { 782 it.increment(ec); 783 } 784 return ec; 785} 786 787template<class T> 788void advanceTo(T &it, size_t Val) { 789 if (error_code ec = advance(it, Val)) 790 report_fatal_error(ec.message()); 791} 792 793void MachOObjectFile::printRelocationTargetName( 794 InMemoryStruct<macho::RelocationEntry>& RE, 795 raw_string_ostream &fmt) const { 796 unsigned Arch = getArch(); 797 bool isScattered = (Arch != Triple::x86_64) && 798 (RE->Word0 & macho::RF_Scattered); 799 800 // Target of a scattered relocation is an address. In the interest of 801 // generating pretty output, scan through the symbol table looking for a 802 // symbol that aligns with that address. If we find one, print it. 803 // Otherwise, we just print the hex address of the target. 804 if (isScattered) { 805 uint32_t Val = RE->Word1; 806 807 error_code ec; 808 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE; 809 SI.increment(ec)) { 810 if (ec) report_fatal_error(ec.message()); 811 812 uint64_t Addr; 813 StringRef Name; 814 815 if ((ec = SI->getAddress(Addr))) 816 report_fatal_error(ec.message()); 817 if (Addr != Val) continue; 818 if ((ec = SI->getName(Name))) 819 report_fatal_error(ec.message()); 820 fmt << Name; 821 return; 822 } 823 824 // If we couldn't find a symbol that this relocation refers to, try 825 // to find a section beginning instead. 826 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE; 827 SI.increment(ec)) { 828 if (ec) report_fatal_error(ec.message()); 829 830 uint64_t Addr; 831 StringRef Name; 832 833 if ((ec = SI->getAddress(Addr))) 834 report_fatal_error(ec.message()); 835 if (Addr != Val) continue; 836 if ((ec = SI->getName(Name))) 837 report_fatal_error(ec.message()); 838 fmt << Name; 839 return; 840 } 841 842 fmt << format("0x%x", Val); 843 return; 844 } 845 846 StringRef S; 847 bool isExtern = (RE->Word1 >> 27) & 1; 848 uint32_t Val = RE->Word1 & 0xFFFFFF; 849 850 if (isExtern) { 851 symbol_iterator SI = begin_symbols(); 852 advanceTo(SI, Val); 853 SI->getName(S); 854 } else { 855 section_iterator SI = begin_sections(); 856 advanceTo(SI, Val); 857 SI->getName(S); 858 } 859 860 fmt << S; 861} 862 863error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, 864 SmallVectorImpl<char> &Result) const { 865 InMemoryStruct<macho::RelocationEntry> RE; 866 getRelocation(Rel, RE); 867 868 unsigned Arch = getArch(); 869 bool isScattered = (Arch != Triple::x86_64) && 870 (RE->Word0 & macho::RF_Scattered); 871 872 std::string fmtbuf; 873 raw_string_ostream fmt(fmtbuf); 874 875 unsigned Type; 876 if (isScattered) 877 Type = (RE->Word0 >> 24) & 0xF; 878 else 879 Type = (RE->Word1 >> 28) & 0xF; 880 881 bool isPCRel; 882 if (isScattered) 883 isPCRel = ((RE->Word0 >> 30) & 1); 884 else 885 isPCRel = ((RE->Word1 >> 24) & 1); 886 887 // Determine any addends that should be displayed with the relocation. 888 // These require decoding the relocation type, which is triple-specific. 889 890 // X86_64 has entirely custom relocation types. 891 if (Arch == Triple::x86_64) { 892 bool isPCRel = ((RE->Word1 >> 24) & 1); 893 894 switch (Type) { 895 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD 896 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT 897 printRelocationTargetName(RE, fmt); 898 fmt << "@GOT"; 899 if (isPCRel) fmt << "PCREL"; 900 break; 901 } 902 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR 903 InMemoryStruct<macho::RelocationEntry> RENext; 904 DataRefImpl RelNext = Rel; 905 RelNext.d.a++; 906 getRelocation(RelNext, RENext); 907 908 // X86_64_SUBTRACTOR must be followed by a relocation of type 909 // X86_64_RELOC_UNSIGNED. 910 // NOTE: Scattered relocations don't exist on x86_64. 911 unsigned RType = (RENext->Word1 >> 28) & 0xF; 912 if (RType != 0) 913 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " 914 "X86_64_RELOC_SUBTRACTOR."); 915 916 // The X86_64_RELOC_UNSIGNED contains the minuend symbol, 917 // X86_64_SUBTRACTOR contains to the subtrahend. 918 printRelocationTargetName(RENext, fmt); 919 fmt << "-"; 920 printRelocationTargetName(RE, fmt); 921 } 922 case macho::RIT_X86_64_TLV: 923 printRelocationTargetName(RE, fmt); 924 fmt << "@TLV"; 925 if (isPCRel) fmt << "P"; 926 break; 927 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1 928 printRelocationTargetName(RE, fmt); 929 fmt << "-1"; 930 break; 931 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2 932 printRelocationTargetName(RE, fmt); 933 fmt << "-2"; 934 break; 935 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4 936 printRelocationTargetName(RE, fmt); 937 fmt << "-4"; 938 break; 939 default: 940 printRelocationTargetName(RE, fmt); 941 break; 942 } 943 // X86 and ARM share some relocation types in common. 944 } else if (Arch == Triple::x86 || Arch == Triple::arm) { 945 // Generic relocation types... 946 switch (Type) { 947 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info 948 return object_error::success; 949 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF 950 InMemoryStruct<macho::RelocationEntry> RENext; 951 DataRefImpl RelNext = Rel; 952 RelNext.d.a++; 953 getRelocation(RelNext, RENext); 954 955 // X86 sect diff's must be followed by a relocation of type 956 // GENERIC_RELOC_PAIR. 957 bool isNextScattered = (Arch != Triple::x86_64) && 958 (RENext->Word0 & macho::RF_Scattered); 959 unsigned RType; 960 if (isNextScattered) 961 RType = (RENext->Word0 >> 24) & 0xF; 962 else 963 RType = (RENext->Word1 >> 28) & 0xF; 964 if (RType != 1) 965 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 966 "GENERIC_RELOC_SECTDIFF."); 967 968 printRelocationTargetName(RE, fmt); 969 fmt << "-"; 970 printRelocationTargetName(RENext, fmt); 971 break; 972 } 973 } 974 975 if (Arch == Triple::x86) { 976 // All X86 relocations that need special printing were already 977 // handled in the generic code. 978 switch (Type) { 979 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF 980 InMemoryStruct<macho::RelocationEntry> RENext; 981 DataRefImpl RelNext = Rel; 982 RelNext.d.a++; 983 getRelocation(RelNext, RENext); 984 985 // X86 sect diff's must be followed by a relocation of type 986 // GENERIC_RELOC_PAIR. 987 bool isNextScattered = (Arch != Triple::x86_64) && 988 (RENext->Word0 & macho::RF_Scattered); 989 unsigned RType; 990 if (isNextScattered) 991 RType = (RENext->Word0 >> 24) & 0xF; 992 else 993 RType = (RENext->Word1 >> 28) & 0xF; 994 if (RType != 1) 995 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 996 "GENERIC_RELOC_LOCAL_SECTDIFF."); 997 998 printRelocationTargetName(RE, fmt); 999 fmt << "-"; 1000 printRelocationTargetName(RENext, fmt); 1001 break; 1002 } 1003 case macho::RIT_Generic_TLV: { 1004 printRelocationTargetName(RE, fmt); 1005 fmt << "@TLV"; 1006 if (isPCRel) fmt << "P"; 1007 break; 1008 } 1009 default: 1010 printRelocationTargetName(RE, fmt); 1011 } 1012 } else { // ARM-specific relocations 1013 switch (Type) { 1014 case macho::RIT_ARM_Half: // ARM_RELOC_HALF 1015 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF 1016 // Half relocations steal a bit from the length field to encode 1017 // whether this is an upper16 or a lower16 relocation. 1018 bool isUpper; 1019 if (isScattered) 1020 isUpper = (RE->Word0 >> 28) & 1; 1021 else 1022 isUpper = (RE->Word1 >> 25) & 1; 1023 1024 if (isUpper) 1025 fmt << ":upper16:("; 1026 else 1027 fmt << ":lower16:("; 1028 printRelocationTargetName(RE, fmt); 1029 1030 InMemoryStruct<macho::RelocationEntry> RENext; 1031 DataRefImpl RelNext = Rel; 1032 RelNext.d.a++; 1033 getRelocation(RelNext, RENext); 1034 1035 // ARM half relocs must be followed by a relocation of type 1036 // ARM_RELOC_PAIR. 1037 bool isNextScattered = (Arch != Triple::x86_64) && 1038 (RENext->Word0 & macho::RF_Scattered); 1039 unsigned RType; 1040 if (isNextScattered) 1041 RType = (RENext->Word0 >> 24) & 0xF; 1042 else 1043 RType = (RENext->Word1 >> 28) & 0xF; 1044 1045 if (RType != 1) 1046 report_fatal_error("Expected ARM_RELOC_PAIR after " 1047 "GENERIC_RELOC_HALF"); 1048 1049 // NOTE: The half of the target virtual address is stashed in the 1050 // address field of the secondary relocation, but we can't reverse 1051 // engineer the constant offset from it without decoding the movw/movt 1052 // instruction to find the other half in its immediate field. 1053 1054 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 1055 // symbol/section pointer of the follow-on relocation. 1056 if (Type == macho::RIT_ARM_HalfDifference) { 1057 fmt << "-"; 1058 printRelocationTargetName(RENext, fmt); 1059 } 1060 1061 fmt << ")"; 1062 break; 1063 } 1064 default: { 1065 printRelocationTargetName(RE, fmt); 1066 } 1067 } 1068 } 1069 } else 1070 printRelocationTargetName(RE, fmt); 1071 1072 fmt.flush(); 1073 Result.append(fmtbuf.begin(), fmtbuf.end()); 1074 return object_error::success; 1075} 1076 1077error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, 1078 bool &Result) const { 1079 InMemoryStruct<macho::RelocationEntry> RE; 1080 getRelocation(Rel, RE); 1081 1082 unsigned Arch = getArch(); 1083 bool isScattered = (Arch != Triple::x86_64) && 1084 (RE->Word0 & macho::RF_Scattered); 1085 unsigned Type; 1086 if (isScattered) 1087 Type = (RE->Word0 >> 24) & 0xF; 1088 else 1089 Type = (RE->Word1 >> 28) & 0xF; 1090 1091 Result = false; 1092 1093 // On arches that use the generic relocations, GENERIC_RELOC_PAIR 1094 // is always hidden. 1095 if (Arch == Triple::x86 || Arch == Triple::arm) { 1096 if (Type == macho::RIT_Pair) Result = true; 1097 } else if (Arch == Triple::x86_64) { 1098 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows 1099 // an X864_64_RELOC_SUBTRACTOR. 1100 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { 1101 DataRefImpl RelPrev = Rel; 1102 RelPrev.d.a--; 1103 InMemoryStruct<macho::RelocationEntry> REPrev; 1104 getRelocation(RelPrev, REPrev); 1105 1106 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF; 1107 1108 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true; 1109 } 1110 } 1111 1112 return object_error::success; 1113} 1114 1115/*===-- Miscellaneous -----------------------------------------------------===*/ 1116 1117uint8_t MachOObjectFile::getBytesInAddress() const { 1118 return MachOObj->is64Bit() ? 8 : 4; 1119} 1120 1121StringRef MachOObjectFile::getFileFormatName() const { 1122 if (!MachOObj->is64Bit()) { 1123 switch (MachOObj->getHeader().CPUType) { 1124 case llvm::MachO::CPUTypeI386: 1125 return "Mach-O 32-bit i386"; 1126 case llvm::MachO::CPUTypeARM: 1127 return "Mach-O arm"; 1128 case llvm::MachO::CPUTypePowerPC: 1129 return "Mach-O 32-bit ppc"; 1130 default: 1131 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 && 1132 "64-bit object file when we're not 64-bit?"); 1133 return "Mach-O 32-bit unknown"; 1134 } 1135 } 1136 1137 switch (MachOObj->getHeader().CPUType) { 1138 case llvm::MachO::CPUTypeX86_64: 1139 return "Mach-O 64-bit x86-64"; 1140 case llvm::MachO::CPUTypePowerPC64: 1141 return "Mach-O 64-bit ppc64"; 1142 default: 1143 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 && 1144 "32-bit object file when we're 64-bit?"); 1145 return "Mach-O 64-bit unknown"; 1146 } 1147} 1148 1149unsigned MachOObjectFile::getArch() const { 1150 switch (MachOObj->getHeader().CPUType) { 1151 case llvm::MachO::CPUTypeI386: 1152 return Triple::x86; 1153 case llvm::MachO::CPUTypeX86_64: 1154 return Triple::x86_64; 1155 case llvm::MachO::CPUTypeARM: 1156 return Triple::arm; 1157 case llvm::MachO::CPUTypePowerPC: 1158 return Triple::ppc; 1159 case llvm::MachO::CPUTypePowerPC64: 1160 return Triple::ppc64; 1161 default: 1162 return Triple::UnknownArch; 1163 } 1164} 1165 1166} // end namespace object 1167} // end namespace llvm 1168