Read about our upcoming Code of Conduct on this issue

Commit dd29d8e7 authored by alex@thinkpad's avatar alex@thinkpad
Browse files

reloc: handle PC-relative add (ADR)

(also updated sign handling in LDR, for consistency)

--HG--
branch : patchmgr
parent 2c4fb7e7f1b5
......@@ -181,9 +181,34 @@ reloc(
offset |= imm << (32 - shift);
uint32_t dest = pc + 8 + offset;
// Ignore offetss inside the reloc space
// Ignore offsets inside the reloc space
if( func_offset <= dest && dest < func_end )
continue;
// Find the data that is being used and
// compute a new offset so that it can be
// accessed from the relocated space.
// Replace with a LDR instruction:
// ADR PC, something => LDR PC, =address_of_something
uint32_t data = dest;
int32_t new_offset = fixups - new_pc - 8;
uint32_t sign_bit = (1 << 23);
if ( new_offset < 0 )
{
// Set offset to negative
sign_bit = 0;
new_offset = -new_offset;
}
// Turn ADR into LDR; keep condition flags
// and destination register from old instruction
uint32_t new_instr = 0
| ( instr & 0xF000F000 )
| ( /*LDR*/ 0x051F0000 )
| ( sign_bit & 0x800000 )
| ( new_offset & 0xFFF )
;
#ifdef RELOC_PRINT
printf( "%08x: %08x add pc shift=%x imm=%2x offset=%x => %08x\n",
pc,
......@@ -194,6 +219,13 @@ reloc(
dest
);
#endif
#ifdef __ARM__
// Copy the data to the offset location
*(uint32_t*) fixups = data;
*(uint32_t*) new_pc = new_instr;
#endif
fixups += 4;
continue;
}
......@@ -201,7 +233,7 @@ reloc(
if( load == LOAD_INSTR )
{
uint32_t reg_base = (instr >> 16) & 0xF;
uint32_t reg_dest = (instr >> 12) & 0xF;
uint32_t reg_dest = (instr >> 12) & 0xF;
int32_t offset = (instr >> 0) & 0xFFF;
if( reg_base != REG_PC )
......@@ -223,16 +255,18 @@ reloc(
// accessed from the relocated space.
uint32_t data = *(uint32_t*)( dest + mem );
int32_t new_offset = fixups - new_pc - 8;
uint32_t sign_bit = (1 << 23);
if( new_offset < 0 )
{
// Set offset to negative
instr &= ~(1<<23);
sign_bit = 0;
new_offset = -new_offset;
}
uint32_t new_instr = 0
| ( instr & ~0xFFF )
| ( new_offset & 0xFFF )
| ( instr & 0xFF7FF000 )
| ( sign_bit & 0x800000 )
| ( new_offset & 0xFFF )
;
#ifdef RELOC_PRINT
// This is one that will need to be copied
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment