patch type added: PATCH_OBJECT_ARM32_ABS_THM (for R_ARM_THM_MOVW_ABS_NC and R_ARM_THM_MOVT_ABS)

This commit is contained in:
Nicolas 2026-03-02 21:28:05 +01:00
parent afc442ada6
commit 8fcf0dedac
3 changed files with 40 additions and 2 deletions

View File

@ -13,6 +13,7 @@ Command = Enum('Command', [('ALLOCATE_DATA', 1), ('COPY_DATA', 2),
('PATCH_OBJECT_ABS', 0x2002),
('PATCH_OBJECT_REL', 0x2003),
('PATCH_OBJECT_ARM32_ABS', 0x2004),
('PATCH_OBJECT_ARM32_ABS_THM', 0x2006),
('ENTRY_POINT', 7),
('RUN_PROG', 64), ('READ_DATA', 65),
('END_COM', 256), ('FREE_MEMORY', 257), ('DUMP_CODE', 258)])

View File

@ -50,6 +50,32 @@ void patch_arm32_abs(uint8_t *patch_addr, uint32_t imm16)
*((uint32_t *)patch_addr) = instr;
}
void patch_arm_thm_abs(uint8_t *patch_addr, uint32_t imm16)
{
// Thumb MOVW (T3) / MOVT (T1) encoding
uint16_t *instr16 = (uint16_t *)patch_addr;
uint16_t first_half = instr16[0];
uint16_t second_half = instr16[1];
// Extract fields from imm16
uint32_t imm4 = (imm16 >> 12) & 0xF;
uint32_t i = (imm16 >> 11) & 0x1;
uint32_t imm3 = (imm16 >> 8) & 0x7;
uint32_t imm8 = imm16 & 0xFF;
// Clear bits
first_half &= (uint16_t)(~(0x000F | (1 << 10)));
second_half &= (uint16_t)(~(0x00FF | (0x7 << 12)));
// Set new fields
first_half |= (uint16_t)((imm4 << 0) | (i << 10));
second_half |= (uint16_t)(imm8 | (imm3 << 12));
instr16[0] = first_half;
instr16[1] = second_half;
}
void patch_arm_thm_jump24(uint8_t *patch_addr, int32_t imm24)
{
// Read the 32-bit instruction (two halfwords)
@ -77,8 +103,8 @@ void patch_arm_thm_jump24(uint8_t *patch_addr, int32_t imm24)
second_half &= 0xD000; // Keep upper 5 bits
// Set new imm fields
first_half |= (S << 10) | imm10;
second_half |= (J1 << 13) | (J2 << 11) | imm11;
first_half |= (uint16_t)((S << 10) | imm10);
second_half |= (uint16_t)((J1 << 13) | (J2 << 11) | imm11);
// Write back
instr16[0] = first_half;
@ -225,6 +251,16 @@ int parse_commands(runmem_t *context, uint8_t *bytes) {
patch_arm_thm_jump24(context->executable_memory + offs, value);
break;
case PATCH_OBJECT_ARM32_ABS_THM:
offs = *(uint32_t*)bytes; bytes += 4;
patch_mask = *(uint32_t*)bytes; bytes += 4;
patch_scale = *(int32_t*)bytes; bytes += 4;
value = *(int32_t*)bytes; bytes += 4;
LOG("PATCH_OBJECT_ARM32_ABS_THM patch_offs=%i patch_mask=%#08x scale=%i value=%i imm16=%#04x\n",
offs, patch_mask, patch_scale, value, (uint32_t)((uintptr_t)(context->data_memory + value) & patch_mask) / (uint32_t)patch_scale);
patch_arm_thm_abs(context->executable_memory + offs, (uint32_t)((uintptr_t)(context->data_memory + value) & patch_mask) / (uint32_t)patch_scale);
break;
case ENTRY_POINT:
rel_entr_point = *(uint32_t*)bytes; bytes += 4;
context->entr_point = (entry_point_t)(context->executable_memory + rel_entr_point);

View File

@ -26,6 +26,7 @@
#define PATCH_OBJECT_ABS 0x2002
#define PATCH_OBJECT_REL 0x2003
#define PATCH_OBJECT_ARM32_ABS 0x2004
#define PATCH_OBJECT_ARM32_ABS_THM 0x2006
#define ENTRY_POINT 7
#define RUN_PROG 64
#define READ_DATA 65