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