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