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