Add big endian PPC relocs (#2502)

* Add support for big endian PPC relocs.
* Add tests for PPC_RELATIVE and PPC_JMP_SLOT.
This commit is contained in:
Rot127 2022-04-06 01:18:40 +00:00 committed by GitHub
parent 0a309afbe9
commit 0c4e84cd9d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 6 deletions

View file

@ -5,6 +5,7 @@
#include <stdio.h>
#include <rz_types.h>
#include <rz_util.h>
#include <rz_util/rz_buf.h>
#include <rz_lib.h>
#include <rz_bin.h>
#include <rz_io.h>
@ -889,6 +890,7 @@ static void patch_reloc(struct Elf_(rz_bin_elf_obj_t) * obj, RzBinElfReloc *rel,
RzBinRelocFormularSymbols formular_sym = { .A = A, .B = B, .GOT = GOT, .L = L, .S = S, .P = P, .MB = 0, .G = 0, .GP = 0, .T = 0, .TLS = 0 };
ut64 patch_addr = rel->paddr != UT64_MAX ? rel->paddr : Elf_(rz_bin_elf_v2p)(obj, rel->vaddr);
ut8 buf[8];
bool big_endian = obj->big_endian;
switch (e_machine) {
case EM_QDSP6:
patch_reloc_hexagon(obj->buf_patched, patch_addr, rel->type, &formular_sym);
@ -933,30 +935,28 @@ static void patch_reloc(struct Elf_(rz_bin_elf_obj_t) * obj, RzBinElfReloc *rel,
break;
}
if (low) {
// TODO big-endian
switch (low) {
case 14:
val &= (1 << 14) - 1;
rz_buf_read_at(obj->buf_patched, patch_addr, buf, 2);
rz_write_le32(buf, (rz_read_le32(buf) & ~((1 << 16) - (1 << 2))) | val << 2);
rz_write_ble32(buf, (rz_read_ble32(buf, big_endian) & ~(RZ_BIT_MASK32(16, 2))) | val << 2, big_endian);
rz_buf_write_at(obj->buf_patched, patch_addr, buf, 2);
break;
case 24:
val &= (1 << 24) - 1;
rz_buf_read_at(obj->buf_patched, patch_addr, buf, 4);
rz_write_le32(buf, (rz_read_le32(buf) & ~((1 << 26) - (1 << 2))) | val << 2);
rz_write_ble32(buf, (rz_read_ble32(buf, big_endian) & ~(RZ_BIT_MASK32(26, 2))) | val << 2, big_endian);
rz_buf_write_at(obj->buf_patched, patch_addr, buf, 4);
break;
}
} else if (word) {
// TODO big-endian
switch (word) {
case 2:
rz_write_le16(buf, val);
rz_write_ble16(buf, val, big_endian);
rz_buf_write_at(obj->buf_patched, patch_addr, buf, 2);
break;
case 4:
rz_write_le32(buf, val);
rz_write_ble32(buf, val, big_endian);
rz_buf_write_at(obj->buf_patched, patch_addr, buf, 4);
break;
}
@ -1212,6 +1212,12 @@ static RzBinReloc *reloc_convert(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT) {
case RZ_PPC_NONE: break;
case RZ_PPC_GLOB_DAT: ADD(32, 0);
case RZ_PPC_JMP_SLOT: ADD(32, 0);
case RZ_PPC_COPY: ADD(32, 0); // copy symbol at runtime
case RZ_PPC_REL24: ADD(24, -P);
case RZ_PPC_REL14: ADD(16, -P);
case RZ_PPC_REL32: ADD(32, -P);
case RZ_PPC_RELATIVE: ADD(32, -P);
case RZ_PPC_PLT32: ADD(32, -P);
default:
eprintf("unimplemented ELF/PPC reloc type %d\n", rel->type);
break;

View file

@ -292,6 +292,7 @@ static inline void *rz_new_copy(int size, void *data) {
#define RZ_PTR_ALIGN_NEXT(v, t) \
((char *)(((size_t)(v) + (t - 1)) & ~(t - 1)))
#define RZ_BIT_MASK32(x, y) ((1UL << (x)) - (1UL << (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))

View file

@ -413,3 +413,35 @@ ret
EOF
RUN
NAME=PPC big endian R_PPC_RELATIVE and R_PPC_JMP_SLOT
FILE=bins/abi_bins/elf/platforms/macppc-openbsd-echo
BROKEN=1
CMDS=<<EOF
# 584 relocs + 2 header lines
ir~?
# R_PPC_RELATIVE
s 0x398f8
pf bbbb
pd 1
# R_PPC_JMP_SLOT
s 0x39ca4
pf bbbb
pd 1
EOF
EXPECT=<<EOF
586
0x000398f8 = 0x00
0x000398f9 = 0x01
0x000398fa = 0x40
0x000398fb = 0xf4
;-- section..preinit_array:
0x000398f8 .dword 0x000140f4 ; RELOC 32 ; [19] -rw- section size 4 named .preinit_array
0x00039ca4 = 0x00
0x00039ca5 = 0x05
0x00039ca6 = 0x06
0x00039ca7 = 0x7c
;-- section..plt:
;-- _Jv_RegisterClasses:
0x00039ca4 .dword 0x0005067c ; section..glink ; RELOC 32 _Jv_RegisterClasses ; [23] -rw- section size 4 named .plt
EOF
RUN