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