mirror of
https://github.com/Garhoogin/RuntimeCodeModules.git
synced 2025-06-19 17:05:34 -04:00
Add zero-value relocation optimization
etc
This commit is contained in:
parent
fbb8bd04f9
commit
988ef820ce
@ -11,6 +11,9 @@
|
||||
#define R_ARM_JUMP24 29
|
||||
#define R_ARM_BASE_ABS 31
|
||||
|
||||
#define R_TYPE_MASK 0x7F
|
||||
#define R_ZERO_VALUE 0x80
|
||||
|
||||
#define HOOK_TYPE_AREPL 0 //ARM branch-and-link replacement
|
||||
#define HOOK_TYPE_ANSUB 1 //ARM branch replacement
|
||||
#define HOOK_TYPE_TREPL 2 //thumb branch-link-exchange replacement
|
||||
@ -49,7 +52,7 @@ typedef struct HOOK_TABLE_ENTRY_ {
|
||||
typedef struct RELOCATION_ENTRY_ {
|
||||
u32 offset : 24; //offset of relocation
|
||||
u32 type : 8; //type of relocation
|
||||
u32 value; //value of relocation
|
||||
u32 value; //value of relocation (optional)
|
||||
} RELOCATION_ENTRY;
|
||||
|
||||
typedef struct RCM_HEADER_ {
|
||||
@ -67,14 +70,14 @@ typedef void (*RCM_LOAD_CALLBACK) (u32 imageBase);
|
||||
typedef void (*RCM_UNLOAD_CALLBACK) (u32 imageBase);
|
||||
|
||||
|
||||
#define HOOK_DATA8(addr,b) ((void *) ((HOOK_TYPE_DATA8 << HOOK_SHIFT) | (u32) (addr))), (void *) b
|
||||
#define HOOK_DATA16(addr,hw) ((void *) ((HOOK_TYPE_DATA16 << HOOK_SHIFT) | (u32) (addr))), (void *) hw
|
||||
#define HOOK_DATA32(addr,w) ((void *) ((HOOK_TYPE_DATA32 << HOOK_SHIFT) | (u32) (addr))), (void *) w
|
||||
#define HOOK_DATA8(addr,b) ((void *) ((HOOK_TYPE_DATA8 << HOOK_SHIFT) + (u32) (addr))), (void *) b
|
||||
#define HOOK_DATA16(addr,hw) ((void *) ((HOOK_TYPE_DATA16 << HOOK_SHIFT) + (u32) (addr))), (void *) hw
|
||||
#define HOOK_DATA32(addr,w) ((void *) ((HOOK_TYPE_DATA32 << HOOK_SHIFT) + (u32) (addr))), (void *) w
|
||||
#define HOOK_LOAD(dest) ((void *) ((HOOK_TYPE_LOAD << HOOK_SHIFT))), (void *) dest
|
||||
#define HOOK_UNLOAD(dest) ((void *) ((HOOK_TYPE_UNLOAD << HOOK_SHIFT))), (void *) dest
|
||||
#define HOOK_AREPL(addr,dest) ((void *) ((HOOK_TYPE_AREPL << HOOK_SHIFT) | (u32) (addr))), (void *) dest
|
||||
#define HOOK_ANSUB(addr,dest) ((void *) ((HOOK_TYPE_ANSUB << HOOK_SHIFT) | (u32) (addr))), (void *) dest
|
||||
#define HOOK_TREPL(addr,dest) ((void *) ((HOOK_TYPE_TREPL << HOOK_SHIFT) | (u32) (addr))), (void *) dest
|
||||
#define HOOK_AREPL(addr,dest) ((void *) ((HOOK_TYPE_AREPL << HOOK_SHIFT) + (u32) (addr))), (void *) dest
|
||||
#define HOOK_ANSUB(addr,dest) ((void *) ((HOOK_TYPE_ANSUB << HOOK_SHIFT) + (u32) (addr))), (void *) dest
|
||||
#define HOOK_TREPL(addr,dest) ((void *) ((HOOK_TYPE_TREPL << HOOK_SHIFT) + (u32) (addr))), (void *) dest
|
||||
#define HOOK_TNSUB(addr,dest) HOOK_DATA16(addr, 0xB500), HOOK_TREPL(((u32) (addr)) + 2, dest), HOOK_DATA16(((u32) (addr)) + 6, 0xBD00)
|
||||
|
||||
//NCP-like synonyms
|
||||
|
Binary file not shown.
@ -61,6 +61,21 @@ public class RCMRelocator {
|
||||
return getSymType(syms, sym) != null;
|
||||
}
|
||||
|
||||
public static int read32(byte[] b, int offset) {
|
||||
int b0 = ((int) b[offset + 0]) & 0xFF;
|
||||
int b1 = ((int) b[offset + 1]) & 0xFF;
|
||||
int b2 = ((int) b[offset + 2]) & 0xFF;
|
||||
int b3 = ((int) b[offset + 3]) & 0xFF;
|
||||
return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
|
||||
}
|
||||
|
||||
public static void write32(byte[] b, int offset, int n) {
|
||||
b[offset + 0] = (byte) ((n >>> 0) & 0xFF);
|
||||
b[offset + 1] = (byte) ((n >>> 8) & 0xFF);
|
||||
b[offset + 2] = (byte) ((n >>> 16) & 0xFF);
|
||||
b[offset + 3] = (byte) ((n >>> 24) & 0xFF);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
//read arguments. First RCM name, then relocation output from objdump, then symbol output
|
||||
//from objdump
|
||||
@ -115,6 +130,7 @@ public class RCMRelocator {
|
||||
byte[] rcm = Files.readAllBytes(Paths.get(rcmPath));
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); //relocation table
|
||||
ByteArrayOutputStream thunks = new ByteArrayOutputStream(); //thunks (for ARM->THUMB B)
|
||||
int nRelocations = 0;
|
||||
try {
|
||||
//before relocation output, count the number of times each destination address shows up.
|
||||
Map<Integer, Integer> refCounts = new HashMap<>();
|
||||
@ -146,7 +162,39 @@ public class RCMRelocator {
|
||||
boolean isAbs32 = r.type.equals("R_ARM_ABS32") && !isLocal;
|
||||
if(!(isThumb && isB) && !(isRelative && isLocal) && !isAbs32) {
|
||||
if(!(!isLocal && r.value == 0)) { //check external relocations for NULL
|
||||
|
||||
//let's get smart, try to arrange this so that we may emit a zero-value
|
||||
int type = Relocation.relocTypeFromString(r.type, r.local);
|
||||
int orig;
|
||||
switch (type) {
|
||||
case Relocation.R_ARM_BASE_ABS:
|
||||
case Relocation.R_ARM_ABS32:
|
||||
//we can add to the data in the file.
|
||||
orig = read32(rcm, r.offset);
|
||||
orig += r.value;
|
||||
write32(rcm, r.offset, orig);
|
||||
r.value -= r.value;
|
||||
break;
|
||||
case Relocation.R_ARM_JUMP24:
|
||||
case Relocation.R_ARM_CALL:
|
||||
if (isThumb) break; //unavoidable. Value must exist
|
||||
orig = read32(rcm, r.offset);
|
||||
int instr = orig;
|
||||
|
||||
//partial relocation; adjust value to 0, don't adjust by base
|
||||
int offset = (orig & 0x00FFFFFF) << 2;
|
||||
if ((offset & 0x02000000) != 0) offset -= 0x04000000;
|
||||
offset = ((offset + r.value) >> 2) & 0x00FFFFFF;
|
||||
orig = (instr & 0xFF000000) | offset;
|
||||
|
||||
write32(rcm, r.offset, orig);
|
||||
r.value -= r.value;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
baos.write(r.getBytes()); //write relocation as normal
|
||||
nRelocations++;
|
||||
} else {
|
||||
//external relocation points to NULL
|
||||
//probably means a symbol was not resolved, throw an error
|
||||
@ -246,7 +294,7 @@ public class RCMRelocator {
|
||||
|
||||
//write relocation data
|
||||
int ofsReloc = rcm.length;
|
||||
int szReloc = relocBytes.length >>> 3;
|
||||
int szReloc = nRelocations;
|
||||
rcm[4] = (byte) (ofsReloc & 0xFF);
|
||||
rcm[5] = (byte) ((ofsReloc >>> 8) & 0xFF);
|
||||
rcm[6] = (byte) (szReloc & 0xFF);
|
||||
@ -270,6 +318,13 @@ public class RCMRelocator {
|
||||
|
||||
class Relocation {
|
||||
|
||||
public static final int ZERO_VALUE = 0x80;
|
||||
public static final int R_ARM_CALL = 28;
|
||||
public static final int R_ARM_ABS32 = 2;
|
||||
public static final int R_ARM_JUMP24 = 29;
|
||||
public static final int R_ARM_BASE_ABS = 31;
|
||||
public static final int R_ARM_V4BX = 40;
|
||||
|
||||
public static int relocTypeFromString(String type, boolean local) {
|
||||
//if local, make the type relative
|
||||
if(local) {
|
||||
@ -286,15 +341,15 @@ class Relocation {
|
||||
|
||||
switch(type) {
|
||||
case "R_ARM_CALL":
|
||||
return 28;
|
||||
return R_ARM_CALL;
|
||||
case "R_ARM_ABS32":
|
||||
return 2;
|
||||
return R_ARM_ABS32;
|
||||
case "R_ARM_JUMP24":
|
||||
return 29;
|
||||
return R_ARM_JUMP24;
|
||||
case "R_ARM_V4BX":
|
||||
return 40;
|
||||
return R_ARM_V4BX;
|
||||
case "R_ARM_BASE_ABS":
|
||||
return 31;
|
||||
return R_ARM_BASE_ABS;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown relocation type " + type);
|
||||
}
|
||||
@ -329,8 +384,19 @@ class Relocation {
|
||||
*/
|
||||
int w0 = (relocTypeFromString(this.type, this.local) << 24) | this.offset;
|
||||
int w1 = this.value;
|
||||
byte[] b;
|
||||
|
||||
byte[] b = {
|
||||
//new zero-value flag: can we optimize?
|
||||
if (this.value == 0) {
|
||||
w0 |= (Relocation.ZERO_VALUE << 24);
|
||||
b = new byte[] {
|
||||
(byte) (w0 & 0xFF),
|
||||
(byte) ((w0 >>> 8) & 0xFF),
|
||||
(byte) ((w0 >>> 16) & 0xFF),
|
||||
(byte) ((w0 >>> 24) & 0xFF)
|
||||
};
|
||||
} else {
|
||||
b = new byte[] {
|
||||
(byte) (w0 & 0xFF),
|
||||
(byte) ((w0 >>> 8) & 0xFF),
|
||||
(byte) ((w0 >>> 16) & 0xFF),
|
||||
@ -340,6 +406,8 @@ class Relocation {
|
||||
(byte) ((w1 >>> 16) & 0xFF),
|
||||
(byte) ((w1 >>> 24) & 0xFF)
|
||||
};
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
Binary file not shown.
29
source/ldr.c
29
source/ldr.c
@ -2,6 +2,11 @@
|
||||
|
||||
Revision history:
|
||||
|
||||
05/06/2023 Garhoogin:
|
||||
Add zero-value relocation flag
|
||||
Allow using external symbols as hook addresses
|
||||
Removed auxiliary hook entry processing
|
||||
|
||||
11/28/2022 Garhoogin:
|
||||
Add data8 hook type
|
||||
|
||||
@ -47,7 +52,7 @@ void LDR_CallLoadCallback(void *pMod) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < hdr->nHook; i++) {
|
||||
if(hookTable[i].aux || hookTable[i].type != HOOK_TYPE_LOAD) continue;
|
||||
if (hookTable[i].type != HOOK_TYPE_LOAD) continue;
|
||||
RCM_LOAD_CALLBACK callback = (RCM_LOAD_CALLBACK) (hookTable[i].branchDestAddr + base);
|
||||
callback(base);
|
||||
}
|
||||
@ -63,7 +68,7 @@ void LDR_CallUnloadCallback(void *pMod) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < hdr->nHook; i++) {
|
||||
if(hookTable[i].aux || hookTable[i].type != HOOK_TYPE_UNLOAD) continue;
|
||||
if (hookTable[i].type != HOOK_TYPE_UNLOAD) continue;
|
||||
RCM_UNLOAD_CALLBACK callback = (RCM_UNLOAD_CALLBACK) (hookTable[i].branchDestAddr + base);
|
||||
callback(base);
|
||||
}
|
||||
@ -80,12 +85,14 @@ void LDR_Relocate(void *pMod) {
|
||||
u16 relocOffset = hdr->relocOffset;
|
||||
u16 nReloc = hdr->relocSize;
|
||||
u16 i;
|
||||
RELOCATION_ENTRY *relocs = (RELOCATION_ENTRY *) (base + relocOffset);
|
||||
RELOCATION_ENTRY *entry = (RELOCATION_ENTRY *) (base + relocOffset);
|
||||
for (i = 0; i < nReloc; i++) {
|
||||
RELOCATION_ENTRY *entry = relocs + i;
|
||||
int type = entry->type & R_TYPE_MASK;
|
||||
u32 destAddr = base + entry->offset;
|
||||
u32 value = entry->value;
|
||||
int type = entry->type;
|
||||
u32 value = 0;
|
||||
if (!(entry->type & R_ZERO_VALUE)) {
|
||||
value = entry->value;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case R_ARM_ABS32:
|
||||
@ -115,6 +122,13 @@ void LDR_Relocate(void *pMod) {
|
||||
*(u32 *) destAddr += value + base;
|
||||
break;
|
||||
}
|
||||
|
||||
//next relocation. Advance whole relocation for nonzero value
|
||||
if (entry->type & R_ZERO_VALUE) {
|
||||
entry = (RELOCATION_ENTRY *) &entry->value;
|
||||
} else {
|
||||
entry++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,8 +146,6 @@ void LDR_LoadModule(void *pMod) {
|
||||
//iterate through the hooks and insert patches
|
||||
HOOK_TABLE_ENTRY *hookTable = hdr->hookTable;
|
||||
for (i = 0; i < nHook; i++) {
|
||||
if(hookTable[i].aux) continue;
|
||||
|
||||
u32 hookType = hookTable[i].type;
|
||||
u32 hookDest = hookTable[i].branchDestAddr;
|
||||
u32 hookSrc = hookTable[i].branchSrcAddr;
|
||||
@ -199,7 +211,6 @@ void LDR_UnloadModule(void *pMod) {
|
||||
|
||||
HOOK_TABLE_ENTRY *hookTable = hdr->hookTable;
|
||||
for (i = nHook; i >= 0; i--) {
|
||||
if(hookTable[i].aux) continue;
|
||||
u16 *patchLocation = (u16 *) (u32) hookTable[i].branchSrcAddr;
|
||||
int type = hookTable[i].type;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user