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