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