diff options
-rw-r--r-- | llvm/include/llvm/Object/MachO.h | 22 | ||||
-rw-r--r-- | llvm/lib/Object/MachOObjectFile.cpp | 38 | ||||
-rw-r--r-- | llvm/test/tools/llvm-objdump/macho-bad-ordinal.test | 8 | ||||
-rw-r--r-- | llvm/tools/llvm-objdump/MachODump.cpp | 25 |
4 files changed, 65 insertions, 28 deletions
diff --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h index b91e8c36581..4ae28a529cc 100644 --- a/llvm/include/llvm/Object/MachO.h +++ b/llvm/include/llvm/Object/MachO.h @@ -139,13 +139,16 @@ typedef content_iterator<MachORebaseEntry> rebase_iterator; /// MachOBindEntry encapsulates the current state in the decompression of /// binding opcodes. This allows you to iterate through the compressed table of /// bindings using: -/// for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable()) { +/// Error Err; +/// for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(&Err)) { /// } +/// if (Err) { report error ... class MachOBindEntry { public: enum class Kind { Regular, Lazy, Weak }; - MachOBindEntry(ArrayRef<uint8_t> Opcodes, bool is64Bit, MachOBindEntry::Kind); + MachOBindEntry(Error *Err, const MachOObjectFile *O, + ArrayRef<uint8_t> Opcodes, bool is64Bit, MachOBindEntry::Kind); uint32_t segmentIndex() const; uint64_t segmentOffset() const; @@ -166,6 +169,8 @@ private: uint64_t readULEB128(); int64_t readSLEB128(); + Error *E; + const MachOObjectFile *O; ArrayRef<uint8_t> Opcodes; const uint8_t *Ptr; uint64_t SegmentOffset; @@ -245,6 +250,7 @@ public: // MachO specific. std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const; + uint32_t getLibraryCount() const; section_iterator getRelocationRelocatedSection(relocation_iterator Rel) const; @@ -292,16 +298,18 @@ public: bool is64); /// For use iterating over all bind table entries. - iterator_range<bind_iterator> bindTable() const; + iterator_range<bind_iterator> bindTable(Error &Err) const; /// For use iterating over all lazy bind table entries. - iterator_range<bind_iterator> lazyBindTable() const; + iterator_range<bind_iterator> lazyBindTable(Error &Err) const; - /// For use iterating over all lazy bind table entries. - iterator_range<bind_iterator> weakBindTable() const; + /// For use iterating over all weak bind table entries. + iterator_range<bind_iterator> weakBindTable(Error &Err) const; /// For use examining bind opcodes not in a MachOObjectFile. - static iterator_range<bind_iterator> bindTable(ArrayRef<uint8_t> Opcodes, + static iterator_range<bind_iterator> bindTable(Error &Err, + const MachOObjectFile *O, + ArrayRef<uint8_t> Opcodes, bool is64, MachOBindEntry::Kind); diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp index 928998330df..25f9a3d93dc 100644 --- a/llvm/lib/Object/MachOObjectFile.cpp +++ b/llvm/lib/Object/MachOObjectFile.cpp @@ -2272,6 +2272,10 @@ std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, return std::error_code(); } +uint32_t MachOObjectFile::getLibraryCount() const { + return Libraries.size(); +} + section_iterator MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const { DataRefImpl Sec; @@ -2925,8 +2929,9 @@ iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const { return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit()); } -MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK) - : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), +MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O, + ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK) + : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0), BindType(0), PointerSize(is64Bit ? 8 : 4), TableKind(BK), Malformed(false), Done(false) {} @@ -2943,6 +2948,7 @@ void MachOBindEntry::moveToEnd() { } void MachOBindEntry::moveNext() { + ErrorAsOutParameter ErrAsOutParam(E); // If in the middle of some loop, move to next binding in loop. SegmentOffset += AdvanceAmount; if (RemainingLoopCount) { @@ -2956,6 +2962,7 @@ void MachOBindEntry::moveNext() { bool More = true; while (More && !Malformed) { // Parse next opcode and set up next loop. + const uint8_t *OpcodeStart = Ptr; uint8_t Byte = *Ptr++; uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK; uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK; @@ -2982,6 +2989,14 @@ void MachOBindEntry::moveNext() { break; case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: Ordinal = ImmValue; + if (ImmValue > O->getLibraryCount()) { + *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad " + "library ordinal: " + Twine((int)ImmValue) + " (max " + + Twine((int)O->getLibraryCount()) + ") for opcode at: 0x" + + utohexstr(OpcodeStart - Opcodes.begin())); + moveToEnd(); + return; + } DEBUG_WITH_TYPE( "mach-o-bind", llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: " @@ -3165,29 +3180,30 @@ bool MachOBindEntry::operator==(const MachOBindEntry &Other) const { } iterator_range<bind_iterator> -MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64, +MachOObjectFile::bindTable(Error &Err, const MachOObjectFile *O, + ArrayRef<uint8_t> Opcodes, bool is64, MachOBindEntry::Kind BKind) { - MachOBindEntry Start(Opcodes, is64, BKind); + MachOBindEntry Start(&Err, O, Opcodes, is64, BKind); Start.moveToFirst(); - MachOBindEntry Finish(Opcodes, is64, BKind); + MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind); Finish.moveToEnd(); return make_range(bind_iterator(Start), bind_iterator(Finish)); } -iterator_range<bind_iterator> MachOObjectFile::bindTable() const { - return bindTable(getDyldInfoBindOpcodes(), is64Bit(), +iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) const { + return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(), MachOBindEntry::Kind::Regular); } -iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const { - return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(), +iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) const { + return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(), MachOBindEntry::Kind::Lazy); } -iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const { - return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(), +iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) const { + return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(), MachOBindEntry::Kind::Weak); } diff --git a/llvm/test/tools/llvm-objdump/macho-bad-ordinal.test b/llvm/test/tools/llvm-objdump/macho-bad-ordinal.test index 16badcc878d..fb49f77f075 100644 --- a/llvm/test/tools/llvm-objdump/macho-bad-ordinal.test +++ b/llvm/test/tools/llvm-objdump/macho-bad-ordinal.test @@ -1,6 +1,4 @@ -# RUN: llvm-objdump -macho -bind -lazy-bind %p/Inputs/bad-ordinal.macho-x86_64 \ -# RUN: | FileCheck %s +# RUN: not llvm-objdump -macho -lazy-bind %p/Inputs/bad-ordinal.macho-x86_64 \ +# RUN: 2>&1 | FileCheck %s - -# CHECK: __DATA __nl_symbol_ptr 0x100001000 pointer 0 <<bad library ordinal>> dyld_stub_binder -# CHECK: __DATA __la_symbol_ptr 0x100001010 <<bad library ordinal>> _printf +# CHECK: bad-ordinal.macho-x86_64': truncated or malformed object (for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad library ordinal: 2 (max 1) for opcode at: 0x2) diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp index 47425823424..7fe811b3b8f 100644 --- a/llvm/tools/llvm-objdump/MachODump.cpp +++ b/llvm/tools/llvm-objdump/MachODump.cpp @@ -9535,7 +9535,8 @@ void llvm::printMachOBindTable(const object::MachOObjectFile *Obj) { outs() << "segment section address type " "addend dylib symbol\n"; - for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable()) { + Error Err = Error::success(); + for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(Err)) { uint32_t SegIndex = Entry.segmentIndex(); uint64_t OffsetInSeg = Entry.segmentOffset(); StringRef SegmentName = sectionTable.segmentName(SegIndex); @@ -9555,6 +9556,8 @@ void llvm::printMachOBindTable(const object::MachOObjectFile *Obj) { << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " << Entry.symbolName() << Attr << "\n"; } + if (Err) + report_error(Obj->getFileName(), std::move(Err)); } //===----------------------------------------------------------------------===// @@ -9567,7 +9570,8 @@ void llvm::printMachOLazyBindTable(const object::MachOObjectFile *Obj) { outs() << "segment section address " "dylib symbol\n"; - for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable()) { + Error Err = Error::success(); + for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) { uint32_t SegIndex = Entry.segmentIndex(); uint64_t OffsetInSeg = Entry.segmentOffset(); StringRef SegmentName = sectionTable.segmentName(SegIndex); @@ -9582,6 +9586,8 @@ void llvm::printMachOLazyBindTable(const object::MachOObjectFile *Obj) { << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " << Entry.symbolName() << "\n"; } + if (Err) + report_error(Obj->getFileName(), std::move(Err)); } //===----------------------------------------------------------------------===// @@ -9594,7 +9600,8 @@ void llvm::printMachOWeakBindTable(const object::MachOObjectFile *Obj) { outs() << "segment section address " "type addend symbol\n"; - for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable()) { + Error Err = Error::success(); + for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) { // Strong symbols don't have a location to update. if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { outs() << " strong " @@ -9616,6 +9623,8 @@ void llvm::printMachOWeakBindTable(const object::MachOObjectFile *Obj) { << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName() << "\n"; } + if (Err) + report_error(Obj->getFileName(), std::move(Err)); } // get_dyld_bind_info_symbolname() is used for disassembly and passed an @@ -9627,16 +9636,22 @@ static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, if (info->bindtable == nullptr) { info->bindtable = llvm::make_unique<SymbolAddressMap>(); SegInfo sectionTable(info->O); - for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable()) { + Error Err = Error::success(); + for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable(Err)) { uint32_t SegIndex = Entry.segmentIndex(); uint64_t OffsetInSeg = Entry.segmentOffset(); - if (!sectionTable.isValidSegIndexAndOffset(SegIndex, OffsetInSeg)) + if (!sectionTable.isValidSegIndexAndOffset(SegIndex, OffsetInSeg)) { + if (Err) + report_error(info->O->getFileName(), std::move(Err)); return nullptr; + } uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); StringRef name = Entry.symbolName(); if (!name.empty()) (*info->bindtable)[Address] = name; } + if (Err) + report_error(info->O->getFileName(), std::move(Err)); } auto name = info->bindtable->lookup(ReferenceValue); return !name.empty() ? name.data() : nullptr; |