Index: include/llvm/Object/MachO.h =================================================================== --- include/llvm/Object/MachO.h +++ include/llvm/Object/MachO.h @@ -200,7 +200,7 @@ // MachO specific. std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const; - unsigned getSectionType(SectionRef Sec) const; + std::error_code getSectionType(SectionRef Sec, unsigned &Type) const; std::error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const override; @@ -330,73 +330,91 @@ SectionRef getAnyRelocationSection(const MachO::any_relocation_info &RE) const; // Walk load commands. - LoadCommandInfo getFirstLoadCommandInfo() const; - LoadCommandInfo getNextLoadCommandInfo(const LoadCommandInfo &L) const; + std::error_code getFirstLoadCommandInfo(LoadCommandInfo &Load) const; + std::error_code getNextLoadCommandInfo(const LoadCommandInfo &L, + LoadCommandInfo &Next) const; // MachO specific structures. - MachO::section getSection(DataRefImpl DRI) const; - MachO::section_64 getSection64(DataRefImpl DRI) const; - MachO::section getSection(const LoadCommandInfo &L, unsigned Index) const; - MachO::section_64 getSection64(const LoadCommandInfo &L,unsigned Index) const; - MachO::nlist getSymbolTableEntry(DataRefImpl DRI) const; - MachO::nlist_64 getSymbol64TableEntry(DataRefImpl DRI) const; - - MachO::linkedit_data_command - getLinkeditDataLoadCommand(const LoadCommandInfo &L) const; - MachO::segment_command - getSegmentLoadCommand(const LoadCommandInfo &L) const; - MachO::segment_command_64 - getSegment64LoadCommand(const LoadCommandInfo &L) const; - MachO::linker_option_command - getLinkerOptionLoadCommand(const LoadCommandInfo &L) const; - MachO::version_min_command - getVersionMinLoadCommand(const LoadCommandInfo &L) const; - MachO::dylib_command - getDylibIDLoadCommand(const LoadCommandInfo &L) const; - MachO::dyld_info_command - getDyldInfoLoadCommand(const LoadCommandInfo &L) const; - MachO::dylinker_command - getDylinkerCommand(const LoadCommandInfo &L) const; - MachO::uuid_command - getUuidCommand(const LoadCommandInfo &L) const; - MachO::rpath_command - getRpathCommand(const LoadCommandInfo &L) const; - MachO::source_version_command - getSourceVersionCommand(const LoadCommandInfo &L) const; - MachO::entry_point_command - getEntryPointCommand(const LoadCommandInfo &L) const; - MachO::encryption_info_command - getEncryptionInfoCommand(const LoadCommandInfo &L) const; - MachO::encryption_info_command_64 - getEncryptionInfoCommand64(const LoadCommandInfo &L) const; - MachO::sub_framework_command - getSubFrameworkCommand(const LoadCommandInfo &L) const; - MachO::sub_umbrella_command - getSubUmbrellaCommand(const LoadCommandInfo &L) const; - MachO::sub_library_command - getSubLibraryCommand(const LoadCommandInfo &L) const; - MachO::sub_client_command - getSubClientCommand(const LoadCommandInfo &L) const; - MachO::routines_command - getRoutinesCommand(const LoadCommandInfo &L) const; - MachO::routines_command_64 - getRoutinesCommand64(const LoadCommandInfo &L) const; - MachO::thread_command - getThreadCommand(const LoadCommandInfo &L) const; - - MachO::any_relocation_info getRelocation(DataRefImpl Rel) const; - MachO::data_in_code_entry getDice(DataRefImpl Rel) const; - MachO::mach_header getHeader() const; - MachO::mach_header_64 getHeader64() const; - uint32_t + std::error_code getSection(DataRefImpl DRI, MachO::section &Section) const; + std::error_code getSection64(DataRefImpl DRI, + MachO::section_64 &Section) const; + std::error_code getSection(const LoadCommandInfo &L, unsigned Index, + MachO::section &Section) const; + std::error_code getSection64(const LoadCommandInfo &L, unsigned Index, + MachO::section_64 &Section) const; + std::error_code getSymbolTableEntry(DataRefImpl DRI, + MachO::nlist &Nlist) const; + std::error_code getSymbol64TableEntry(DataRefImpl DRI, + MachO::nlist_64 &Nlist) const; + + std::error_code + getLinkeditDataLoadCommand(const LoadCommandInfo &L, + MachO::linkedit_data_command &Cmd) const; + std::error_code getSegmentLoadCommand(const LoadCommandInfo &L, + MachO::segment_command &Cmd) const; + std::error_code getSegment64LoadCommand(const LoadCommandInfo &L, + MachO::segment_command_64 &Cmd) const; + std::error_code + getLinkerOptionLoadCommand(const LoadCommandInfo &L, + MachO::linker_option_command &Cmd) const; + std::error_code + getVersionMinLoadCommand(const LoadCommandInfo &L, + MachO::version_min_command &Cmd) const; + std::error_code getDylibIDLoadCommand(const LoadCommandInfo &L, + MachO::dylib_command &Cmd) const; + std::error_code getDyldInfoLoadCommand(const LoadCommandInfo &L, + MachO::dyld_info_command &Cmd) const; + std::error_code getDylinkerCommand(const LoadCommandInfo &L, + MachO::dylinker_command &Cmd) const; + std::error_code getUuidCommand(const LoadCommandInfo &L, + MachO::uuid_command &Cmd) const; + std::error_code getRpathCommand(const LoadCommandInfo &L, + MachO::rpath_command &Cmd) const; + std::error_code + getSourceVersionCommand(const LoadCommandInfo &L, + MachO::source_version_command &Cmd) const; + std::error_code getEntryPointCommand(const LoadCommandInfo &L, + MachO::entry_point_command &Cmd) const; + std::error_code + getEncryptionInfoCommand(const LoadCommandInfo &L, + MachO::encryption_info_command &Cmd) const; + std::error_code + getEncryptionInfoCommand64(const LoadCommandInfo &L, + MachO::encryption_info_command_64 &Cmd) const; + std::error_code + getSubFrameworkCommand(const LoadCommandInfo &L, + MachO::sub_framework_command &Cmd) const; + std::error_code getSubUmbrellaCommand(const LoadCommandInfo &L, + MachO::sub_umbrella_command &Cmd) const; + std::error_code getSubLibraryCommand(const LoadCommandInfo &L, + MachO::sub_library_command &Cmd) const; + std::error_code getSubClientCommand(const LoadCommandInfo &L, + MachO::sub_client_command &Cmd) const; + std::error_code getRoutinesCommand(const LoadCommandInfo &L, + MachO::routines_command &Cmd) const; + std::error_code getRoutinesCommand64(const LoadCommandInfo &L, + MachO::routines_command_64 &Cmd) const; + std::error_code getThreadCommand(const LoadCommandInfo &L, + MachO::thread_command &Cmd) const; + + std::error_code getRelocation(DataRefImpl Rel, + MachO::any_relocation_info &RelInfo) const; + std::error_code getDice(DataRefImpl Rel, MachO::data_in_code_entry &Dice) const; + std::error_code getHeader(MachO::mach_header &Header) const; + std::error_code getHeader64(MachO::mach_header_64 &Header) const; + std::error_code getIndirectSymbolTableEntry(const MachO::dysymtab_command &DLC, - unsigned Index) const; - MachO::data_in_code_entry getDataInCodeTableEntry(uint32_t DataOffset, - unsigned Index) const; - MachO::symtab_command getSymtabLoadCommand() const; - MachO::dysymtab_command getDysymtabLoadCommand() const; - MachO::linkedit_data_command getDataInCodeLoadCommand() const; - MachO::linkedit_data_command getLinkOptHintsLoadCommand() const; + unsigned Index, uint32_t &Res) const; + std::error_code + getDataInCodeTableEntry(uint32_t DataOffset, unsigned Index, + MachO::data_in_code_entry &Dice) const; + std::error_code getSymtabLoadCommand(MachO::symtab_command &Cmd) const; + std::error_code getDysymtabLoadCommand(MachO::dysymtab_command &Cmd) const; + std::error_code + getDataInCodeLoadCommand(MachO::linkedit_data_command &Cmd) const; + std::error_code + getLinkOptHintsLoadCommand(MachO::linkedit_data_command &Cmd) const; + ArrayRef getDyldInfoRebaseOpcodes() const; ArrayRef getDyldInfoBindOpcodes() const; ArrayRef getDyldInfoWeakBindOpcodes() const; @@ -404,7 +422,7 @@ ArrayRef getDyldInfoExportsTrie() const; ArrayRef getUuid() const; - StringRef getStringTableData() const; + std::error_code getStringTableData(StringRef &Res) const; bool is64Bit() const; void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; @@ -470,7 +488,9 @@ inline std::error_code DiceRef::getOffset(uint32_t &Result) const { const MachOObjectFile *MachOOF = static_cast(OwningObject); - MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); + MachO::data_in_code_entry Dice; + if (auto Err = MachOOF->getDice(DicePimpl, Dice)) + return Err; Result = Dice.offset; return object_error::success; } @@ -478,7 +498,9 @@ inline std::error_code DiceRef::getLength(uint16_t &Result) const { const MachOObjectFile *MachOOF = static_cast(OwningObject); - MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); + MachO::data_in_code_entry Dice; + if (auto Err = MachOOF->getDice(DicePimpl, Dice)) + return Err; Result = Dice.length; return object_error::success; } @@ -486,7 +508,9 @@ inline std::error_code DiceRef::getKind(uint16_t &Result) const { const MachOObjectFile *MachOOF = static_cast(OwningObject); - MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); + MachO::data_in_code_entry Dice; + if (auto Err = MachOOF->getDice(DicePimpl, Dice)) + return Err; Result = Dice.kind; return object_error::success; } Index: lib/Object/MachOObjectFile.cpp =================================================================== --- lib/Object/MachOObjectFile.cpp +++ lib/Object/MachOObjectFile.cpp @@ -39,47 +39,59 @@ } template -static T getStruct(const MachOObjectFile *O, const char *P) { +static std::error_code getStruct(const MachOObjectFile *O, const char *P, + T &Cmd) { // Don't read before the beginning or past the end of the file if (P < O->getData().begin() || P + sizeof(T) > O->getData().end()) - report_fatal_error("Malformed MachO file."); + return object_error::parse_failed; - T Cmd; memcpy(&Cmd, P, sizeof(T)); if (O->isLittleEndian() != sys::IsLittleEndianHost) MachO::swapStruct(Cmd); - return Cmd; + return std::error_code(); } template -static uint32_t getSegmentLoadCommandNumSections(const SegmentCmd &S, - uint32_t Cmdsize) { +static std::error_code getSegmentLoadCommandNumSections(const SegmentCmd &S, + uint32_t Cmdsize, + uint32_t &NumSections) { const unsigned SectionSize = sizeof(SegmentCmd); + // Number of sections too large for size of load command. if (S.nsects > std::numeric_limits::max() / SectionSize || S.nsects * SectionSize > Cmdsize - sizeof(S)) - report_fatal_error( - "Number of sections too large for size of load command."); - return S.nsects; + return object_error::parse_failed; + NumSections = S.nsects; + return std::error_code(); } -static uint32_t +static std::error_code getSegmentLoadCommandNumSections(const MachOObjectFile *O, - const MachOObjectFile::LoadCommandInfo &L) { - if (O->is64Bit()) - return getSegmentLoadCommandNumSections(O->getSegment64LoadCommand(L), - L.C.cmdsize); + const MachOObjectFile::LoadCommandInfo &L, + uint32_t &NumSections) { + if (O->is64Bit()) { + MachO::segment_command_64 Cmd; + if (auto Err = O->getSegment64LoadCommand(L, Cmd)) + return Err; + return getSegmentLoadCommandNumSections(Cmd, L.C.cmdsize, NumSections); + } - return getSegmentLoadCommandNumSections(O->getSegmentLoadCommand(L), - L.C.cmdsize); + MachO::segment_command Cmd; + if (auto Err = O->getSegmentLoadCommand(L, Cmd)) + return Err; + return getSegmentLoadCommandNumSections(Cmd, L.C.cmdsize, NumSections); } static bool isPageZeroSegment(const MachOObjectFile *O, const MachOObjectFile::LoadCommandInfo &L) { if (O->is64Bit()) { - MachO::segment_command_64 S = O->getSegment64LoadCommand(L); + MachO::segment_command_64 S; + if (O->getSegment64LoadCommand(L, S)) + return false; return StringRef("__PAGEZERO").equals(S.segname); } - MachO::segment_command S = O->getSegmentLoadCommand(L); + MachO::segment_command S; + if (O->getSegmentLoadCommand(L, S)) + return false; return StringRef("__PAGEZERO").equals(S.segname); } @@ -103,10 +115,11 @@ return O->getData().substr(Offset, 1).data(); } -static MachO::nlist_base -getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) { +static std::error_code getSymbolTableEntryBase(const MachOObjectFile *O, + DataRefImpl DRI, + MachO::nlist_base &NlistBase) { const char *P = reinterpret_cast(DRI.p); - return getStruct(O, P); + return getStruct(O, P, NlistBase); } static StringRef parseSegmentOrSectionName(const char *P) { @@ -124,8 +137,12 @@ ++it; } -static unsigned getCPUType(const MachOObjectFile *O) { - return O->getHeader().cputype; +static std::error_code getCPUType(const MachOObjectFile *O, unsigned &Res) { + MachO::mach_header Header; + if (auto Err = O->getHeader(Header)) + return Err; + Res = Header.cputype; + return std::error_code(); } static void printRelocationTargetName(const MachOObjectFile *O, @@ -234,14 +251,20 @@ return RE.r_word1 & 0xf; } -static uint32_t getSectionFlags(const MachOObjectFile *O, - DataRefImpl Sec) { +static std::error_code getSectionFlags(const MachOObjectFile *O, + DataRefImpl Sec, uint32_t &Flags) { if (O->is64Bit()) { - MachO::section_64 Sect = O->getSection64(Sec); - return Sect.flags; + MachO::section_64 Sect; + if (auto Err = O->getSection64(Sec, Sect)) + return Err; + Flags = Sect.flags; + return std::error_code(); } - MachO::section Sect = O->getSection(Sec); - return Sect.flags; + MachO::section Sect; + if (auto Err = O->getSection(Sec, Sect)) + return Err; + Flags = Sect.flags; + return std::error_code(); } MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, @@ -251,14 +274,19 @@ DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr), DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr), HasPageZeroSegment(false) { - uint32_t LoadCommandCount = this->getHeader().ncmds; + MachO::mach_header Header; + if ((EC = getHeader(Header))) + return; + uint32_t LoadCommandCount = Header.ncmds; if (LoadCommandCount == 0) return; MachO::LoadCommandType SegmentLoadType = is64Bit() ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT; - MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo(); + MachOObjectFile::LoadCommandInfo Load; + if ((EC = getFirstLoadCommandInfo(Load))) + return; for (unsigned I = 0; ; ++I) { if (Load.C.cmd == MachO::LC_SYMTAB) { // Multiple symbol tables @@ -307,10 +335,14 @@ const unsigned SegmentLoadSize = this->is64Bit() ? sizeof(MachO::segment_command_64) : sizeof(MachO::segment_command); - if (Load.C.cmdsize < SegmentLoadSize) - report_fatal_error("Segment load command size is too small."); - - uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load); + if (Load.C.cmdsize < SegmentLoadSize) { + // Segment load command size is too small. + EC = object_error::parse_failed; + return; + } + uint32_t NumSections; + if ((EC = getSegmentLoadCommandNumSections(this, Load, NumSections))) + return; for (unsigned J = 0; J < NumSections; ++J) { const char *Sec = getSectionPtr(this, Load, J); Sections.push_back(Sec); @@ -327,8 +359,8 @@ if (I == LoadCommandCount - 1) break; - else - Load = getNextLoadCommandInfo(Load); + if ((EC = getNextLoadCommandInfo(Load, Load))) + return; } } @@ -341,35 +373,49 @@ std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, StringRef &Res) const { - StringRef StringTable = getStringTableData(); - MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); + StringRef StringTable; + if (auto Err = getStringTableData(StringTable)) + return Err; + MachO::nlist_base Entry; + if (auto Err = getSymbolTableEntryBase(this, Symb, Entry)) + return Err; const char *Start = &StringTable.data()[Entry.n_strx]; + // Symbol name entry points before beginning or past end of file. if (Start < getData().begin() || Start >= getData().end()) - report_fatal_error( - "Symbol name entry points before beginning or past end of file."); + return object_error::parse_failed; Res = StringRef(Start); return object_error::success; } -unsigned MachOObjectFile::getSectionType(SectionRef Sec) const { +std::error_code MachOObjectFile::getSectionType(SectionRef Sec, + unsigned &Type) const { DataRefImpl DRI = Sec.getRawDataRefImpl(); - uint32_t Flags = getSectionFlags(this, DRI); - return Flags & MachO::SECTION_TYPE; + uint32_t Flags; + if (auto Err = getSectionFlags(this, DRI, Flags)) + return Err; + Type = Flags & MachO::SECTION_TYPE; + return object_error::success; } // getIndirectName() returns the name of the alias'ed symbol who's string table // index is in the n_value field. std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb, StringRef &Res) const { - StringRef StringTable = getStringTableData(); + StringRef StringTable; + if (auto Err = getStringTableData(StringTable)) + return Err; uint64_t NValue; if (is64Bit()) { - MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); + MachO::nlist_64 Entry; + if (auto Err = getSymbol64TableEntry(Symb, Entry)) + return Err; NValue = Entry.n_value; if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) return object_error::parse_failed; } else { - MachO::nlist Entry = getSymbolTableEntry(Symb); + MachO::nlist Entry; + if (auto Err = getSymbolTableEntry(Symb, Entry)) + return Err; NValue = Entry.n_value; if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) return object_error::parse_failed; @@ -384,14 +430,18 @@ std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const { if (is64Bit()) { - MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); + MachO::nlist_64 Entry; + if (auto Err = getSymbol64TableEntry(Symb, Entry)) + return Err; if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && Entry.n_value == 0) Res = UnknownAddressOrSize; else Res = Entry.n_value; } else { - MachO::nlist Entry = getSymbolTableEntry(Symb); + MachO::nlist Entry; + if (auto Err = getSymbolTableEntry(Symb, Entry)) + return Err; if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && Entry.n_value == 0) Res = UnknownAddressOrSize; @@ -405,7 +455,9 @@ uint32_t &Result) const { uint32_t flags = getSymbolFlags(DRI); if (flags & SymbolRef::SF_Common) { - MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); + MachO::nlist_base Entry; + if (auto Err = getSymbolTableEntryBase(this, DRI, Entry)) + return Err; Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); } else { Result = 0; @@ -427,7 +479,9 @@ std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const { - MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); + MachO::nlist_base Entry; + if (auto Err = getSymbolTableEntryBase(this, Symb, Entry)) + return Err; uint8_t n_type = Entry.n_type; Res = SymbolRef::ST_Other; @@ -450,7 +504,10 @@ } uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { - MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); + MachO::nlist_base Entry; + // FIXME: Shouldn't getSymbolFlags() return std::error_code as well? + if (getSymbolTableEntryBase(this, DRI, Entry)) + return 0U; uint8_t MachOType = Entry.n_type; uint16_t MachOFlags = Entry.n_desc; @@ -493,7 +550,9 @@ std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, section_iterator &Res) const { - MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); + MachO::nlist_base Entry; + if (auto Err = getSymbolTableEntryBase(this, Symb, Entry)) + return Err; uint8_t index = Entry.n_sect; if (index == 0) { @@ -501,8 +560,9 @@ } else { DataRefImpl DRI; DRI.d.a = index - 1; + // Invalid section index. if (DRI.d.a >= Sections.size()) - report_fatal_error("getSymbolSection: Invalid section index."); + return object_error::parse_failed; Res = section_iterator(SectionRef(DRI, this)); } @@ -521,15 +581,29 @@ } uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const { - if (is64Bit()) - return getSection64(Sec).addr; - return getSection(Sec).addr; + if (is64Bit()) { + MachO::section_64 Section; + if (getSection64(Sec, Section)) + return UnknownAddressOrSize; + return Section.addr; + } + MachO::section Section; + if (getSection(Sec, Section)) + return UnknownAddressOrSize; + return Section.addr; } uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const { - if (is64Bit()) - return getSection64(Sec).size; - return getSection(Sec).size; + if (is64Bit()) { + MachO::section_64 Section; + if (getSection64(Sec, Section)) + return UnknownAddressOrSize; + return Section.size; + } + MachO::section Section; + if (getSection(Sec, Section)) + return UnknownAddressOrSize; + return Section.size; } std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, @@ -538,11 +612,15 @@ uint64_t Size; if (is64Bit()) { - MachO::section_64 Sect = getSection64(Sec); + MachO::section_64 Sect; + if (auto Err = getSection64(Sec, Sect)) + return Err; Offset = Sect.offset; Size = Sect.size; } else { - MachO::section Sect = getSection(Sec); + MachO::section Sect; + if (auto Err = getSection(Sec, Sect)) + return Err; Offset = Sect.offset; Size = Sect.size; } @@ -552,25 +630,31 @@ } uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const { - uint32_t Align; + uint32_t Align = 0; if (is64Bit()) { - MachO::section_64 Sect = getSection64(Sec); - Align = Sect.align; + MachO::section_64 Sect; + if (!getSection64(Sec, Sect)) + Align = Sect.align; } else { - MachO::section Sect = getSection(Sec); - Align = Sect.align; + MachO::section Sect; + if (!getSection(Sec, Sect)) + Align = Sect.align; } return uint64_t(1) << Align; } bool MachOObjectFile::isSectionText(DataRefImpl Sec) const { - uint32_t Flags = getSectionFlags(this, Sec); + uint32_t Flags; + if (getSectionFlags(this, Sec, Flags)) + return false; return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; } bool MachOObjectFile::isSectionData(DataRefImpl Sec) const { - uint32_t Flags = getSectionFlags(this, Sec); + uint32_t Flags; + if (getSectionFlags(this, Sec, Flags)) + return false; unsigned SectionType = Flags & MachO::SECTION_TYPE; return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && !(SectionType == MachO::S_ZEROFILL || @@ -578,7 +662,9 @@ } bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const { - uint32_t Flags = getSectionFlags(this, Sec); + uint32_t Flags; + if (getSectionFlags(this, Sec, Flags)) + return false; unsigned SectionType = Flags & MachO::SECTION_TYPE; return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && (SectionType == MachO::S_ZEROFILL || @@ -615,13 +701,15 @@ relocation_iterator MachOObjectFile::section_rel_end(DataRefImpl Sec) const { - uint32_t Num; + uint32_t Num = 0; if (is64Bit()) { - MachO::section_64 Sect = getSection64(Sec); - Num = Sect.nreloc; + MachO::section_64 Sect; + if (!getSection64(Sec, Sect)) + Num = Sect.nreloc; } else { - MachO::section Sect = getSection(Sec); - Num = Sect.nreloc; + MachO::section Sect; + if (!getSection(Sec, Sect)) + Num = Sect.nreloc; } DataRefImpl Ret; @@ -648,17 +736,22 @@ std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const { - assert(getHeader().filetype == MachO::MH_OBJECT && + MachO::mach_header Header; + if (auto Err = getHeader(Header)) + return Err; + assert(Header.filetype == MachO::MH_OBJECT && "Only implemented for MH_OBJECT"); - MachO::any_relocation_info RE = getRelocation(Rel); + MachO::any_relocation_info RE; + if (auto Err = getRelocation(Rel, RE)) + return Err; Res = getAnyRelocationAddress(RE); return object_error::success; } symbol_iterator MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { - MachO::any_relocation_info RE = getRelocation(Rel); - if (isRelocationScattered(RE)) + MachO::any_relocation_info RE; + if (getRelocation(Rel, RE) || isRelocationScattered(RE)) return symbol_end(); uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); @@ -666,7 +759,10 @@ if (!isExtern) return symbol_end(); - MachO::symtab_command S = getSymtabLoadCommand(); + MachO::symtab_command S; + if (!getSymtabLoadCommand(S)) + return symbol_end(); + unsigned SymbolTableEntrySize = is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); @@ -678,12 +774,18 @@ section_iterator MachOObjectFile::getRelocationSection(DataRefImpl Rel) const { - return section_iterator(getAnyRelocationSection(getRelocation(Rel))); + MachO::any_relocation_info RE; + if (!getRelocation(Rel, RE)) + return section_end(); + + return section_iterator(getAnyRelocationSection(RE)); } std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, uint64_t &Res) const { - MachO::any_relocation_info RE = getRelocation(Rel); + MachO::any_relocation_info RE; + if (auto Err = getRelocation(Rel, RE)) + return Err; Res = getAnyRelocationType(RE); return object_error::success; } @@ -803,7 +905,9 @@ std::error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) const { - MachO::any_relocation_info RE = getRelocation(Rel); + MachO::any_relocation_info RE; + if (auto Err = getRelocation(Rel, RE)) + return Err; unsigned Arch = this->getArch(); @@ -830,7 +934,9 @@ case MachO::X86_64_RELOC_SUBTRACTOR: { DataRefImpl RelNext = Rel; moveRelocationNext(RelNext); - MachO::any_relocation_info RENext = getRelocation(RelNext); + MachO::any_relocation_info RENext; + if (auto Err = getRelocation(RelNext, RENext)) + return Err; // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type // X86_64_RELOC_UNSIGNED. @@ -878,7 +984,9 @@ case MachO::GENERIC_RELOC_SECTDIFF: { DataRefImpl RelNext = Rel; moveRelocationNext(RelNext); - MachO::any_relocation_info RENext = getRelocation(RelNext); + MachO::any_relocation_info RENext; + if (auto Err = getRelocation(RelNext, RENext)) + return Err; // X86 sect diff's must be followed by a relocation of type // GENERIC_RELOC_PAIR. @@ -900,7 +1008,9 @@ case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { DataRefImpl RelNext = Rel; moveRelocationNext(RelNext); - MachO::any_relocation_info RENext = getRelocation(RelNext); + MachO::any_relocation_info RENext; + if (auto Err = getRelocation(RelNext, RENext)) + return Err; // X86 sect diff's must be followed by a relocation of type // GENERIC_RELOC_PAIR. @@ -939,7 +1049,9 @@ DataRefImpl RelNext = Rel; moveRelocationNext(RelNext); - MachO::any_relocation_info RENext = getRelocation(RelNext); + MachO::any_relocation_info RENext; + if (auto Err = getRelocation(RelNext, RENext)) + return Err; // ARM half relocs must be followed by a relocation of type // ARM_RELOC_PAIR. @@ -1160,8 +1272,9 @@ // all the Libraries. if (LibrariesShortNames.size() == 0) { for (unsigned i = 0; i < Libraries.size(); i++) { - MachO::dylib_command D = - getStruct(this, Libraries[i]); + MachO::dylib_command D; + if (auto Err = getStruct(this, Libraries[i], D)) + return Err; if (D.dylib.name >= D.cmdsize) return object_error::parse_failed; const char *P = (const char *)(Libraries[i]) + D.dylib.name; @@ -1191,7 +1304,10 @@ if (!SymtabLoadCmd) return basic_symbol_iterator(SymbolRef(DRI, this)); - MachO::symtab_command Symtab = getSymtabLoadCommand(); + MachO::symtab_command Symtab; + if (!getSymtabLoadCommand(Symtab)) + return basic_symbol_iterator(SymbolRef(DRI, this)); + unsigned SymbolTableEntrySize = is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); @@ -1206,7 +1322,10 @@ if (!SymtabLoadCmd) return basic_symbol_iterator(SymbolRef(DRI, this)); - MachO::symtab_command Symtab = getSymtabLoadCommand(); + MachO::symtab_command Symtab; + if (!getSymtabLoadCommand(Symtab)) + return basic_symbol_iterator(SymbolRef(DRI, this)); + if (Index >= Symtab.nsyms) report_fatal_error("Requested symbol index is out of range."); unsigned SymbolTableEntrySize = @@ -1232,7 +1351,9 @@ } StringRef MachOObjectFile::getFileFormatName() const { - unsigned CPUType = getCPUType(this); + unsigned CPUType; + if (getCPUType(this, CPUType)) + return "Mach-O unknown"; if (!is64Bit()) { switch (CPUType) { case llvm::MachO::CPU_TYPE_I386: @@ -1432,7 +1553,10 @@ } unsigned MachOObjectFile::getArch() const { - return getArch(getCPUType(this)); + unsigned CPUType; + if (getCPUType(this, CPUType)) + return Triple::UnknownArch; + return getArch(CPUType); } Triple MachOObjectFile::getArch(const char **McpuDefault, @@ -1440,13 +1564,15 @@ Triple T; if (is64Bit()) { MachO::mach_header_64 H_64; - H_64 = getHeader64(); + if (getHeader64(H_64)) + return Triple(); T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault); *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype, McpuDefault); } else { MachO::mach_header H; - H = getHeader(); + if (getHeader(H)) + return Triple(); T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault); *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype, McpuDefault); @@ -1471,7 +1597,10 @@ if (!DataInCodeLoadCmd) return dice_iterator(DiceRef(DRI, this)); - MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); + MachO::linkedit_data_command DicLC; + if (!getDataInCodeLoadCommand(DicLC)) + return dice_iterator(DiceRef(DRI, this)); + DRI.p = reinterpret_cast(getPtr(this, DicLC.dataoff)); return dice_iterator(DiceRef(DRI, this)); } @@ -1481,7 +1610,10 @@ if (!DataInCodeLoadCmd) return dice_iterator(DiceRef(DRI, this)); - MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); + MachO::linkedit_data_command DicLC; + if (!getDataInCodeLoadCommand(DicLC)) + return dice_iterator(DiceRef(DRI, this)); + unsigned Offset = DicLC.dataoff + DicLC.datasize; DRI.p = reinterpret_cast(getPtr(this, Offset)); return dice_iterator(DiceRef(DRI, this)); @@ -2126,10 +2258,12 @@ return makeArrayRef(Base->segname); } -bool -MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) - const { - if (getCPUType(this) == MachO::CPU_TYPE_X86_64) +bool MachOObjectFile::isRelocationScattered( + const MachO::any_relocation_info &RE) const { + unsigned CPUType; + if (getCPUType(this, CPUType)) + return false; + if (CPUType == MachO::CPU_TYPE_X86_64) return false; return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; } @@ -2203,236 +2337,264 @@ return SectionRef(DRI, this); } -MachOObjectFile::LoadCommandInfo -MachOObjectFile::getFirstLoadCommandInfo() const { - MachOObjectFile::LoadCommandInfo Load; - +std::error_code +MachOObjectFile::getFirstLoadCommandInfo(LoadCommandInfo &Load) const { unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header); Load.Ptr = getPtr(this, HeaderSize); - Load.C = getStruct(this, Load.Ptr); + if (auto Err = getStruct(this, Load.Ptr, Load.C)) + return Err; + // Load command with size < 8 bytes. if (Load.C.cmdsize < 8) - report_fatal_error("Load command with size < 8 bytes."); - return Load; + return object_error::parse_failed; + return std::error_code(); } -MachOObjectFile::LoadCommandInfo -MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const { - MachOObjectFile::LoadCommandInfo Next; +std::error_code +MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L, + LoadCommandInfo &Next) const { Next.Ptr = L.Ptr + L.C.cmdsize; - Next.C = getStruct(this, Next.Ptr); + if (auto Err = getStruct(this, Next.Ptr, Next.C)) + return Err; + // Load command with size < 8 bytes. if (Next.C.cmdsize < 8) - report_fatal_error("Load command with size < 8 bytes."); - return Next; + return object_error::parse_failed; + return std::error_code(); } -MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { +std::error_code MachOObjectFile::getSection(DataRefImpl DRI, + MachO::section &Section) const { assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); - return getStruct(this, Sections[DRI.d.a]); + return getStruct(this, Sections[DRI.d.a], Section); } -MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { +std::error_code +MachOObjectFile::getSection64(DataRefImpl DRI, + MachO::section_64 &Section) const { assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); - return getStruct(this, Sections[DRI.d.a]); + return getStruct(this, Sections[DRI.d.a], Section); } -MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, - unsigned Index) const { +std::error_code MachOObjectFile::getSection(const LoadCommandInfo &L, + unsigned Index, + MachO::section &Section) const { const char *Sec = getSectionPtr(this, L, Index); - return getStruct(this, Sec); + return getStruct(this, Sec, Section); } -MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, - unsigned Index) const { +std::error_code +MachOObjectFile::getSection64(const LoadCommandInfo &L, unsigned Index, + MachO::section_64 &Section) const { const char *Sec = getSectionPtr(this, L, Index); - return getStruct(this, Sec); + return getStruct(this, Sec, Section); } -MachO::nlist -MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { +std::error_code +MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, + MachO::nlist &Nlist) const { const char *P = reinterpret_cast(DRI.p); - return getStruct(this, P); + return getStruct(this, P, Nlist); } -MachO::nlist_64 -MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { +std::error_code +MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI, + MachO::nlist_64 &Nlist) const { const char *P = reinterpret_cast(DRI.p); - return getStruct(this, P); + return getStruct(this, P, Nlist); } -MachO::linkedit_data_command -MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code MachOObjectFile::getLinkeditDataLoadCommand( + const LoadCommandInfo &L, MachO::linkedit_data_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::segment_command -MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code +MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L, + MachO::segment_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::segment_command_64 -MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code +MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L, + MachO::segment_command_64 &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::linker_option_command -MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code MachOObjectFile::getLinkerOptionLoadCommand( + const LoadCommandInfo &L, MachO::linker_option_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::version_min_command -MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code MachOObjectFile::getVersionMinLoadCommand( + const LoadCommandInfo &L, MachO::version_min_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::dylib_command -MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code +MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L, + MachO::dylib_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::dyld_info_command -MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code +MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L, + MachO::dyld_info_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::dylinker_command -MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code +MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L, + MachO::dylinker_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::uuid_command -MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code +MachOObjectFile::getUuidCommand(const LoadCommandInfo &L, + MachO::uuid_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::rpath_command -MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code +MachOObjectFile::getRpathCommand(const LoadCommandInfo &L, + MachO::rpath_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::source_version_command -MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code MachOObjectFile::getSourceVersionCommand( + const LoadCommandInfo &L, MachO::source_version_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::entry_point_command -MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code +MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L, + MachO::entry_point_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::encryption_info_command -MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code MachOObjectFile::getEncryptionInfoCommand( + const LoadCommandInfo &L, MachO::encryption_info_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::encryption_info_command_64 -MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code MachOObjectFile::getEncryptionInfoCommand64( + const LoadCommandInfo &L, MachO::encryption_info_command_64 &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::sub_framework_command -MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code MachOObjectFile::getSubFrameworkCommand( + const LoadCommandInfo &L, MachO::sub_framework_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::sub_umbrella_command -MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code +MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L, + MachO::sub_umbrella_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::sub_library_command -MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code +MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L, + MachO::sub_library_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::sub_client_command -MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code +MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L, + MachO::sub_client_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::routines_command -MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code +MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L, + MachO::routines_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::routines_command_64 -MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code +MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L, + MachO::routines_command_64 &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::thread_command -MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +std::error_code +MachOObjectFile::getThreadCommand(const LoadCommandInfo &L, + MachO::thread_command &Cmd) const { + return getStruct(this, L.Ptr, Cmd); } -MachO::any_relocation_info -MachOObjectFile::getRelocation(DataRefImpl Rel) const { +std::error_code +MachOObjectFile::getRelocation(DataRefImpl Rel, + MachO::any_relocation_info &RelInfo) const { DataRefImpl Sec; Sec.d.a = Rel.d.a; uint32_t Offset; if (is64Bit()) { - MachO::section_64 Sect = getSection64(Sec); + MachO::section_64 Sect; + if (auto Err = getSection64(Sec, Sect)) + return Err; Offset = Sect.reloff; } else { - MachO::section Sect = getSection(Sec); + MachO::section Sect; + if (auto Err = getSection(Sec, Sect)) + return Err; Offset = Sect.reloff; } auto P = reinterpret_cast( getPtr(this, Offset)) + Rel.d.b; - return getStruct( - this, reinterpret_cast(P)); + return getStruct(this, reinterpret_cast(P), RelInfo); } -MachO::data_in_code_entry -MachOObjectFile::getDice(DataRefImpl Rel) const { +std::error_code +MachOObjectFile::getDice(DataRefImpl Rel, + MachO::data_in_code_entry &Dice) const { const char *P = reinterpret_cast(Rel.p); - return getStruct(this, P); + return getStruct(this, P, Dice); } -MachO::mach_header MachOObjectFile::getHeader() const { - return getStruct(this, getPtr(this, 0)); +std::error_code MachOObjectFile::getHeader(MachO::mach_header &Header) const { + return getStruct(this, getPtr(this, 0), Header); } -MachO::mach_header_64 MachOObjectFile::getHeader64() const { - return getStruct(this, getPtr(this, 0)); +std::error_code +MachOObjectFile::getHeader64(MachO::mach_header_64 &Header) const { + return getStruct(this, getPtr(this, 0), Header); } -uint32_t MachOObjectFile::getIndirectSymbolTableEntry( - const MachO::dysymtab_command &DLC, - unsigned Index) const { +std::error_code MachOObjectFile::getIndirectSymbolTableEntry( + const MachO::dysymtab_command &DLC, unsigned Index, uint32_t &Res) const { uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); - return getStruct(this, getPtr(this, Offset)); + return getStruct(this, getPtr(this, Offset), Res); } -MachO::data_in_code_entry -MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, - unsigned Index) const { +std::error_code MachOObjectFile::getDataInCodeTableEntry( + uint32_t DataOffset, unsigned Index, + MachO::data_in_code_entry &Dice) const { uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); - return getStruct(this, getPtr(this, Offset)); + return getStruct(this, getPtr(this, Offset), Dice); } -MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { +std::error_code +MachOObjectFile::getSymtabLoadCommand(MachO::symtab_command &Cmd) const { if (SymtabLoadCmd) - return getStruct(this, SymtabLoadCmd); + return getStruct(this, SymtabLoadCmd, Cmd); // If there is no SymtabLoadCmd return a load command with zero'ed fields. - MachO::symtab_command Cmd; Cmd.cmd = MachO::LC_SYMTAB; Cmd.cmdsize = sizeof(MachO::symtab_command); Cmd.symoff = 0; Cmd.nsyms = 0; Cmd.stroff = 0; Cmd.strsize = 0; - return Cmd; + return std::error_code(); } -MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { +std::error_code +MachOObjectFile::getDysymtabLoadCommand(MachO::dysymtab_command &Cmd) const { if (DysymtabLoadCmd) - return getStruct(this, DysymtabLoadCmd); + return getStruct(this, DysymtabLoadCmd, Cmd); // If there is no DysymtabLoadCmd return a load command with zero'ed fields. - MachO::dysymtab_command Cmd; Cmd.cmd = MachO::LC_DYSYMTAB; Cmd.cmdsize = sizeof(MachO::dysymtab_command); Cmd.ilocalsym = 0; @@ -2453,88 +2615,91 @@ Cmd.nextrel = 0; Cmd.locreloff = 0; Cmd.nlocrel = 0; - return Cmd; + return std::error_code(); } -MachO::linkedit_data_command -MachOObjectFile::getDataInCodeLoadCommand() const { +std::error_code +MachOObjectFile::getDataInCodeLoadCommand(MachO::linkedit_data_command &Cmd) const { if (DataInCodeLoadCmd) - return getStruct(this, DataInCodeLoadCmd); + return getStruct(this, DataInCodeLoadCmd, Cmd); // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. - MachO::linkedit_data_command Cmd; Cmd.cmd = MachO::LC_DATA_IN_CODE; Cmd.cmdsize = sizeof(MachO::linkedit_data_command); Cmd.dataoff = 0; Cmd.datasize = 0; - return Cmd; + return std::error_code(); } -MachO::linkedit_data_command -MachOObjectFile::getLinkOptHintsLoadCommand() const { +std::error_code +MachOObjectFile::getLinkOptHintsLoadCommand(MachO::linkedit_data_command &Cmd) const { if (LinkOptHintsLoadCmd) - return getStruct(this, LinkOptHintsLoadCmd); + return getStruct(this, LinkOptHintsLoadCmd, Cmd); // If there is no LinkOptHintsLoadCmd return a load command with zero'ed // fields. - MachO::linkedit_data_command Cmd; Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT; Cmd.cmdsize = sizeof(MachO::linkedit_data_command); Cmd.dataoff = 0; Cmd.datasize = 0; - return Cmd; + return std::error_code(); } ArrayRef MachOObjectFile::getDyldInfoRebaseOpcodes() const { - if (!DyldInfoLoadCmd) + if (!DyldInfoLoadCmd) return ArrayRef(); - MachO::dyld_info_command DyldInfo - = getStruct(this, DyldInfoLoadCmd); + MachO::dyld_info_command DyldInfo; + if (getStruct(this, DyldInfoLoadCmd, DyldInfo)) + return ArrayRef(); const uint8_t *Ptr = reinterpret_cast( getPtr(this, DyldInfo.rebase_off)); return ArrayRef(Ptr, DyldInfo.rebase_size); } ArrayRef MachOObjectFile::getDyldInfoBindOpcodes() const { - if (!DyldInfoLoadCmd) + if (!DyldInfoLoadCmd) return ArrayRef(); - MachO::dyld_info_command DyldInfo - = getStruct(this, DyldInfoLoadCmd); + MachO::dyld_info_command DyldInfo; + if (getStruct(this, DyldInfoLoadCmd, DyldInfo)) + return ArrayRef(); const uint8_t *Ptr = reinterpret_cast( getPtr(this, DyldInfo.bind_off)); return ArrayRef(Ptr, DyldInfo.bind_size); } ArrayRef MachOObjectFile::getDyldInfoWeakBindOpcodes() const { - if (!DyldInfoLoadCmd) + if (!DyldInfoLoadCmd) return ArrayRef(); - MachO::dyld_info_command DyldInfo - = getStruct(this, DyldInfoLoadCmd); + MachO::dyld_info_command DyldInfo; + if (getStruct(this, DyldInfoLoadCmd, DyldInfo)) + return ArrayRef(); const uint8_t *Ptr = reinterpret_cast( getPtr(this, DyldInfo.weak_bind_off)); return ArrayRef(Ptr, DyldInfo.weak_bind_size); } ArrayRef MachOObjectFile::getDyldInfoLazyBindOpcodes() const { - if (!DyldInfoLoadCmd) + if (!DyldInfoLoadCmd) return ArrayRef(); - MachO::dyld_info_command DyldInfo - = getStruct(this, DyldInfoLoadCmd); + MachO::dyld_info_command DyldInfo; + if (getStruct(this, DyldInfoLoadCmd, DyldInfo)) + return ArrayRef(); const uint8_t *Ptr = reinterpret_cast( getPtr(this, DyldInfo.lazy_bind_off)); return ArrayRef(Ptr, DyldInfo.lazy_bind_size); } ArrayRef MachOObjectFile::getDyldInfoExportsTrie() const { - if (!DyldInfoLoadCmd) + if (!DyldInfoLoadCmd) return ArrayRef(); - MachO::dyld_info_command DyldInfo - = getStruct(this, DyldInfoLoadCmd); + MachO::dyld_info_command DyldInfo; + if (getStruct(this, DyldInfoLoadCmd, DyldInfo)) + return ArrayRef(); const uint8_t *Ptr = reinterpret_cast( getPtr(this, DyldInfo.export_off)); return ArrayRef(Ptr, DyldInfo.export_size); @@ -2548,9 +2713,12 @@ return ArrayRef(reinterpret_cast(Ptr), 16); } -StringRef MachOObjectFile::getStringTableData() const { - MachO::symtab_command S = getSymtabLoadCommand(); - return getData().substr(S.stroff, S.strsize); +std::error_code MachOObjectFile::getStringTableData(StringRef &Res) const { + MachO::symtab_command S; + if (auto Err = getSymtabLoadCommand(S)) + return Err; + Res = getData().substr(S.stroff, S.strsize); + return std::error_code(); } bool MachOObjectFile::is64Bit() const { @@ -2571,7 +2739,10 @@ } bool MachOObjectFile::isRelocatableObject() const { - return getHeader().filetype == MachO::MH_OBJECT; + MachO::mach_header Header; + if (getHeader(Header)) + return false; + return Header.filetype == MachO::MH_OBJECT; } ErrorOr>