From 06210ae42d418d50d8d9365d5c9419308ae9e7ee Mon Sep 17 00:00:00 2001 From: dim Date: Mon, 26 Dec 2016 20:36:37 +0000 Subject: MFC r309124: Upgrade our copies of clang, llvm, lldb, compiler-rt and libc++ to 3.9.0 release, and add lld 3.9.0. Also completely revamp the build system for clang, llvm, lldb and their related tools. Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11 support to build; see UPDATING for more information. Release notes for llvm, clang and lld are available here: Thanks to Ed Maste, Bryan Drewery, Andrew Turner, Antoine Brodin and Jan Beich for their help. Relnotes: yes MFC r309147: Pull in r282174 from upstream llvm trunk (by Krzysztof Parzyszek): [PPC] Set SP after loading data from stack frame, if no red zone is present Follow-up to r280705: Make sure that the SP is only restored after all data is loaded from the stack frame, if there is no red zone. This completes the fix for https://llvm.org/bugs/show_bug.cgi?id=26519. Differential Revision: https://reviews.llvm.org/D24466 Reported by: Mark Millard PR: 214433 MFC r309149: Pull in r283060 from upstream llvm trunk (by Hal Finkel): [PowerPC] Refactor soft-float support, and enable PPC64 soft float This change enables soft-float for PowerPC64, and also makes soft-float disable all vector instruction sets for both 32-bit and 64-bit modes. This latter part is necessary because the PPC backend canonicalizes many Altivec vector types to floating-point types, and so soft-float breaks scalarization support for many operations. Both for embedded targets and for operating-system kernels desiring soft-float support, it seems reasonable that disabling hardware floating-point also disables vector instructions (embedded targets without hardware floating point support are unlikely to have Altivec, etc. and operating system kernels desiring not to use floating-point registers to lower syscall cost are unlikely to want to use vector registers either). If someone needs this to work, we'll need to change the fact that we promote many Altivec operations to act on v4f32. To make it possible to disable Altivec when soft-float is enabled, hardware floating-point support needs to be expressed as a positive feature, like the others, and not a negative feature, because target features cannot have dependencies on the disabling of some other feature. So +soft-float has now become -hard-float. Fixes PR26970. Pull in r283061 from upstream clang trunk (by Hal Finkel): [PowerPC] Enable soft-float for PPC64, and +soft-float -> -hard-float Enable soft-float support on PPC64, as the backend now supports it. Also, the backend now uses -hard-float instead of +soft-float, so set the target features accordingly. Fixes PR26970. Reported by: Mark Millard PR: 214433 MFC r309212: Add a few missed clang 3.9.0 files to OptionalObsoleteFiles. MFC r309262: Fix packaging for clang, lldb and lld 3.9.0 During the upgrade of clang/llvm etc to 3.9.0 in r309124, the PACKAGE directive in the usr.bin/clang/*.mk files got dropped accidentally. Restore it, with a few minor changes and additions: * Correct license in clang.ucl to NCSA * Add PACKAGE=clang for clang and most of the "ll" tools * Put lldb in its own package * Put lld in its own package Reviewed by: gjb, jmallett Differential Revision: https://reviews.freebsd.org/D8666 MFC r309656: During the bootstrap phase, when building the minimal llvm library on PowerPC, add lib/Support/Atomic.cpp. This is needed because upstream llvm revision r271821 disabled the use of std::call_once, which causes some fallback functions from Atomic.cpp to be used instead. Reported by: Mark Millard PR: 214902 MFC r309835: Tentatively apply https://reviews.llvm.org/D18730 to work around gcc PR 70528 (bogus error: constructor required before non-static data member). This should fix buildworld with the external gcc package. Reported by: https://jenkins.freebsd.org/job/FreeBSD_HEAD_amd64_gcc/ MFC r310194: Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to 3.9.1 release. Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11 support to build; see UPDATING for more information. Release notes for llvm, clang and lld will be available here: Relnotes: yes --- contrib/llvm/lib/Object/MachOObjectFile.cpp | 404 +++++++++++++++++----------- 1 file changed, 249 insertions(+), 155 deletions(-) (limited to 'contrib/llvm/lib/Object/MachOObjectFile.cpp') diff --git a/contrib/llvm/lib/Object/MachOObjectFile.cpp b/contrib/llvm/lib/Object/MachOObjectFile.cpp index d1f79b2..563236f 100644 --- a/contrib/llvm/lib/Object/MachOObjectFile.cpp +++ b/contrib/llvm/lib/Object/MachOObjectFile.cpp @@ -38,6 +38,13 @@ namespace { }; } +static Error +malformedError(Twine Msg) { + std::string StringMsg = "truncated or malformed object (" + Msg.str() + ")"; + return make_error(std::move(StringMsg), + object_error::parse_failed); +} + // FIXME: Replace all uses of this function with getStructOrErr. template static T getStruct(const MachOObjectFile *O, const char *P) { @@ -53,10 +60,10 @@ static T getStruct(const MachOObjectFile *O, const char *P) { } template -static ErrorOr getStructOrErr(const MachOObjectFile *O, const char *P) { +static Expected getStructOrErr(const MachOObjectFile *O, const char *P) { // Don't read before the beginning or past the end of the file if (P < O->getData().begin() || P + sizeof(T) > O->getData().end()) - return object_error::parse_failed; + return malformedError("Structure read out-of-range"); T Cmd; memcpy(&Cmd, P, sizeof(T)); @@ -161,120 +168,180 @@ static uint32_t getSectionFlags(const MachOObjectFile *O, return Sect.flags; } -static ErrorOr -getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) { - auto CmdOrErr = getStructOrErr(Obj, Ptr); - if (!CmdOrErr) - return CmdOrErr.getError(); - if (CmdOrErr->cmdsize < 8) - return object_error::macho_small_load_command; - MachOObjectFile::LoadCommandInfo Load; - Load.Ptr = Ptr; - Load.C = CmdOrErr.get(); - return Load; +static Expected +getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr, + uint32_t LoadCommandIndex) { + if (auto CmdOrErr = getStructOrErr(Obj, Ptr)) { + if (CmdOrErr->cmdsize < 8) + return malformedError("load command " + Twine(LoadCommandIndex) + + " with size less than 8 bytes"); + return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr}); + } else + return CmdOrErr.takeError(); } -static ErrorOr +static Expected getFirstLoadCommandInfo(const MachOObjectFile *Obj) { unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header); - return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize)); + if (sizeof(MachOObjectFile::LoadCommandInfo) > Obj->getHeader().sizeofcmds) + return malformedError("load command 0 extends past the end all load " + "commands in the file"); + return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0); } -static ErrorOr -getNextLoadCommandInfo(const MachOObjectFile *Obj, +static Expected +getNextLoadCommandInfo(const MachOObjectFile *Obj, uint32_t LoadCommandIndex, const MachOObjectFile::LoadCommandInfo &L) { - return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize); + unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64) + : sizeof(MachO::mach_header); + if (L.Ptr + L.C.cmdsize + sizeof(MachOObjectFile::LoadCommandInfo) > + Obj->getData().data() + HeaderSize + Obj->getHeader().sizeofcmds) + return malformedError("load command " + Twine(LoadCommandIndex + 1) + + " extends past the end all load commands in the file"); + return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1); } template static void parseHeader(const MachOObjectFile *Obj, T &Header, - std::error_code &EC) { - auto HeaderOrErr = getStructOrErr(Obj, getPtr(Obj, 0)); - if (HeaderOrErr) - Header = HeaderOrErr.get(); + Error &Err) { + if (sizeof(T) > Obj->getData().size()) { + Err = malformedError("the mach header extends past the end of the " + "file"); + return; + } + if (auto HeaderOrErr = getStructOrErr(Obj, getPtr(Obj, 0))) + Header = *HeaderOrErr; else - EC = HeaderOrErr.getError(); + Err = HeaderOrErr.takeError(); } // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all // sections to \param Sections, and optionally sets // \param IsPageZeroSegment to true. template -static std::error_code parseSegmentLoadCommand( +static Error parseSegmentLoadCommand( const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load, - SmallVectorImpl &Sections, bool &IsPageZeroSegment) { + SmallVectorImpl &Sections, bool &IsPageZeroSegment, + uint32_t LoadCommandIndex, const char *CmdName) { const unsigned SegmentLoadSize = sizeof(SegmentCmd); if (Load.C.cmdsize < SegmentLoadSize) - return object_error::macho_load_segment_too_small; - auto SegOrErr = getStructOrErr(Obj, Load.Ptr); - if (!SegOrErr) - return SegOrErr.getError(); - SegmentCmd S = SegOrErr.get(); - const unsigned SectionSize = + return malformedError("load command " + Twine(LoadCommandIndex) + + " " + CmdName + " cmdsize too small"); + if (auto SegOrErr = getStructOrErr(Obj, Load.Ptr)) { + SegmentCmd S = SegOrErr.get(); + const unsigned SectionSize = Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section); - if (S.nsects > std::numeric_limits::max() / SectionSize || - S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize) - return object_error::macho_load_segment_too_many_sections; - for (unsigned J = 0; J < S.nsects; ++J) { - const char *Sec = getSectionPtr(Obj, Load, J); - Sections.push_back(Sec); - } - IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname); - return std::error_code(); + if (S.nsects > std::numeric_limits::max() / SectionSize || + S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize) + return malformedError("load command " + Twine(LoadCommandIndex) + + " inconsistent cmdsize in " + CmdName + + " for the number of sections"); + for (unsigned J = 0; J < S.nsects; ++J) { + const char *Sec = getSectionPtr(Obj, Load, J); + Sections.push_back(Sec); + } + IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname); + } else + return SegOrErr.takeError(); + + return Error::success(); +} + +Expected> +MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian, + bool Is64Bits) { + Error Err; + std::unique_ptr Obj( + new MachOObjectFile(std::move(Object), IsLittleEndian, + Is64Bits, Err)); + if (Err) + return std::move(Err); + return std::move(Obj); } MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, - bool Is64bits, std::error_code &EC) + bool Is64bits, Error &Err) : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr), DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr), HasPageZeroSegment(false) { - if (is64Bit()) - parseHeader(this, Header64, EC); - else - parseHeader(this, Header, EC); - if (EC) + ErrorAsOutParameter ErrAsOutParam(Err); + uint64_t BigSize; + if (is64Bit()) { + parseHeader(this, Header64, Err); + BigSize = sizeof(MachO::mach_header_64); + } else { + parseHeader(this, Header, Err); + BigSize = sizeof(MachO::mach_header); + } + if (Err) return; + BigSize += getHeader().sizeofcmds; + if (getData().data() + BigSize > getData().end()) { + Err = malformedError("load commands extend past the end of the file"); + return; + } uint32_t LoadCommandCount = getHeader().ncmds; if (LoadCommandCount == 0) return; - auto LoadOrErr = getFirstLoadCommandInfo(this); - if (!LoadOrErr) { - EC = LoadOrErr.getError(); + LoadCommandInfo Load; + if (auto LoadOrErr = getFirstLoadCommandInfo(this)) + Load = *LoadOrErr; + else { + Err = LoadOrErr.takeError(); return; } - LoadCommandInfo Load = LoadOrErr.get(); + for (unsigned I = 0; I < LoadCommandCount; ++I) { + if (is64Bit()) { + if (Load.C.cmdsize % 8 != 0) { + // We have a hack here to allow 64-bit Mach-O core files to have + // LC_THREAD commands that are only a multiple of 4 and not 8 to be + // allowed since the macOS kernel produces them. + if (getHeader().filetype != MachO::MH_CORE || + Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) { + Err = malformedError("load command " + Twine(I) + " cmdsize not a " + "multiple of 8"); + return; + } + } + } else { + if (Load.C.cmdsize % 4 != 0) { + Err = malformedError("load command " + Twine(I) + " cmdsize not a " + "multiple of 4"); + return; + } + } LoadCommands.push_back(Load); if (Load.C.cmd == MachO::LC_SYMTAB) { // Multiple symbol tables if (SymtabLoadCmd) { - EC = object_error::parse_failed; + Err = malformedError("Multiple symbol tables"); return; } SymtabLoadCmd = Load.Ptr; } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { // Multiple dynamic symbol tables if (DysymtabLoadCmd) { - EC = object_error::parse_failed; + Err = malformedError("Multiple dynamic symbol tables"); return; } DysymtabLoadCmd = Load.Ptr; } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { // Multiple data in code tables if (DataInCodeLoadCmd) { - EC = object_error::parse_failed; + Err = malformedError("Multiple data-in-code tables"); return; } DataInCodeLoadCmd = Load.Ptr; } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { // Multiple linker optimization hint tables if (LinkOptHintsLoadCmd) { - EC = object_error::parse_failed; + Err = malformedError("Multiple linker optimization hint tables"); return; } LinkOptHintsLoadCmd = Load.Ptr; @@ -282,24 +349,25 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) { // Multiple dyldinfo load commands if (DyldInfoLoadCmd) { - EC = object_error::parse_failed; + Err = malformedError("Multiple dyldinfo load commands"); return; } DyldInfoLoadCmd = Load.Ptr; } else if (Load.C.cmd == MachO::LC_UUID) { // Multiple UUID load commands if (UuidLoadCmd) { - EC = object_error::parse_failed; + Err = malformedError("Multiple UUID load commands"); return; } UuidLoadCmd = Load.Ptr; } else if (Load.C.cmd == MachO::LC_SEGMENT_64) { - if ((EC = parseSegmentLoadCommand( - this, Load, Sections, HasPageZeroSegment))) + if ((Err = parseSegmentLoadCommand( + this, Load, Sections, HasPageZeroSegment, I, + "LC_SEGMENT_64"))) return; } else if (Load.C.cmd == MachO::LC_SEGMENT) { - if ((EC = parseSegmentLoadCommand( - this, Load, Sections, HasPageZeroSegment))) + if ((Err = parseSegmentLoadCommand( + this, Load, Sections, HasPageZeroSegment, I, "LC_SEGMENT"))) return; } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB || Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || @@ -309,15 +377,66 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, Libraries.push_back(Load.Ptr); } if (I < LoadCommandCount - 1) { - auto LoadOrErr = getNextLoadCommandInfo(this, Load); - if (!LoadOrErr) { - EC = LoadOrErr.getError(); + if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load)) + Load = *LoadOrErr; + else { + Err = LoadOrErr.takeError(); return; } - Load = LoadOrErr.get(); + } + } + if (!SymtabLoadCmd) { + if (DysymtabLoadCmd) { + Err = malformedError("contains LC_DYSYMTAB load command without a " + "LC_SYMTAB load command"); + return; + } + } else if (DysymtabLoadCmd) { + MachO::symtab_command Symtab = + getStruct(this, SymtabLoadCmd); + MachO::dysymtab_command Dysymtab = + getStruct(this, DysymtabLoadCmd); + if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) { + Err = malformedError("ilocalsym in LC_DYSYMTAB load command " + "extends past the end of the symbol table"); + return; + } + uint64_t BigSize = Dysymtab.ilocalsym; + BigSize += Dysymtab.nlocalsym; + if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) { + Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load " + "command extends past the end of the symbol table"); + return; + } + if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) { + Err = malformedError("nextdefsym in LC_DYSYMTAB load command " + "extends past the end of the symbol table"); + return; + } + BigSize = Dysymtab.iextdefsym; + BigSize += Dysymtab.nextdefsym; + if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) { + Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB " + "load command extends past the end of the symbol " + "table"); + return; + } + if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) { + Err = malformedError("nundefsym in LC_DYSYMTAB load command " + "extends past the end of the symbol table"); + return; + } + BigSize = Dysymtab.iundefsym; + BigSize += Dysymtab.nundefsym; + if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) { + Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load " + " command extends past the end of the symbol table"); + return; } } assert(LoadCommands.size() == LoadCommandCount); + + Err = Error::success(); } void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { @@ -327,13 +446,14 @@ void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.p += SymbolTableEntrySize; } -ErrorOr MachOObjectFile::getSymbolName(DataRefImpl Symb) const { +Expected MachOObjectFile::getSymbolName(DataRefImpl Symb) const { StringRef StringTable = getStringTableData(); MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); const char *Start = &StringTable.data()[Entry.n_strx]; - if (Start < getData().begin() || Start >= getData().end()) - report_fatal_error( - "Symbol name entry points before beginning or past end of file."); + if (Start < getData().begin() || Start >= getData().end()) { + return malformedError("bad string index: " + Twine(Entry.n_strx) + + " for symbol at index " + Twine(getSymbolIndex(Symb))); + } return StringRef(Start); } @@ -372,7 +492,7 @@ uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const { return getNValue(Sym); } -ErrorOr MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const { +Expected MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const { return getSymbolValue(Sym); } @@ -389,7 +509,8 @@ uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const { return getNValue(DRI); } -SymbolRef::Type MachOObjectFile::getSymbolType(DataRefImpl Symb) const { +Expected +MachOObjectFile::getSymbolType(DataRefImpl Symb) const { MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); uint8_t n_type = Entry.n_type; @@ -401,7 +522,10 @@ SymbolRef::Type MachOObjectFile::getSymbolType(DataRefImpl Symb) const { case MachO::N_UNDF : return SymbolRef::ST_Unknown; case MachO::N_SECT : - section_iterator Sec = *getSymbolSection(Symb); + Expected SecOrError = getSymbolSection(Symb); + if (!SecOrError) + return SecOrError.takeError(); + section_iterator Sec = *SecOrError; if (Sec->isData() || Sec->isBSS()) return SymbolRef::ST_Data; return SymbolRef::ST_Function; @@ -448,7 +572,7 @@ uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { return Result; } -ErrorOr +Expected MachOObjectFile::getSymbolSection(DataRefImpl Symb) const { MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); uint8_t index = Entry.n_sect; @@ -457,8 +581,10 @@ MachOObjectFile::getSymbolSection(DataRefImpl Symb) const { return section_end(); DataRefImpl DRI; DRI.d.a = index - 1; - if (DRI.d.a >= Sections.size()) - report_fatal_error("getSymbolSection: Invalid section index."); + if (DRI.d.a >= Sections.size()){ + return malformedError("bad section index: " + Twine((int)index) + + " for symbol at index " + Twine(getSymbolIndex(Symb))); + } return section_iterator(SectionRef(DRI, this)); } @@ -546,6 +672,10 @@ uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const { return uint64_t(1) << Align; } +bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const { + return false; +} + bool MachOObjectFile::isSectionText(DataRefImpl Sec) const { uint32_t Flags = getSectionFlags(this, Sec); return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; @@ -576,6 +706,14 @@ bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } +bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const { + StringRef SegmentName = getSectionFinalSegmentName(Sec); + StringRef SectName; + if (!getSectionName(Sec, SectName)) + return (SegmentName == "__LLVM" && SectName == "__bitcode"); + return false; +} + relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { DataRefImpl Ret; Ret.d.a = Sec.d.a; @@ -942,15 +1080,20 @@ MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const { } basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { + DataRefImpl DRI; + MachO::symtab_command Symtab = getSymtabLoadCommand(); + if (!SymtabLoadCmd || Symtab.nsyms == 0) + return basic_symbol_iterator(SymbolRef(DRI, this)); + return getSymbolByIndex(0); } basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { DataRefImpl DRI; - if (!SymtabLoadCmd) + MachO::symtab_command Symtab = getSymtabLoadCommand(); + if (!SymtabLoadCmd || Symtab.nsyms == 0) return basic_symbol_iterator(SymbolRef(DRI, this)); - MachO::symtab_command Symtab = getSymtabLoadCommand(); unsigned SymbolTableEntrySize = is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); @@ -961,20 +1104,29 @@ basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { } basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { - DataRefImpl DRI; - if (!SymtabLoadCmd) - return basic_symbol_iterator(SymbolRef(DRI, this)); - MachO::symtab_command Symtab = getSymtabLoadCommand(); - if (Index >= Symtab.nsyms) + if (!SymtabLoadCmd || Index >= Symtab.nsyms) report_fatal_error("Requested symbol index is out of range."); unsigned SymbolTableEntrySize = is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); + DataRefImpl DRI; DRI.p = reinterpret_cast(getPtr(this, Symtab.symoff)); DRI.p += Index * SymbolTableEntrySize; return basic_symbol_iterator(SymbolRef(DRI, this)); } +uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const { + MachO::symtab_command Symtab = getSymtabLoadCommand(); + if (!SymtabLoadCmd) + report_fatal_error("getSymbolIndex() called with no symbol table symbol"); + unsigned SymbolTableEntrySize = + is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); + DataRefImpl DRIstart; + DRIstart.p = reinterpret_cast(getPtr(this, Symtab.symoff)); + uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize; + return Index; +} + section_iterator MachOObjectFile::section_begin() const { DataRefImpl DRI; return section_iterator(SectionRef(DRI, this)); @@ -1036,8 +1188,8 @@ Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { } } -Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType, - const char **McpuDefault) { +Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType, + const char **McpuDefault) { if (McpuDefault) *McpuDefault = nullptr; @@ -1077,13 +1229,13 @@ Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType, case MachO::CPU_SUBTYPE_ARM_V7EM: if (McpuDefault) *McpuDefault = "cortex-m4"; - return Triple("armv7em-apple-darwin"); + return Triple("thumbv7em-apple-darwin"); case MachO::CPU_SUBTYPE_ARM_V7K: return Triple("armv7k-apple-darwin"); case MachO::CPU_SUBTYPE_ARM_V7M: if (McpuDefault) *McpuDefault = "cortex-m3"; - return Triple("armv7m-apple-darwin"); + return Triple("thumbv7m-apple-darwin"); case MachO::CPU_SUBTYPE_ARM_V7S: return Triple("armv7s-apple-darwin"); default: @@ -1115,56 +1267,6 @@ Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType, } } -Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType, - const char **McpuDefault) { - if (McpuDefault) - *McpuDefault = nullptr; - - switch (CPUType) { - case MachO::CPU_TYPE_ARM: - switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { - case MachO::CPU_SUBTYPE_ARM_V4T: - return Triple("thumbv4t-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_V5TEJ: - return Triple("thumbv5e-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_XSCALE: - return Triple("xscale-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_V6: - return Triple("thumbv6-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_V6M: - if (McpuDefault) - *McpuDefault = "cortex-m0"; - return Triple("thumbv6m-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_V7: - return Triple("thumbv7-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_V7EM: - if (McpuDefault) - *McpuDefault = "cortex-m4"; - return Triple("thumbv7em-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_V7K: - return Triple("thumbv7k-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_V7M: - if (McpuDefault) - *McpuDefault = "cortex-m3"; - return Triple("thumbv7m-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_V7S: - return Triple("thumbv7s-apple-darwin"); - default: - return Triple(); - } - default: - return Triple(); - } -} - -Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType, - const char **McpuDefault, Triple *ThumbTriple) { - Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault); - *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType, - McpuDefault); - return T; -} - Triple MachOObjectFile::getHostArch() { return Triple(sys::getDefaultTargetTriple()); } @@ -1194,10 +1296,8 @@ unsigned MachOObjectFile::getArch() const { return getArch(getCPUType(this)); } -Triple MachOObjectFile::getArch(const char **McpuDefault, - Triple *ThumbTriple) const { - *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault); - return getArch(Header.cputype, Header.cpusubtype, McpuDefault); +Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const { + return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault); } relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { @@ -2307,23 +2407,17 @@ bool MachOObjectFile::isRelocatableObject() const { return getHeader().filetype == MachO::MH_OBJECT; } -ErrorOr> +Expected> ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) { StringRef Magic = Buffer.getBuffer().slice(0, 4); - std::error_code EC; - std::unique_ptr Ret; if (Magic == "\xFE\xED\xFA\xCE") - Ret.reset(new MachOObjectFile(Buffer, false, false, EC)); - else if (Magic == "\xCE\xFA\xED\xFE") - Ret.reset(new MachOObjectFile(Buffer, true, false, EC)); - else if (Magic == "\xFE\xED\xFA\xCF") - Ret.reset(new MachOObjectFile(Buffer, false, true, EC)); - else if (Magic == "\xCF\xFA\xED\xFE") - Ret.reset(new MachOObjectFile(Buffer, true, true, EC)); - else - return object_error::parse_failed; - - if (EC) - return EC; - return std::move(Ret); + return MachOObjectFile::create(Buffer, false, false); + if (Magic == "\xCE\xFA\xED\xFE") + return MachOObjectFile::create(Buffer, true, false); + if (Magic == "\xFE\xED\xFA\xCF") + return MachOObjectFile::create(Buffer, false, true); + if (Magic == "\xCF\xFA\xED\xFE") + return MachOObjectFile::create(Buffer, true, true); + return make_error("Unrecognized MachO magic number", + object_error::invalid_file_type); } -- cgit v1.1