Skip to content

Commit

Permalink
Add support for more AArch64 ELF relocs (#1699)
Browse files Browse the repository at this point in the history
* Add support for more AArch64 ELF relocs

Co-authored-by: Giovanni <[email protected]>

* Update prev and add more relocs

---------

Co-authored-by: Giovanni <[email protected]>
Co-authored-by: Pavel I <[email protected]>
  • Loading branch information
3 people authored Jan 31, 2024
1 parent a8e715a commit dbb3aa4
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 21 deletions.
3 changes: 1 addition & 2 deletions librz/bin/format/elf/elf_relocs.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ static bool get_relocs_entry(ELFOBJ *bin, RzBinElfSection *section, RzVector /*<
if (!get_reloc_entry(bin, &tmp, segment->offset + entry_offset, segment->mode)) {
return false;
}

fix_rva_and_offset(bin, &tmp, section);

if (!rz_vector_push(relocs, &tmp)) {
Expand Down Expand Up @@ -244,7 +243,7 @@ RZ_OWN RzVector /*<RzBinElfReloc>*/ *Elf_(rz_bin_elf_relocs_new)(RZ_NONNULL ELFO
bool Elf_(rz_bin_elf_has_relocs)(RZ_NONNULL ELFOBJ *bin) {
rz_return_val_if_fail(bin, false);

return bin->relocs;
return bin->relocs && (rz_vector_len(bin->relocs) > 0);
}

size_t Elf_(rz_bin_elf_get_relocs_count)(RZ_NONNULL ELFOBJ *bin) {
Expand Down
116 changes: 107 additions & 9 deletions librz/bin/p/bin_elf.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,14 @@ static void patch_reloc_hexagon(RZ_INOUT RzBuffer *buf_patched, const ut64 patch
}
}

// AARCH64-specific defines
// Take the PAGE component of an address or offset.
#define PG(x) ((x) & ~0xFFFULL)
#define PG_OFFSET(x) ((x)&0xFFFULL)
#define ADR_IMM_MASK1 (((1U << 2) - 1) << 29)
#define ADR_IMM_MASK2 (((1U << 19) - 1) << 5)
#define ADR_IMM_MASK3 (((1U << 19) - 1) << 2)

static void patch_reloc(struct Elf_(rz_bin_elf_obj_t) * obj, RzBinElfReloc *rel, ut64 S, ut64 B, ut64 L, ut64 GOT) {
ut16 e_machine = obj->ehdr.e_machine;
ut64 val = 0;
Expand All @@ -1040,11 +1048,81 @@ static void patch_reloc(struct Elf_(rz_bin_elf_obj_t) * obj, RzBinElfReloc *rel,
}
rz_buf_write_ble32_at(obj->buf_patched, patch_addr, val, obj->big_endian);
break;
case EM_AARCH64:
val = S + A;
rz_write_le64(buf, val);
rz_buf_write_at(obj->buf_patched, patch_addr, buf, 8);
case EM_AARCH64: {
ut32 keep;
ut32 nbytes = 4;
rz_buf_read_at(obj->buf_patched, patch_addr, buf, 8);
switch (rel->type) {
case RZ_AARCH64_ABS16:
val = S + A;
rz_write_le16(buf, val);
nbytes = 2;
break;
case RZ_AARCH64_ABS32:
val = S + A;
rz_write_le32(buf, val);
break;
case RZ_AARCH64_GLOB_DAT:
case RZ_AARCH64_ABS64:
case RZ_AARCH64_JUMP_SLOT:
val = S + A;
rz_write_le64(buf, val);
nbytes = 8;
break;
case RZ_AARCH64_PREL16:
val = S + A - P;
rz_write_le16(buf, val);
nbytes = 2;
break;
case RZ_AARCH64_PREL32:
val = S + A - P;
rz_write_le32(buf, val);
break;
case RZ_AARCH64_PREL64:
val = S + A - P;
rz_write_le64(buf, val);
nbytes = 8;
break;
case RZ_AARCH64_RELATIVE:
val = B + A;
rz_write_le64(buf, val);
nbytes = 8;
break;
case RZ_AARCH64_ADR_PREL_PG_HI21:
case RZ_AARCH64_ADR_PREL_PG_HI21_NC:
case RZ_AARCH64_ADR_GOT_PAGE:
// Reencode ADR imm
keep = rz_read_le32(buf) & ~(ADR_IMM_MASK1 | ADR_IMM_MASK2);
val = ((st64)(PG(S + A) - PG(P))) >> 12;
rz_write_le32(buf, keep | ((val & RZ_BIT_MASK32(2, 0)) << 29) | ((val & ADR_IMM_MASK3) << 3));
break;
case RZ_AARCH64_JUMP26:
case RZ_AARCH64_CALL26:
// Reencode 26 bits of the offset
keep = rz_read_le32(buf) & ~RZ_BIT_MASK32(26, 0);
val = ((st64)(S + A - P)) >> 2;
rz_write_le32(buf, keep | (val & RZ_BIT_MASK32(26, 0)));
break;
case RZ_AARCH64_LDST8_ABS_LO12_NC:
case RZ_AARCH64_ADD_ABS_LO12_NC:
keep = rz_read_le32(buf) & ~(RZ_BIT_MASK32(12, 0) << 10);
val = PG_OFFSET(S + A);
rz_write_le32(buf, keep | ((val & RZ_BIT_MASK32(12, 0)) << 10));
break;
case RZ_AARCH64_LD64_GOT_LO12_NC:
case RZ_AARCH64_LDST64_ABS_LO12_NC:
// Reencode LD/ST imm
keep = rz_read_le32(buf) & ~(RZ_BIT_MASK32(12, 0) << 10);
val = PG_OFFSET(S + A) >> 3;
rz_write_le32(buf, keep | ((val & RZ_BIT_MASK32(12, 0)) << 10));
break;
default:
nbytes = 0;
break;
}
rz_buf_write_at(obj->buf_patched, patch_addr, buf, nbytes);
break;
}
case EM_PPC64: {
int low = 0, word = 0;
switch (rel->type) {
Expand Down Expand Up @@ -1281,9 +1359,11 @@ static RzBinReloc *reloc_convert(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT) {
case RZ_386_PC16: ADD(16, -P);
case RZ_386_8: ADD(8, 0);
case RZ_386_PC8: ADD(8, -P);
case RZ_386_COPY: ADD(32, 0); // XXX: copy symbol at runtime
case RZ_386_COPY: ADD(32, 0); // copy symbol at runtime
case RZ_386_IRELATIVE: r->is_ifunc = true; SET(32);
default: break;
default:
RZ_LOG_WARN("unimplemented ELF/X86_32 reloc type %d\n", rel->type);
break;
}
break;
case EM_X86_64:
Expand All @@ -1303,9 +1383,11 @@ static RzBinReloc *reloc_convert(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT) {
case RZ_X86_64_8: ADD(8, 0);
case RZ_X86_64_PC8: ADD(8, -P);
case RZ_X86_64_GOTPCREL: ADD(64, GOT - P);
case RZ_X86_64_COPY: ADD(64, 0); // XXX: copy symbol at runtime
case RZ_X86_64_COPY: ADD(64, 0); // copy symbol at runtime
case RZ_X86_64_IRELATIVE: r->is_ifunc = true; SET(64);
default: break;
default:
RZ_LOG_WARN("unimplemented ELF/X86_64 reloc type %d\n", rel->type);
break;
}
break;
case EM_ARM:
Expand Down Expand Up @@ -1358,12 +1440,28 @@ static RzBinReloc *reloc_convert(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT) {
case EM_AARCH64:
switch (rel->type) {
case RZ_AARCH64_NONE: break;
case RZ_AARCH64_ABS64: ADD(64, 0);
case RZ_AARCH64_ABS32: ADD(32, 0);
case RZ_AARCH64_ABS16: ADD(16, 0);
case RZ_AARCH64_PREL64: ADD(64, 0);
case RZ_AARCH64_PREL32: ADD(32, 0);
case RZ_AARCH64_PREL16: ADD(16, 0);
case RZ_AARCH64_GLOB_DAT: SET(64);
case RZ_AARCH64_JUMP_SLOT: SET(64);
case RZ_AARCH64_RELATIVE: ADD(64, B);
default: break; // reg relocations
case RZ_AARCH64_LDST8_ABS_LO12_NC: ADD(16, 0);
case RZ_AARCH64_ADD_ABS_LO12_NC: ADD(16, 0);
case RZ_AARCH64_JUMP26: ADD(32, 0);
case RZ_AARCH64_CALL26: ADD(32, 0);
case RZ_AARCH64_LDST64_ABS_LO12_NC: ADD(32, 0);
case RZ_AARCH64_LD64_GOT_LO12_NC: ADD(32, 0);
// Page-relative relocations
case RZ_AARCH64_ADR_GOT_PAGE: ADD(32, 0);
case RZ_AARCH64_ADR_PREL_PG_HI21: ADD(32, 0);
case RZ_AARCH64_ADR_PREL_PG_HI21_NC: ADD(32, 0);
default:
RZ_LOG_WARN("unimplemented ELF/AARCH64 reloc type %d\n", rel->type);
break;
}
break;
case EM_PPC:
Expand Down
1 change: 1 addition & 0 deletions librz/include/rz_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ static inline void *rz_new_copy(int size, const void *data) {
((char *)(((size_t)(v) + (t - 1)) & ~(t - 1)))

#define RZ_BIT_MASK32(x, y) ((1UL << (x)) - (1UL << (y)))
#define RZ_BIT_MASK64(x, y) ((1ULL << (x)) - (1ULL << (y)))
#define RZ_BIT_SET(x, y) (((ut8 *)x)[y >> 4] |= (1 << (y & 0xf)))
#define RZ_BIT_UNSET(x, y) (((ut8 *)x)[y >> 4] &= ~(1 << (y & 0xf)))
#define RZ_BIT_TOGGLE(x, y) (RZ_BIT_CHK(x, y) ? RZ_BIT_UNSET(x, y) : RZ_BIT_SET(x, y))
Expand Down
70 changes: 60 additions & 10 deletions test/db/formats/elf/elf-relarm
Original file line number Diff line number Diff line change
Expand Up @@ -116,27 +116,35 @@ EXPECT=<<EOF
EOF
RUN

NAME=ELF: arm64 sh relocs
NAME=ELF: arm64 relocs 1
FILE=bins/elf/r2pay-arm64.so
CMDS=<<EOF
ir~?
s section..init_array
pd 10
EOF
EXPECT=<<EOF
231
320
;-- section..init_array:
;-- segment.LOAD1:
0x00126510 .qword 0x0000000000005a6c ; sym..datadiv_decode9958896245423089702 ; [12] -rw- section size 728 named .init_array
0x00126518 .qword 0x0000000000005a80 ; sym..datadiv_decode10476194973746341988
0x00126520 .qword 0x00000000000efddc ; sym..datadiv_decode16323044921667855934
;-- .datadiv_decode9958896245423089702:
0x00126510 .qword 0x0000000000005a6c ; reloc.target..datadiv_decode9958896245423089702 ; sym..datadiv_decode9958896245423089702; RELOC 64 .datadiv_decode9958896245423089702 @ 0x00005a6c ; [12] -rw- section size 728 named .init_array
;-- .datadiv_decode10476194973746341988:
0x00126518 .qword 0x0000000000005a80 ; reloc.target..datadiv_decode10476194973746341988 ; sym..datadiv_decode10476194973746341988; RELOC 64 .datadiv_decode10476194973746341988 @ 0x00005a80
;-- .datadiv_decode16323044921667855934:
0x00126520 .qword 0x00000000000efddc ; reloc.target..datadiv_decode16323044921667855934 ; sym..datadiv_decode16323044921667855934; RELOC 64 .datadiv_decode16323044921667855934 @ 0x000efddc
0x00126528 .qword 0x0000000000009080 ; entry.init0 ; RELOC 64
0x00126530 .qword 0x0000000000077d14 ; entry.init1 ; RELOC 64
0x00126538 .qword 0x00000000000f22e0 ; sym..datadiv_decode667225052219618748
0x00126540 .qword 0x00000000000f22e4 ; sym..datadiv_decode8132880250332170398
0x00126548 .qword 0x00000000000f22e8 ; sym..datadiv_decode3655886617018729963
0x00126550 .qword 0x00000000000f22ec ; sym..datadiv_decode16406252260792032531
0x00126558 .qword 0x00000000000f22f0 ; sym..datadiv_decode13403071575248320347
;-- .datadiv_decode667225052219618748:
0x00126538 .qword 0x00000000000f22e0 ; reloc.target..datadiv_decode667225052219618748 ; sym..datadiv_decode667225052219618748; RELOC 64 .datadiv_decode667225052219618748 @ 0x000f22e0
;-- .datadiv_decode8132880250332170398:
0x00126540 .qword 0x00000000000f22e4 ; reloc.target..datadiv_decode8132880250332170398 ; sym..datadiv_decode8132880250332170398; RELOC 64 .datadiv_decode8132880250332170398 @ 0x000f22e4
;-- .datadiv_decode3655886617018729963:
0x00126548 .qword 0x00000000000f22e8 ; reloc.target..datadiv_decode3655886617018729963 ; sym..datadiv_decode3655886617018729963; RELOC 64 .datadiv_decode3655886617018729963 @ 0x000f22e8
;-- .datadiv_decode16406252260792032531:
0x00126550 .qword 0x00000000000f22ec ; reloc.target..datadiv_decode16406252260792032531 ; sym..datadiv_decode16406252260792032531; RELOC 64 .datadiv_decode16406252260792032531 @ 0x000f22ec
;-- .datadiv_decode13403071575248320347:
0x00126558 .qword 0x00000000000f22f0 ; reloc.target..datadiv_decode13403071575248320347 ; sym..datadiv_decode13403071575248320347; RELOC 64 .datadiv_decode13403071575248320347 @ 0x000f22f0
EOF
RUN

Expand All @@ -159,3 +167,45 @@ EXPECT=<<EOF
0x00011040 0x00011040 @...
EOF
RUN

NAME=ELF: arm64 relocs 2
FILE=bins/elf/graphascii.c-gcc-arm64-O0.o
CMDS=<<EOF
ir~?
s 0x8000444
pf bbbb
pi 1
s 0x8000460
pf bbbb
pi 1
s 0x800046c
pf bbbb
pi 1
s 0x80003d8
pf bbbb
pi 1
EOF
EXPECT=<<EOF
315
0x08000444 = 0x00
0x08000445 = 0x00
0x08000446 = 0x00
0x08000447 = 0xf0
adrp x0, 0x8003000
0x08000460 = 0x1c
0x08000461 = 0x0d
0x08000462 = 0x00
0x08000463 = 0x94
bl reloc.target.stackCursor
0x0800046c = 0x00
0x0800046d = 0x64
0x0800046e = 0x44
0x0800046f = 0xf9
ldr x0, [x0, 0x8c8]
0x080003d8 = 0x3a
0x080003d9 = 0x0d
0x080003da = 0x00
0x080003db = 0x94
bl reloc.target.fputs
EOF
RUN

0 comments on commit dbb3aa4

Please sign in to comment.