Skip to content

Commit

Permalink
Support ARM ELF THM_PC22 / THM_JUMP24 relocs (#4503)
Browse files Browse the repository at this point in the history
* Support ARM ELF THM_PC22 / THM_JUMP24 relocs

This revision adds proper support for the following ARM ELF relocations:

- RZ_ARM_THM_PC22
- RZ_ARM_THM_JUMP24

These require a rather special encoding as some bits of the relative
offset are encoded in a non-common fashion.
  • Loading branch information
timiv authored May 20, 2024
1 parent 4ead42d commit c7464ab
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 6 deletions.
40 changes: 34 additions & 6 deletions librz/bin/p/bin_elf.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1040,14 +1040,41 @@ static void patch_reloc(struct Elf_(rz_bin_elf_obj_t) * obj, RzBinElfReloc *rel,
case EM_QDSP6:
patch_reloc_hexagon(obj->buf_patched, patch_addr, rel->type, &formular_sym);
break;
case EM_ARM:
val = S + A;
if (!rel->sym && rel->mode == DT_REL) {
rz_buf_read_at(obj->buf_patched, patch_addr, buf, 4);
val += obj->big_endian ? rz_read_be32(buf) : rz_read_le32(buf);
case EM_ARM: {
ut16 keephw1, keephw2;
ut32 nbytes = 4;
rz_buf_read_at(obj->buf_patched, patch_addr, buf, 4);
switch (rel->type) {
case RZ_ARM_THM_JUMP24:
case RZ_ARM_THM_PC22:
// Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0
// I1 = NOT(J1 EOR S)
// I2 = NOT(J2 EOR S)
val = S + A;
keephw1 = rz_read_ble16(&buf[0], big_endian);
keephw2 = rz_read_ble16(&buf[2], big_endian);
rz_write_ble16(&buf[0],
(keephw1 & 0xF800U) | // opcode
((val >> 14) & 0x0400U) | // sign
((val >> 12) & 0x03FFU), // imm 10
big_endian);
rz_write_ble16(&buf[2],
(keephw2 & 0xD000U) | // opcode
(((~(val >> 10)) ^ (val >> 11)) & 0x2000) | // J1
(((~(val >> 11)) ^ (val >> 13)) & 0x0800) | // J2
((val >> 1) & 0x07ff), // imm11
big_endian);
break;
default:
val = S + A;
if (!rel->sym && rel->mode == DT_REL) {
val += rz_read_ble32(buf, big_endian);
}
rz_write_ble32(buf, val, big_endian);
}
rz_buf_write_ble32_at(obj->buf_patched, patch_addr, val, obj->big_endian);
rz_buf_write_at(obj->buf_patched, patch_addr, buf, nbytes);
break;
}
case EM_AARCH64: {
ut32 keep;
ut32 nbytes = 4;
Expand Down Expand Up @@ -1435,6 +1462,7 @@ static RzBinReloc *reloc_convert(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT) {
case RZ_ARM_CALL: ADD(24, -P);
case RZ_ARM_JUMP24: ADD(24, -P);
case RZ_ARM_THM_JUMP24: ADD(24, -P);
case RZ_ARM_THM_PC22: ADD(24, -P);
case RZ_ARM_PREL31: ADD(32, -P);
case RZ_ARM_MOVW_PREL_NC: ADD(16, -P);
case RZ_ARM_MOVT_PREL: ADD(32, -P);
Expand Down
20 changes: 20 additions & 0 deletions test/db/formats/elf/elf-relarm
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,26 @@ EXPECT=<<EOF
EOF
RUN

NAME=ELF: arm thumb relocs 1
FILE=bins/elf/mbedtls-bignum-thumb-interwork.so
CMDS=<<EOF
ir~?
# ARM_THM_PC22
s 0x08000b82
pf bbbb
pd 1
EOF
EXPECT=<<EOF
4810
0x08000b82 = 0x19
0x08000b83 = 0xf0
0x08000b84 = 0xaa
0x08000b85 = 0xfa
;-- memset:
0x08000b82 bl memset ; RELOC 24 memset
EOF
RUN

NAME=ELF: arm64 relocs 1
FILE=bins/elf/r2pay-arm64.so
CMDS=<<EOF
Expand Down

0 comments on commit c7464ab

Please sign in to comment.