mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-23 22:59:04 +08:00
Merge remote-tracking branch 'origin/GP-5154_ARM_AARCH64_coff_relocations--SQUASHED'
This commit is contained in:
+197
@@ -0,0 +1,197 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.util.bin.formatt.coff.relocation;
|
||||
|
||||
import ghidra.app.util.bin.format.RelocationException;
|
||||
import ghidra.app.util.bin.format.coff.*;
|
||||
import ghidra.app.util.bin.format.coff.relocation.CoffRelocationContext;
|
||||
import ghidra.app.util.bin.format.coff.relocation.CoffRelocationHandler;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.reloc.Relocation.Status;
|
||||
import ghidra.program.model.reloc.RelocationResult;
|
||||
|
||||
public class AARCH64_CoffRelocationHandler implements CoffRelocationHandler {
|
||||
|
||||
/**
|
||||
* Relocation is ignored
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_ABSOLUTE = 0x0000;
|
||||
|
||||
/**
|
||||
* Target's 32-bit VA
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_ADDR32 = 0x0001;
|
||||
|
||||
|
||||
/**
|
||||
* Target's 32-bit RVA
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_ADDR32NB = 0x0002;
|
||||
|
||||
/**
|
||||
* 26-bit relative displacement to target (for b and bl instructions)
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_BRANCH26 = 0x0003;
|
||||
|
||||
/**
|
||||
* Page base of target (for adrp instruction)
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_PAGEBASE_REL21 = 0x0004;
|
||||
|
||||
|
||||
/**
|
||||
* 12-bit relative displacement to target (for adr instruction)
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_REL21 = 0x0005;
|
||||
|
||||
/**
|
||||
* 12-bit page offset of target (for add/adds(immed) with shift of 0)
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_PAGEOFFSET_12A = 0x0006;
|
||||
|
||||
/**
|
||||
* 12-bit page offset of target for (ldr indexed, unsigned immediate)
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_PAGEOFFSET_12L = 0x0007;
|
||||
|
||||
/**
|
||||
* 32-bit offset of target from beginning of its section (for debugging and static tls)
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_SECREL = 0x0008;
|
||||
|
||||
/**
|
||||
* bits 0:11 of target's section offset (for add/adds (immed) with shift of 0)
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_SECREL_LOW12A = 0x0009;
|
||||
|
||||
/**
|
||||
* bits 12:23 of target's section offset (for add/adds (immed) with shift of 0)
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_SECREL_HIGH12A = 0x000A;
|
||||
|
||||
/**
|
||||
* bits 0:11 of target's section offset (for ldr, indexed, unsigned immediate)
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_SECREL_LOW12L = 0x000B;
|
||||
|
||||
/**
|
||||
* clr token
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_TOKEN = 0x000C;
|
||||
|
||||
/**
|
||||
* 16-bit section index of target's section (for debugging)
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_SECTION = 0x000D;
|
||||
|
||||
/**
|
||||
* 64-bit VA of target
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_ADDR64 = 0x000E;
|
||||
|
||||
/**
|
||||
* 19-bit offset to target (for conditional b instruction)
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_BRANCH19 = 0x000F;
|
||||
|
||||
/**
|
||||
* 14-bit offset to target (for tbz and tbnz instructions)
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_BRANCH14 = 0x0010;
|
||||
|
||||
/**
|
||||
* 32-bit relative address from byte following relocation
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM64_REL32 = 0x0011;
|
||||
|
||||
@Override
|
||||
public boolean canRelocate(CoffFileHeader fileHeader) {
|
||||
return fileHeader.getMachine() == CoffMachineType.IMAGE_FILE_MACHINE_ARM64;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelocationResult relocate(Address address, CoffRelocation relocation,
|
||||
CoffRelocationContext relocationContext)
|
||||
throws MemoryAccessException, RelocationException {
|
||||
|
||||
Program program = relocationContext.getProgram();
|
||||
Memory mem = program.getMemory();
|
||||
|
||||
int byteLength = 4; // most relocations affect 4-bytes (change if different)
|
||||
|
||||
int bytesToAdjust = mem.getInt(address);
|
||||
Address symbolAddr = relocationContext.getSymbolAddress(relocation);
|
||||
switch (relocation.getType()) {
|
||||
|
||||
case IMAGE_REL_ARM64_ABSOLUTE:
|
||||
return RelocationResult.SKIPPED;
|
||||
|
||||
case IMAGE_REL_ARM64_ADDR32NB:
|
||||
mem.setInt(address, (int) symbolAddr.getOffset());
|
||||
break;
|
||||
|
||||
case IMAGE_REL_ARM64_BRANCH26:
|
||||
int instMask = 0xfc000000;
|
||||
bytesToAdjust = bytesToAdjust & instMask;
|
||||
int displacement = (int) symbolAddr.subtract(address);
|
||||
displacement >>= 2;
|
||||
displacement &= (~instMask);
|
||||
bytesToAdjust = bytesToAdjust | displacement;
|
||||
mem.setInt(address, bytesToAdjust);
|
||||
break;
|
||||
|
||||
case IMAGE_REL_ARM64_PAGEBASE_REL21:
|
||||
long base = address.getOffset() & ~0xfff;
|
||||
long offset = symbolAddr.getOffset() - base;
|
||||
offset = offset >> 12;
|
||||
int immlo = (int) offset & 0x3;
|
||||
offset = offset >> 2;
|
||||
int immhi = (int) offset & 0x7ffff;
|
||||
instMask = ~((0x3 << 29) | (0x7ffff << 5));
|
||||
bytesToAdjust &= instMask;
|
||||
bytesToAdjust = bytesToAdjust | (immhi << 5) | (immlo << 29);
|
||||
mem.setInt(address, bytesToAdjust);
|
||||
break;
|
||||
|
||||
case IMAGE_REL_ARM64_PAGEOFFSET_12A:
|
||||
offset = symbolAddr.getOffset() & 0xfff;
|
||||
instMask = ~(0xfff << 10);
|
||||
bytesToAdjust &= instMask;
|
||||
bytesToAdjust = (int) (bytesToAdjust | (offset << 10));
|
||||
mem.setInt(address, bytesToAdjust);
|
||||
break;
|
||||
|
||||
case IMAGE_REL_ARM64_PAGEOFFSET_12L:
|
||||
int size = bytesToAdjust >>> 30;
|
||||
offset = symbolAddr.getOffset() & 0xfff;
|
||||
offset >>= size;
|
||||
instMask = ~(0xfff << 10);
|
||||
bytesToAdjust &= instMask;
|
||||
bytesToAdjust = (int) (bytesToAdjust | (offset << 10));
|
||||
mem.setInt(address, bytesToAdjust);
|
||||
break;
|
||||
|
||||
default: {
|
||||
return RelocationResult.UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
return new RelocationResult(Status.APPLIED, byteLength);
|
||||
}
|
||||
|
||||
}
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.util.bin.format.coff.relocation;
|
||||
|
||||
import ghidra.app.util.bin.format.RelocationException;
|
||||
import ghidra.app.util.bin.format.coff.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.reloc.Relocation.Status;
|
||||
import ghidra.program.model.reloc.RelocationResult;
|
||||
|
||||
public class ARM_CoffRelocationHandler implements CoffRelocationHandler {
|
||||
|
||||
/**
|
||||
* The relocation is ignored.
|
||||
*/
|
||||
public final static short IMAGE_REL_ARM_ABSOLUTE = 0x0000;
|
||||
|
||||
/**
|
||||
* 32-bit VA of target
|
||||
*/
|
||||
public final static short IMAGE_REL_ARM_ADDR32 = 0x0001;
|
||||
|
||||
/**
|
||||
* 32-bit RVA of target
|
||||
*/
|
||||
public final static short IMAGE_REL_ARM_ADDR32NB = 0x0002;
|
||||
|
||||
/**
|
||||
* 24-bit relative displacement to target
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM_BRANCH24 = 0x0003;
|
||||
|
||||
/**
|
||||
* Reference to subroutine call. Two 16-bit instructions with 11-bit offsets.
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM_BRANCH11 = 0x0004;
|
||||
|
||||
/**
|
||||
* 32-bit relative address from byte following relocation
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM_REL32 = 0x000a;
|
||||
|
||||
/**
|
||||
* 16-bit section index of section containing target (for debugging)
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM_SECTION = 0x000e;
|
||||
|
||||
/**
|
||||
* 32-it offset of target from beginning of sections. For debugging
|
||||
* and static TLS
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM_SECREL = 0x000f;
|
||||
|
||||
/**
|
||||
* 32-bit VA of target (MOVW for low 16 bits; MOVT for high 16 bits)
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM_MOV32 = 0x0010;
|
||||
|
||||
/**
|
||||
* 32-bit VA of target (MOVW for low 16 bits; MOVT for high 16 bits)
|
||||
*/
|
||||
public static final short IMAGE_REL_THUMB_MOV32 = 0x0011;
|
||||
|
||||
/**
|
||||
* Instruction fixed up with 21-bit relative displace to target
|
||||
* (which is 2-byte aligned).
|
||||
*/
|
||||
public static final short IMAGE_REL_THUMB_BRANCH20 = 0x0012;
|
||||
|
||||
// 0x0013 unused
|
||||
|
||||
/**
|
||||
* Instruction fixed up with 25-bit relative displacement to target
|
||||
* (which is 2-byte aligned)
|
||||
*/
|
||||
public static final short IMAGE_REL_THUMB_BRANCH24 = 0x0014;
|
||||
|
||||
/**
|
||||
* Instruction fixed up with the 25-bit relative displacement to target
|
||||
* (which is 4-byte aligned)
|
||||
*/
|
||||
public static final short IMAGE_REL_THUMB_BLX23 = 0x0015;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static final short IMAGE_REL_ARM_PAIR = 0x0016;
|
||||
|
||||
@Override
|
||||
public boolean canRelocate(CoffFileHeader fileHeader) {
|
||||
switch (fileHeader.getMachine()) {
|
||||
case CoffMachineType.IMAGE_FILE_MACHINE_ARM:
|
||||
case CoffMachineType.IMAGE_FILE_MACHINE_ARMNT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelocationResult relocate(Address address, CoffRelocation relocation,
|
||||
CoffRelocationContext relocationContext)
|
||||
throws MemoryAccessException, RelocationException {
|
||||
|
||||
Program program = relocationContext.getProgram();
|
||||
Memory mem = program.getMemory();
|
||||
|
||||
int byteLength = 4; // most relocations affect 4-bytes (change if different)
|
||||
|
||||
int bytesToAdjust = mem.getInt(address);
|
||||
Address symbolAddr = relocationContext.getSymbolAddress(relocation);
|
||||
switch (relocation.getType()) {
|
||||
|
||||
case IMAGE_REL_ARM_ABSOLUTE:
|
||||
return RelocationResult.SKIPPED;
|
||||
|
||||
case IMAGE_REL_ARM_ADDR32:
|
||||
mem.setInt(address, (int) symbolAddr.getOffset());
|
||||
break;
|
||||
|
||||
case IMAGE_REL_ARM_ADDR32NB:
|
||||
mem.setInt(address, (int) symbolAddr.getOffset());
|
||||
break;
|
||||
|
||||
case IMAGE_REL_THUMB_MOV32:
|
||||
int symAddress = (int) symbolAddr.getOffset();
|
||||
long highImmed16 = getImmed16(symAddress >> 16);
|
||||
long lowImmed16 = getImmed16(symAddress & 0xffff);
|
||||
long longBytesToAdjust = mem.getLong(address);
|
||||
longBytesToAdjust = longBytesToAdjust | (highImmed16 << 32) | lowImmed16;
|
||||
byteLength = 8;
|
||||
mem.setLong(address, longBytesToAdjust);
|
||||
break;
|
||||
|
||||
case IMAGE_REL_THUMB_BRANCH24:
|
||||
int displacement = (int) symbolAddr.subtract(address) - 4;
|
||||
int adjustment = getThAddr24(displacement);
|
||||
bytesToAdjust = bytesToAdjust & 0xd000f800;
|
||||
int adjusted = bytesToAdjust | adjustment;
|
||||
mem.setInt(address, adjusted);
|
||||
break;
|
||||
|
||||
case IMAGE_REL_THUMB_BLX23:
|
||||
displacement = (int) symbolAddr.subtract(address) - 4;
|
||||
adjustment = getThAddr24(displacement);
|
||||
bytesToAdjust = bytesToAdjust & 0xd000f800;
|
||||
adjusted = bytesToAdjust | adjustment;
|
||||
mem.setInt(address, adjusted);
|
||||
break;
|
||||
|
||||
default: {
|
||||
return RelocationResult.UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
return new RelocationResult(Status.APPLIED, byteLength);
|
||||
}
|
||||
|
||||
private int getImmed16(int value) {
|
||||
// see Immed16 constructor in ARMTHUMBinstructions.sinc
|
||||
int immed12_imm8 = value & 0xff;
|
||||
int immed12_imm3 = (value >> 8) & 0x7;
|
||||
int immed12_i = (value >> 11) & 1;
|
||||
int sop003 = (value >> 12) & 0xf;
|
||||
return (immed12_imm3 << 28) | (immed12_imm8 << 16) | (immed12_i << 10) | sop003;
|
||||
}
|
||||
|
||||
private int getThAddr24(int displacement) {
|
||||
// see ThAddr25 constructors in ARMThumbinstructions.sinc
|
||||
int part2J1 = (displacement & (1 << 23)) >> 23;
|
||||
int part2J2 = (displacement & (1 << 22)) >> 22;
|
||||
int part2off = (displacement & (0x7ff << 1)) >> 1;
|
||||
int offset10 = (displacement & (0x3ff << 12)) >> 12;
|
||||
int offset10s = displacement < 0 ? 1 : 0;
|
||||
if (displacement >= 0) {
|
||||
part2J1 ^= 1;
|
||||
part2J2 ^= 1;
|
||||
}
|
||||
int adjustment =
|
||||
(part2J1 << (16 + 13)) | (part2J2 << (16 + 11)) | (part2off << 16) |
|
||||
(offset10s << 10) | offset10;
|
||||
return adjustment;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user