| 2253 | { |
| 2254 | public: |
| 2255 | virtual bool ApplyRelocation(Ref<BinaryView> view, Ref<Architecture> arch, Ref<Relocation> reloc, uint8_t* dest, size_t len) override |
| 2256 | { |
| 2257 | (void)view; |
| 2258 | BNRelocationInfo info = reloc->GetInfo(); |
| 2259 | if (len < info.size) |
| 2260 | return false; |
| 2261 | Ref<Symbol> sym = reloc->GetSymbol(); |
| 2262 | uint32_t target = (uint32_t)reloc->GetTarget(); |
| 2263 | uint32_t* dest32 = (uint32_t*)dest; |
| 2264 | |
| 2265 | auto swap = [&arch](uint32_t x) { return (arch->GetEndianness() == LittleEndian)? x : bswap32(x); }; |
| 2266 | switch (info.nativeType) |
| 2267 | { |
| 2268 | case R_ARM_COPY: |
| 2269 | case R_ARM_GLOB_DAT: |
| 2270 | case R_ARM_JUMP_SLOT: |
| 2271 | case R_ARM_BASE_PREL: |
| 2272 | case R_ARM_GOT_BREL: |
| 2273 | dest32[0] = swap(target); |
| 2274 | break; |
| 2275 | case R_ARM_RELATIVE: |
| 2276 | case R_ARM_ABS32: |
| 2277 | dest32[0] = swap(swap(dest32[0]) + target); |
| 2278 | break; |
| 2279 | case R_ARM_REL32: |
| 2280 | dest32[0] = swap((uint32_t)((target + (info.implicitAddend ? swap(dest32[0]) : info.addend)) - reloc->GetAddress())); |
| 2281 | break; |
| 2282 | case R_ARM_CALL: |
| 2283 | { |
| 2284 | if (target & 1) |
| 2285 | { |
| 2286 | LogError("Unsupported relocation R_ARM_CALL to thumb target"); |
| 2287 | break; |
| 2288 | } |
| 2289 | struct _bl { |
| 2290 | int32_t imm:24; |
| 2291 | uint32_t group1:4; |
| 2292 | uint32_t cond:4; |
| 2293 | }; |
| 2294 | _bl* bl = (_bl*) dest32; |
| 2295 | int64_t newTarget = (target + (info.implicitAddend ? ((bl->imm << 2) + 8) : info.addend)) - reloc->GetAddress(); |
| 2296 | if ((newTarget - 8) > 0x3ffffff) |
| 2297 | { |
| 2298 | LogError("Unsupported relocation R_ARM_CALL @ 0x%" PRIx64 " with target greater than 0x3ffffff: 0x%" PRIx64, reloc->GetAddress(), newTarget - 8); |
| 2299 | break; |
| 2300 | } |
| 2301 | bl->imm = (newTarget - 8) >> 2; |
| 2302 | break; |
| 2303 | } |
| 2304 | case R_ARM_THM_CALL: |
| 2305 | case R_ARM_THM_JUMP24: |
| 2306 | { |
| 2307 | // TODO: not portable |
| 2308 | #pragma pack(push, 1) |
| 2309 | union _thumb32_bl_hw1 { |
| 2310 | uint16_t word; |
| 2311 | struct { |
| 2312 | uint16_t offHi:10; // 21-12 |
nothing calls this directly
no test coverage detected