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