llvm.org GIT mirror llvm / 3903b47
Add the error handling for Mach-O dyld compact lazy bind, weak bind and rebase entry errors and test cases for each of the error checks. Also verified with Nick Kledzik that a BIND_OPCODE_SET_ADDEND_SLEB opcode is legal in a lazy bind table, so code that had that as an error check was removed. With MachORebaseEntry and MachOBindEntry classes now returning an llvm::Error in all cases for malformed input the variables Malformed and logic to set use them is no longer needed and has been removed from those classes. Also in a few places, removed the redundant Done assignment to true when also calling moveToEnd() as it does that assignment. This only leaves the dyld compact export entries left to have error handling yet to be added for the dyld compact info. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298883 91177308-0d34-0410-b5e6-96231b3b80d8 Kevin Enderby 3 years ago
22 changed file(s) with 351 addition(s) and 52 deletion(s). Raw diff Collapse all Expand all
145145 MachORebaseEntry(Error *Err, const MachOObjectFile *O,
146146 ArrayRef opcodes, bool is64Bit);
147147
148 uint32_t segmentIndex() const;
148 int32_t segmentIndex() const;
149149 uint64_t segmentOffset() const;
150150 StringRef typeName() const;
151151 StringRef segmentName() const;
160160 friend class MachOObjectFile;
161161 void moveToFirst();
162162 void moveToEnd();
163 uint64_t readULEB128();
163 uint64_t readULEB128(const char **error);
164164
165165 Error *E;
166166 const MachOObjectFile *O;
167167 ArrayRef Opcodes;
168168 const uint8_t *Ptr;
169169 uint64_t SegmentOffset;
170 uint32_t SegmentIndex;
170 int32_t SegmentIndex;
171171 uint64_t RemainingLoopCount;
172172 uint64_t AdvanceAmount;
173173 uint8_t RebaseType;
174174 uint8_t PointerSize;
175 bool Malformed;
176175 bool Done;
177176 };
178177 typedef content_iterator rebase_iterator;
230229 uint8_t BindType;
231230 uint8_t PointerSize;
232231 Kind TableKind;
233 bool Malformed;
234232 bool Done;
235233 };
236234 typedef content_iterator bind_iterator;
371369 /// For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
372370 /// the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode.
373371 const char *BindEntryCheckCountAndSkip(uint32_t Count, uint32_t Skip,
372 uint8_t PointerSize, int32_t SegIndex,
373 uint64_t SegOffset) const {
374 return BindRebaseSectionTable->checkCountAndSkip(Count, Skip, PointerSize,
375 SegIndex, SegOffset);
376 }
377
378 /// For use with a SegIndex,SegOffset pair in MachORebaseEntry::moveNext() to
379 /// validate a MachORebaseEntry.
380 const char *RebaseEntryCheckSegAndOffset(int32_t SegIndex, uint64_t SegOffset,
381 bool endInvalid) const {
382 return BindRebaseSectionTable->checkSegAndOffset(SegIndex, SegOffset,
383 endInvalid);
384 }
385 /// For use in MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
386 /// the REBASE_OPCODE_DO_*_TIMES* opcodes.
387 const char *RebaseEntryCheckCountAndSkip(uint32_t Count, uint32_t Skip,
374388 uint8_t PointerSize, int32_t SegIndex,
375389 uint64_t SegOffset) const {
376390 return BindRebaseSectionTable->checkCountAndSkip(Count, Skip, PointerSize,
27572757 MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
27582758 ArrayRef Bytes, bool is64Bit)
27592759 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0),
2760 SegmentIndex(0), RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
2761 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
2760 SegmentIndex(-1), RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
2761 PointerSize(is64Bit ? 8 : 4), Done(false) {}
27622762
27632763 void MachORebaseEntry::moveToFirst() {
27642764 Ptr = Opcodes.begin();
27722772 }
27732773
27742774 void MachORebaseEntry::moveNext() {
2775 ErrorAsOutParameter ErrAsOutParam(E);
27752776 // If in the middle of some loop, move to next rebasing in loop.
27762777 SegmentOffset += AdvanceAmount;
27772778 if (RemainingLoopCount) {
27782779 --RemainingLoopCount;
27792780 return;
27802781 }
2781 if (Ptr == Opcodes.end()) {
2782 if (Ptr >= Opcodes.end()) {
2783 if (Opcodes.begin() != Opcodes.end() && Done != true) {
2784 *E = malformedError("missing REBASE_OPCODE_DONE at end of opcodes");
2785 moveToEnd();
2786 return;
2787 }
27822788 Done = true;
27832789 return;
27842790 }
27852791 bool More = true;
2786 while (More && !Malformed) {
2792 while (More) {
27872793 // Parse next opcode and set up next loop.
2794 const uint8_t *OpcodeStart = Ptr;
27882795 uint8_t Byte = *Ptr++;
27892796 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
27902797 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
2798 uint32_t Count, Skip;
2799 const char *error = nullptr;
27912800 switch (Opcode) {
27922801 case MachO::REBASE_OPCODE_DONE:
27932802 More = false;
27972806 break;
27982807 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
27992808 RebaseType = ImmValue;
2809 if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
2810 *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
2811 Twine((int)RebaseType) + " for opcode at: 0x" +
2812 utohexstr(OpcodeStart - Opcodes.begin()));
2813 moveToEnd();
2814 return;
2815 }
28002816 DEBUG_WITH_TYPE(
28012817 "mach-o-rebase",
28022818 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
28042820 break;
28052821 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
28062822 SegmentIndex = ImmValue;
2807 SegmentOffset = readULEB128();
2823 SegmentOffset = readULEB128(&error);
2824 if (error) {
2825 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
2826 Twine(error) + " for opcode at: 0x" +
2827 utohexstr(OpcodeStart - Opcodes.begin()));
2828 moveToEnd();
2829 return;
2830 }
2831 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2832 true);
2833 if (error) {
2834 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
2835 Twine(error) + " for opcode at: 0x" +
2836 utohexstr(OpcodeStart - Opcodes.begin()));
2837 moveToEnd();
2838 return;
2839 }
28082840 DEBUG_WITH_TYPE(
28092841 "mach-o-rebase",
28102842 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
28132845 << "\n");
28142846 break;
28152847 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
2816 SegmentOffset += readULEB128();
2848 SegmentOffset += readULEB128(&error);
2849 if (error) {
2850 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " +
2851 Twine(error) + " for opcode at: 0x" +
2852 utohexstr(OpcodeStart - Opcodes.begin()));
2853 moveToEnd();
2854 return;
2855 }
2856 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2857 true);
2858 if (error) {
2859 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " +
2860 Twine(error) + " for opcode at: 0x" +
2861 utohexstr(OpcodeStart - Opcodes.begin()));
2862 moveToEnd();
2863 return;
2864 }
28172865 DEBUG_WITH_TYPE("mach-o-rebase",
28182866 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
28192867 << format("SegmentOffset=0x%06X",
28202868 SegmentOffset) << "\n");
28212869 break;
28222870 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
2871 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2872 true);
2873 if (error) {
2874 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
2875 Twine(error) + " for opcode at: 0x" +
2876 utohexstr(OpcodeStart - Opcodes.begin()));
2877 moveToEnd();
2878 return;
2879 }
28232880 SegmentOffset += ImmValue * PointerSize;
2881 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2882 false);
2883 if (error) {
2884 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
2885 " (after adding immediate times the pointer size) " +
2886 Twine(error) + " for opcode at: 0x" +
2887 utohexstr(OpcodeStart - Opcodes.begin()));
2888 moveToEnd();
2889 return;
2890 }
28242891 DEBUG_WITH_TYPE("mach-o-rebase",
28252892 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
28262893 << format("SegmentOffset=0x%06X",
28272894 SegmentOffset) << "\n");
28282895 break;
28292896 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
2897 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2898 true);
2899 if (error) {
2900 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
2901 Twine(error) + " for opcode at: 0x" +
2902 utohexstr(OpcodeStart - Opcodes.begin()));
2903 moveToEnd();
2904 return;
2905 }
28302906 AdvanceAmount = PointerSize;
2831 RemainingLoopCount = ImmValue - 1;
2907 Skip = 0;
2908 Count = ImmValue;
2909 if (ImmValue != 0)
2910 RemainingLoopCount = ImmValue - 1;
2911 else
2912 RemainingLoopCount = 0;
2913 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
2914 SegmentIndex, SegmentOffset);
2915 if (error) {
2916 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES "
2917 + Twine(error) + " for opcode at: 0x" +
2918 utohexstr(OpcodeStart - Opcodes.begin()));
2919 moveToEnd();
2920 return;
2921 }
28322922 DEBUG_WITH_TYPE(
28332923 "mach-o-rebase",
28342924 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
28382928 << "\n");
28392929 return;
28402930 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
2931 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2932 true);
2933 if (error) {
2934 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
2935 Twine(error) + " for opcode at: 0x" +
2936 utohexstr(OpcodeStart - Opcodes.begin()));
2937 moveToEnd();
2938 return;
2939 }
28412940 AdvanceAmount = PointerSize;
2842 RemainingLoopCount = readULEB128() - 1;
2941 Skip = 0;
2942 Count = readULEB128(&error);
2943 if (error) {
2944 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
2945 Twine(error) + " for opcode at: 0x" +
2946 utohexstr(OpcodeStart - Opcodes.begin()));
2947 moveToEnd();
2948 return;
2949 }
2950 if (Count != 0)
2951 RemainingLoopCount = Count - 1;
2952 else
2953 RemainingLoopCount = 0;
2954 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
2955 SegmentIndex, SegmentOffset);
2956 if (error) {
2957 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES "
2958 + Twine(error) + " for opcode at: 0x" +
2959 utohexstr(OpcodeStart - Opcodes.begin()));
2960 moveToEnd();
2961 return;
2962 }
28432963 DEBUG_WITH_TYPE(
28442964 "mach-o-rebase",
28452965 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
28492969 << "\n");
28502970 return;
28512971 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
2852 AdvanceAmount = readULEB128() + PointerSize;
2972 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
2973 true);
2974 if (error) {
2975 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
2976 Twine(error) + " for opcode at: 0x" +
2977 utohexstr(OpcodeStart - Opcodes.begin()));
2978 moveToEnd();
2979 return;
2980 }
2981 Skip = readULEB128(&error);
2982 if (error) {
2983 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
2984 Twine(error) + " for opcode at: 0x" +
2985 utohexstr(OpcodeStart - Opcodes.begin()));
2986 moveToEnd();
2987 return;
2988 }
2989 AdvanceAmount = Skip + PointerSize;
2990 Count = 1;
28532991 RemainingLoopCount = 0;
2992 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
2993 SegmentIndex, SegmentOffset);
2994 if (error) {
2995 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB "
2996 + Twine(error) + " for opcode at: 0x" +
2997 utohexstr(OpcodeStart - Opcodes.begin()));
2998 moveToEnd();
2999 return;
3000 }
28543001 DEBUG_WITH_TYPE(
28553002 "mach-o-rebase",
28563003 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
28603007 << "\n");
28613008 return;
28623009 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
2863 RemainingLoopCount = readULEB128() - 1;
2864 AdvanceAmount = readULEB128() + PointerSize;
3010 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3011 true);
3012 if (error) {
3013 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3014 "ULEB " + Twine(error) + " for opcode at: 0x" +
3015 utohexstr(OpcodeStart - Opcodes.begin()));
3016 moveToEnd();
3017 return;
3018 }
3019 Count = readULEB128(&error);
3020 if (error) {
3021 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3022 "ULEB " + Twine(error) + " for opcode at: 0x" +
3023 utohexstr(OpcodeStart - Opcodes.begin()));
3024 moveToEnd();
3025 return;
3026 }
3027 if (Count != 0)
3028 RemainingLoopCount = Count - 1;
3029 else
3030 RemainingLoopCount = 0;
3031 Skip = readULEB128(&error);
3032 if (error) {
3033 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3034 "ULEB " + Twine(error) + " for opcode at: 0x" +
3035 utohexstr(OpcodeStart - Opcodes.begin()));
3036 moveToEnd();
3037 return;
3038 }
3039 AdvanceAmount = Skip + PointerSize;
3040
3041 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3042 SegmentIndex, SegmentOffset);
3043 if (error) {
3044 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3045 "ULEB " + Twine(error) + " for opcode at: 0x" +
3046 utohexstr(OpcodeStart - Opcodes.begin()));
3047 moveToEnd();
3048 return;
3049 }
28653050 DEBUG_WITH_TYPE(
28663051 "mach-o-rebase",
28673052 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
28713056 << "\n");
28723057 return;
28733058 default:
2874 Malformed = true;
3059 *E = malformedError("bad rebase info (bad opcode value 0x" +
3060 utohexstr(Opcode) + " for opcode at: 0x" +
3061 utohexstr(OpcodeStart - Opcodes.begin()));
3062 moveToEnd();
3063 return;
28753064 }
28763065 }
28773066 }
28783067
2879 uint64_t MachORebaseEntry::readULEB128() {
3068 uint64_t MachORebaseEntry::readULEB128(const char **error) {
28803069 unsigned Count;
2881 uint64_t Result = decodeULEB128(Ptr, &Count);
3070 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
28823071 Ptr += Count;
2883 if (Ptr > Opcodes.end()) {
3072 if (Ptr > Opcodes.end())
28843073 Ptr = Opcodes.end();
2885 Malformed = true;
2886 }
28873074 return Result;
28883075 }
28893076
2890 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
3077 int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
28913078
28923079 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
28933080
29553142 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0),
29563143 SegmentIndex(-1), LibraryOrdinalSet(false), Ordinal(0), Flags(0),
29573144 Addend(0), RemainingLoopCount(0), AdvanceAmount(0), BindType(0),
2958 PointerSize(is64Bit ? 8 : 4), TableKind(BK), Malformed(false),
2959 Done(false) {}
3145 PointerSize(is64Bit ? 8 : 4), TableKind(BK), Done(false) {}
29603146
29613147 void MachOBindEntry::moveToFirst() {
29623148 Ptr = Opcodes.begin();
29773163 --RemainingLoopCount;
29783164 return;
29793165 }
2980 if (Ptr == Opcodes.end()) {
3166 if (Ptr >= Opcodes.end()) {
3167 if (Opcodes.begin() != Opcodes.end() && Done != true) {
3168 *E = malformedError("missing BIND_OPCODE_DONE at end of opcodes");
3169 moveToEnd();
3170 return;
3171 }
29813172 Done = true;
29823173 return;
29833174 }
29843175 bool More = true;
2985 while (More && !Malformed) {
3176 while (More) {
29863177 // Parse next opcode and set up next loop.
29873178 const uint8_t *OpcodeStart = Ptr;
29883179 uint8_t Byte = *Ptr++;
30073198 break;
30083199 }
30093200 More = false;
3010 Done = true;
30113201 moveToEnd();
30123202 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
30133203 break;
30143204 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
3205 if (TableKind == Kind::Weak) {
3206 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
3207 "weak bind table for opcode at: 0x" +
3208 utohexstr(OpcodeStart - Opcodes.begin()));
3209 moveToEnd();
3210 return;
3211 }
30153212 Ordinal = ImmValue;
30163213 LibraryOrdinalSet = true;
30173214 if (ImmValue > O->getLibraryCount()) {
30283225 << "Ordinal=" << Ordinal << "\n");
30293226 break;
30303227 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
3228 if (TableKind == Kind::Weak) {
3229 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3230 "weak bind table for opcode at: 0x" +
3231 utohexstr(OpcodeStart - Opcodes.begin()));
3232 moveToEnd();
3233 return;
3234 }
30313235 Ordinal = readULEB128(&error);
30323236 LibraryOrdinalSet = true;
30333237 if (error) {
30513255 << "Ordinal=" << Ordinal << "\n");
30523256 break;
30533257 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
3258 if (TableKind == Kind::Weak) {
3259 *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3260 "weak bind table for opcode at: 0x" +
3261 utohexstr(OpcodeStart - Opcodes.begin()));
3262 moveToEnd();
3263 return;
3264 }
30543265 if (ImmValue) {
30553266 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
30563267 Ordinal = SignExtended;
31173328 moveToEnd();
31183329 return;
31193330 }
3120 if (TableKind == Kind::Lazy)
3121 Malformed = true;
31223331 DEBUG_WITH_TYPE(
31233332 "mach-o-bind",
31243333 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
32013410 SegmentOffset) << "\n");
32023411 return;
32033412 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
3413 if (TableKind == Kind::Lazy) {
3414 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
3415 "lazy bind table for opcode at: 0x" +
3416 utohexstr(OpcodeStart - Opcodes.begin()));
3417 moveToEnd();
3418 return;
3419 }
32043420 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
32053421 if (error) {
32063422 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
32443460 return;
32453461 }
32463462 RemainingLoopCount = 0;
3247 if (TableKind == Kind::Lazy)
3248 Malformed = true;
32493463 DEBUG_WITH_TYPE(
32503464 "mach-o-bind",
32513465 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
32553469 << "\n");
32563470 return;
32573471 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
3472 if (TableKind == Kind::Lazy) {
3473 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
3474 "allowed in lazy bind table for opcode at: 0x" +
3475 utohexstr(OpcodeStart - Opcodes.begin()));
3476 moveToEnd();
3477 return;
3478 }
32583479 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
32593480 if (error) {
32603481 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
32893510 moveToEnd();
32903511 return;
32913512 }
3292 if (TableKind == Kind::Lazy)
3293 Malformed = true;
32943513 DEBUG_WITH_TYPE("mach-o-bind",
32953514 llvm::dbgs()
32963515 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
32983517 SegmentOffset) << "\n");
32993518 return;
33003519 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
3520 if (TableKind == Kind::Lazy) {
3521 *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
3522 "allowed in lazy bind table for opcode at: 0x" +
3523 utohexstr(OpcodeStart - Opcodes.begin()));
3524 moveToEnd();
3525 return;
3526 }
33013527 Count = readULEB128(&error);
33023528 if (Count != 0)
33033529 RemainingLoopCount = Count - 1;
33503576 moveToEnd();
33513577 return;
33523578 }
3353 if (TableKind == Kind::Lazy)
3354 Malformed = true;
33553579 DEBUG_WITH_TYPE(
33563580 "mach-o-bind",
33573581 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
33613585 << "\n");
33623586 return;
33633587 default:
3364 Malformed = true;
33653588 *E = malformedError("bad bind info (bad opcode value 0x" +
33663589 utohexstr(Opcode) + " for opcode at: 0x" +
33673590 utohexstr(OpcodeStart - Opcodes.begin()));
33753598 unsigned Count;
33763599 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
33773600 Ptr += Count;
3378 if (Ptr > Opcodes.end()) {
3601 if (Ptr > Opcodes.end())
33793602 Ptr = Opcodes.end();
3380 Malformed = true;
3381 }
33823603 return Result;
33833604 }
33843605
33863607 unsigned Count;
33873608 int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
33883609 Ptr += Count;
3389 if (Ptr > Opcodes.end()) {
3610 if (Ptr > Opcodes.end())
33903611 Ptr = Opcodes.end();
3391 Malformed = true;
3392 }
33933612 return Result;
33943613 }
33953614
34723691 }
34733692
34743693 // For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
3475 // validate a MachOBindEntry.
3694 // validate a MachOBindEntry or MachORebaseEntry.
34763695 const char * BindRebaseSegInfo::checkSegAndOffset(int32_t SegIndex,
34773696 uint64_t SegOffset,
34783697 bool endInvalid) {
34793698 if (SegIndex == -1)
3480 return "missing preceding BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
3699 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
34813700 if (SegIndex >= MaxSegIndex)
34823701 return "bad segIndex (too large)";
34833702 for (const SectionInfo &SI : Sections) {
34953714 }
34963715
34973716 // For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
3498 // the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode. The SegIndex
3499 // and SegOffset must have been already checked.
3717 // the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode and for use in
3718 // MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
3719 // REBASE_OPCODE_DO_*_TIMES* opcodes. The SegIndex and SegOffset must have
3720 // been already checked.
35003721 const char * BindRebaseSegInfo::checkCountAndSkip(uint32_t Count, uint32_t Skip,
35013722 uint8_t PointerSize,
3502 int32_t SegIndex,
3503 uint64_t SegOffset) {
3723 int32_t SegIndex,
3724 uint64_t SegOffset) {
35043725 const SectionInfo &SI = findSection(SegIndex, SegOffset);
35053726 uint64_t addr = SI.SegmentStartAddress + SegOffset;
35063727 if (addr >= SI.Address + SI.Size)
35083729 uint64_t i = 0;
35093730 if (Count > 1)
35103731 i = (Skip + PointerSize) * (Count - 1);
3511 if (addr + i >= SI.Address + SI.Size)
3512 return "bad count and skip, too large";
3732 else if (Count == 1)
3733 i = Skip + PointerSize;
3734 if (addr + i >= SI.Address + SI.Size) {
3735 // For rebase opcodes they can step from one section to another.
3736 uint64_t TrailingSegOffset = (addr + i) - SI.SegmentStartAddress;
3737 const char *error = checkSegAndOffset(SegIndex, TrailingSegOffset, false);
3738 if (error)
3739 return "bad count and skip, too large";
3740 }
35133741 return nullptr;
35143742 }
35153743
2828 ADD_ADDR_ULEB: macho-bind-add_addr_uleb': truncated or malformed object (for BIND_OPCODE_ADD_ADDR_ULEB bad segOffset, too large for opcode at: 0x17)
2929
3030 RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-do-bind-no-segIndex 2>&1 | FileCheck -check-prefix BIND-NO-SEGINDEX %s
31 BIND-NO-SEGINDEX: macho-bind-do-bind-no-segIndex': truncated or malformed object (for BIND_OPCODE_DO_BIND missing preceding BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB for opcode at: 0x15)
31 BIND-NO-SEGINDEX: macho-bind-do-bind-no-segIndex': truncated or malformed object (for BIND_OPCODE_DO_BIND missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB for opcode at: 0x15)
3232
3333 RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-bind-add-addr-uleb 2>&1 | FileCheck -check-prefix ADD-ADDR-ULEB %s
3434 ADD-ADDR-ULEB: macho-bind-bind-add-addr-uleb': truncated or malformed object (for BIND_OPCODE_ADD_ADDR_ULEB (after adding ULEB) bad segOffset, too large for opcode at: 0x18)
4747
4848 RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-bad-opcode-value 2>&1 | FileCheck -check-prefix BAD-OPCODE-VALUE %s
4949 BAD-OPCODE-VALUE: macho-bind-bad-opcode-value': truncated or malformed object (bad bind info (bad opcode value 0xD0 for opcode at: 0x18)
50
51 RUN: not llvm-objdump -macho -lazy-bind %p/Inputs/macho-lazy-do_bind_add_addr_uleb 2>&1 | FileCheck -check-prefix LAZY_DO_BIND_ADD_ADDR_ULEB %s
52 LAZY_DO_BIND_ADD_ADDR_ULEB: macho-lazy-do_bind_add_addr_uleb': truncated or malformed object (BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in lazy bind table for opcode at: 0xC)
53
54 RUN: not llvm-objdump -macho -lazy-bind %p/Inputs/macho-lazy-do-bind-add-addr-imm-scaled 2>&1 | FileCheck -check-prefix LAZY-DO-BIND-ADD-ADDR-IMM-SCALED %s
55 LAZY-DO-BIND-ADD-ADDR-IMM-SCALED: macho-lazy-do-bind-add-addr-imm-scaled': truncated or malformed object (BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not allowed in lazy bind table for opcode at: 0xC)
56
57 RUN: not llvm-objdump -macho -lazy-bind %p/Inputs/macho-lazy-do-bind-uleb-times-skipping-uleb 2>&1 | FileCheck -check-prefix LAZY-DO-BIND-ULEB-TIMES-SKIPPING-ULEB %s
58 LAZY-DO-BIND-ULEB-TIMES-SKIPPING-ULEB: macho-lazy-do-bind-uleb-times-skipping-uleb': truncated or malformed object (BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not allowed in lazy bind table for opcode at: 0xC)
59
60 RUN: not llvm-objdump -macho -weak-bind %p/Inputs/macho-weak-bind-set-dylib-ordinal-imm 2>&1 | FileCheck -check-prefix WEAK-BIND-SET-DYLIB-ORDINAL-IMM %s
61 WEAK-BIND-SET-DYLIB-ORDINAL-IMM: macho-weak-bind-set-dylib-ordinal-imm': truncated or malformed object (BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in weak bind table for opcode at: 0x2)
62
63 RUN: not llvm-objdump -macho -weak-bind %p/Inputs/macho-weak-bind-set-dylib-ordinal-uleb 2>&1 | FileCheck -check-prefix WEAK-BIND-SET-DYLIB-ORDINAL-ULEB %s
64 WEAK-BIND-SET-DYLIB-ORDINAL-ULEB: macho-weak-bind-set-dylib-ordinal-uleb': truncated or malformed object (BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in weak bind table for opcode at: 0x2)
65
66 RUN: not llvm-objdump -macho -weak-bind %p/Inputs/macho-weak-bind-set-dylib-special-imm 2>&1 | FileCheck -check-prefix WEAK-BIND-SET-DYLIB-SPECIAL-IMM %s
67 WEAK-BIND-SET-DYLIB-SPECIAL-IMM: macho-weak-bind-set-dylib-special-imm': truncated or malformed object (BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in weak bind table for opcode at: 0x2)
68
69 RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-missing-done 2>&1 | FileCheck -check-prefix BIND-MISSING-DONE %s
70 BIND-MISSING-DONE: macho-bind-missing-done': truncated or malformed object (missing BIND_OPCODE_DONE at end of opcodes)
71
72 RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-set-type-imm 2>&1 | FileCheck -check-prefix REBASE-SET-TYPE-IMM %s
73 REBASE-SET-TYPE-IMM: macho-rebase-set-type-imm': truncated or malformed object (for REBASE_OPCODE_SET_TYPE_IMM bad bind type: 5 for opcode at: 0x0)
74
75 RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-uleb-malformed-uleb128 2>&1 | FileCheck -check-prefix REBASE-ULEB-MALFORMED-ULEB128 %s
76 REBASE-ULEB-MALFORMED-ULEB128: macho-rebase-uleb-malformed-uleb128': truncated or malformed object (for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB malformed uleb128, extends past end for opcode at: 0x1)
77
78 RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-seg-too-big 2>&1 | FileCheck -check-prefix REBASE-SEG-TOO-BIG %s
79 REBASE-SEG-TOO-BIG: macho-rebase-seg-too-big': truncated or malformed object (for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB bad segIndex (too large) for opcode at: 0x1)
80
81 RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-segoff-too-big 2>&1 | FileCheck -check-prefix REBASE-SEGOFF-TOO-BIG %s
82 REBASE-SEGOFF-TOO-BIG: macho-rebase-segoff-too-big': truncated or malformed object (for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB bad segOffset, too large for opcode at: 0x1)
83
84 RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-add-addr-uleb 2>&1 | FileCheck -check-prefix REBASE-ADD-ADDR-ULEB %s
85 REBASE-ADD-ADDR-ULEB: macho-rebase-add-addr-uleb': truncated or malformed object (for REBASE_OPCODE_ADD_ADDR_ULEB bad segOffset, too large for opcode at: 0x3)
86
87 RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-add-addr-imm-scaled 2>&1 | FileCheck -check-prefix REBASE-ADD-ADDR-IMM-SCALED %s
88 REBASE-ADD-ADDR-IMM-SCALED: macho-rebase-add-addr-imm-scaled': truncated or malformed object (for REBASE_OPCODE_ADD_ADDR_IMM_SCALED (after adding immediate times the pointer size) bad segOffset, too large for opcode at: 0x3)
89
90 RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-imm-times 2>&1 | FileCheck -check-prefix REBASE-IMM-TIMES %s
91 REBASE-IMM-TIMES: macho-rebase-imm-times': truncated or malformed object (for REBASE_OPCODE_DO_REBASE_IMM_TIMES bad count and skip, too large for opcode at: 0x3)
92
93 RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-uleb-times 2>&1 | FileCheck -check-prefix REBASE-ULEB-TIMES %s
94 REBASE-ULEB-TIMES: macho-rebase-uleb-times': truncated or malformed object (for REBASE_OPCODE_DO_REBASE_ULEB_TIMES bad count and skip, too large for opcode at: 0x3)
95
96 RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-add-addr-uleb-too-big 2>&1 | FileCheck -check-prefix REBASE-ADD-ADDR-ULEB-TOO-BIG %s
97 REBASE-ADD-ADDR-ULEB-TOO-BIG: macho-rebase-add-addr-uleb-too-big': truncated or malformed object (for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB bad count and skip, too large for opcode at: 0x3)
98
99 RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-uleb-times-skipping-uleb 2>&1 | FileCheck -check-prefix REBASE-ULEB-TIMES-SKIPPING-ULEB %s
100 REBASE-ULEB-TIMES-SKIPPING-ULEB: macho-rebase-uleb-times-skipping-uleb': truncated or malformed object (for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB bad count and skip, too large for opcode at: 0x3)
101
102 RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-bad-opcode-value 2>&1 | FileCheck -check-prefix REBASE-BAD-OPCODE-VALUE %s
103 REBASE-BAD-OPCODE-VALUE: macho-rebase-bad-opcode-value': truncated or malformed object (bad rebase info (bad opcode value 0xD0 for opcode at: 0x4)
104
105 RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-missing-done 2>&1 | FileCheck -check-prefix REBASE-MISSING-DONE %s
106 REBASE-MISSING-DONE: macho-rebase-missing-done': truncated or malformed object (missing REBASE_OPCODE_DONE at end of opcodes)