| 2959 | } |
| 2960 | |
| 2961 | virtual bool ApplyRelocation(Ref<BinaryView> view, Ref<Architecture> arch, Ref<Relocation> reloc, uint8_t* dest, size_t len) override |
| 2962 | { |
| 2963 | if (len < 4) |
| 2964 | return false; |
| 2965 | |
| 2966 | auto info = reloc->GetInfo(); |
| 2967 | auto addr = reloc->GetAddress(); |
| 2968 | auto symbol = reloc->GetSymbol(); |
| 2969 | uint64_t target = reloc->GetTarget() + info.addend; |
| 2970 | |
| 2971 | int32_t gpAddr = 0; |
| 2972 | uint64_t* dest64 = (uint64_t*)dest; |
| 2973 | uint32_t* dest32 = (uint32_t*)dest; |
| 2974 | auto swap = [&arch](uint32_t x) { return (arch->GetEndianness() == LittleEndian) ? x : bswap32(x); }; |
| 2975 | auto swap64 = [&arch](uint64_t x) { return (arch->GetEndianness() == LittleEndian) ? x : bswap64(x); }; |
| 2976 | uint32_t inst = swap(dest32[0]); |
| 2977 | uint64_t inst64 = swap64(dest64[0]); |
| 2978 | |
| 2979 | switch (info.nativeType) |
| 2980 | { |
| 2981 | case R_MIPS_JUMP_SLOT: |
| 2982 | case R_MIPS_COPY: |
| 2983 | dest32[0] = swap((uint32_t)target); |
| 2984 | break; |
| 2985 | case R_MIPS64_COPY: |
| 2986 | dest64[0] = swap64(target); |
| 2987 | break; |
| 2988 | case R_MIPS_32: |
| 2989 | dest32[0] = swap((uint32_t)(inst + target)); |
| 2990 | break; |
| 2991 | case R_MIPS_64: |
| 2992 | dest64[0] = swap64(inst64 + target); |
| 2993 | break; |
| 2994 | case R_MIPS_HIGHEST: |
| 2995 | { |
| 2996 | dest64[0] = swap64(inst64 & 0xffff0000ffffffff) | (((target + 0x800080008000) >> 16) & 0xffff00000000 ); |
| 2997 | break; |
| 2998 | } |
| 2999 | case R_MIPS_HIGHER: |
| 3000 | { |
| 3001 | dest64[0] = swap64(inst64 & 0xffff0000ffffffff) | (((target + 0x80008000)) & 0xffff00000000 ); |
| 3002 | break; |
| 3003 | } |
| 3004 | case R_MIPS_HI16: |
| 3005 | { |
| 3006 | // Find the first _LO16 in the list of relocations |
| 3007 | BNRelocationInfo* cur = info.next; |
| 3008 | while (cur && (cur->nativeType != R_MIPS_LO16)) |
| 3009 | cur = cur->next; |
| 3010 | |
| 3011 | if (cur) |
| 3012 | { |
| 3013 | uint32_t inst2 = *(uint32_t*)(cur->relocationDataCache); |
| 3014 | Instruction instruction; |
| 3015 | memset(&instruction, 0, sizeof(instruction)); |
| 3016 | if (mips_decompose(&inst2, sizeof(uint32_t), &instruction, arch->GetAddressSize() == 8 ? MIPS_64 : MIPS_32, cur->address, arch->GetEndianness(), DECOMPOSE_FLAGS_PSEUDO_OP)) |
| 3017 | break; |
| 3018 |
nothing calls this directly
no test coverage detected