Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix COFF reloc naming #4701

Merged
merged 2 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 114 additions & 69 deletions librz/bin/format/coff/coff_reloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,112 @@ RZ_API ut64 rz_coff_import_index_addr(struct rz_bin_coff_obj *obj, ut64 imp_inde

typedef void (*RelocsForeachCb)(RZ_BORROW RzBinReloc *reloc, ut8 *patch_buf, size_t patch_buf_sz, void *user);

static size_t reloc_general_arch_rel32_common(struct rz_bin_coff_obj *bin, RzBinReloc *reloc, ut64 sym_vaddr, ut8 *patch_buf, const char *print_name) {
reloc->print_name = print_name;
reloc->type = RZ_BIN_RELOC_32;
reloc->additive = 1;
ut32 data;
if (!rz_buf_read_le32_at(bin->b, reloc->paddr, &data)) {
return 0;
}
reloc->addend = data;
data += sym_vaddr - reloc->vaddr - 4;
rz_write_le32(patch_buf, (st32)data);

return 4;
}

static size_t reloc_arm_branches_common(struct rz_bin_coff_obj *bin, RzBinReloc *reloc, ut64 sym_vaddr, ut8 *patch_buf, const char *print_name) {
reloc->print_name = print_name;
reloc->type = RZ_BIN_RELOC_32;
ut16 hiword;
if (!rz_buf_read_le16_at(bin->b, reloc->paddr, &hiword)) {
return 0;
}
ut16 loword;
if (!rz_buf_read_le16_at(bin->b, reloc->paddr + 2, &loword)) {
return 0;
}
ut64 dst = sym_vaddr - reloc->vaddr - 4;
if (dst & 1) {
return 0;
}
loword |= (ut16)(dst >> 1) & 0x7ff;
hiword |= (ut16)(dst >> 12) & 0x7ff;
rz_write_le16(patch_buf, hiword);
rz_write_le16(patch_buf + 2, loword);

return 4;
}

static ut8 handle_i386_relocs(struct rz_bin_coff_obj *bin, RzBinReloc *reloc, ut64 sym_vaddr, ut8 *patch_buf, ut16 reloc_type) {
switch (reloc_type) {
case COFF_REL_I386_DIR32:
reloc->type = RZ_BIN_RELOC_32;
rz_write_le32(patch_buf, (ut32)sym_vaddr);
reloc->print_name = "IMAGE_REL_I386_32";
return 4;
case COFF_REL_I386_REL32:
return reloc_general_arch_rel32_common(bin, reloc, sym_vaddr, patch_buf, "IMAGE_REL_I386_REL32");
// TODO: Missing handling of other relocation types
default:
RZ_LOG_WARN("Unimplemented/unknown COFF i386 relocation type: %d\n", reloc_type);
break;
}
XVilka marked this conversation as resolved.
Show resolved Hide resolved

return 0;
}

static ut8 handle_amd64_relocs(struct rz_bin_coff_obj *bin, RzBinReloc *reloc, ut64 sym_vaddr, ut8 *patch_buf, ut16 reloc_type) {
switch (reloc_type) {
case COFF_REL_AMD64_REL32:
return reloc_general_arch_rel32_common(bin, reloc, sym_vaddr, patch_buf, "IMAGE_REL_AMD64_REL32");
// TODO: Missing handling of other relocation types
default:
RZ_LOG_WARN("Unimplemented/unknown COFF AMD64 relocation type: %d\n", reloc_type);
break;
}
XVilka marked this conversation as resolved.
Show resolved Hide resolved

return 0;
}

static ut8 handle_arm_relocs(struct rz_bin_coff_obj *bin, RzBinReloc *reloc, ut64 sym_vaddr, ut8 *patch_buf, ut16 reloc_type) {
switch (reloc_type) {
case COFF_REL_ARM_BRANCH24T:
return reloc_arm_branches_common(bin, reloc, sym_vaddr, patch_buf, "IMAGE_REL_ARM_BRANCH24T");
case COFF_REL_ARM_BLX23T:
return reloc_arm_branches_common(bin, reloc, sym_vaddr, patch_buf, "IMAGE_REL_ARM_BLX23T");
// TODO: Missing handling of other relocation types
default:
RZ_LOG_WARN("Unimplemented/unknown COFF ARM relocation type: %d\n", reloc_type);
break;
}
XVilka marked this conversation as resolved.
Show resolved Hide resolved

return 0;
}

static ut8 handle_arm64_relocs(struct rz_bin_coff_obj *bin, RzBinReloc *reloc, ut64 sym_vaddr, ut8 *patch_buf, ut16 reloc_type) {
switch (reloc_type) {
case COFF_REL_ARM64_BRANCH26:
reloc->type = RZ_BIN_RELOC_32;
ut32 data;
if (!rz_buf_read_le32_at(bin->b, reloc->paddr, &data)) {
break;
}
ut64 dst = sym_vaddr - reloc->vaddr;
data |= (ut32)((dst >> 2) & 0x3ffffffULL);
rz_write_le32(patch_buf, data);
reloc->print_name = "IMAGE_REL_ARM64_BRANCH26";
return 4;
// TODO: Missing handling of other relocation types
default:
RZ_LOG_WARN("Unimplemented/unknown COFF ARM64 relocation type: %d\n", reloc_type);
break;
}
XVilka marked this conversation as resolved.
Show resolved Hide resolved

return 0;
}

static void relocs_foreach(struct rz_bin_coff_obj *bin, RelocsForeachCb cb, void *user) {
if (!bin->scn_hdrs) {
return;
Expand Down Expand Up @@ -97,82 +203,21 @@ static void relocs_foreach(struct rz_bin_coff_obj *bin, RelocsForeachCb cb, void
ut8 patch_buf[8];
if (sym_vaddr) {
switch (bin->hdr.f_magic) {
// TODO: Missing handling of MIPS architecture
case COFF_FILE_MACHINE_I386:
switch (rel[j].rz_type) {
case COFF_REL_I386_DIR32:
reloc.type = RZ_BIN_RELOC_32;
rz_write_le32(patch_buf, (ut32)sym_vaddr);
plen = 4;
break;
case COFF_REL_I386_REL32:
reloc.type = RZ_BIN_RELOC_32;
reloc.additive = 1;
ut32 data;
if (!rz_buf_read_le32_at(bin->b, reloc.paddr, &data)) {
break;
}
reloc.addend = data;
data += sym_vaddr - reloc.vaddr - 4;
rz_write_le32(patch_buf, (st32)data);
plen = 4;
break;
}
plen = handle_i386_relocs(bin, &reloc, sym_vaddr, patch_buf, rel[j].rz_type);
break;
case COFF_FILE_MACHINE_AMD64:
switch (rel[j].rz_type) {
case COFF_REL_AMD64_REL32:
reloc.type = RZ_BIN_RELOC_32;
reloc.additive = 1;
ut32 data;
if (!rz_buf_read_le32_at(bin->b, reloc.paddr, &data)) {
break;
}
reloc.addend = data;
data += sym_vaddr - reloc.vaddr - 4;
rz_write_le32(patch_buf, (st32)data);
plen = 4;
break;
}
plen = handle_amd64_relocs(bin, &reloc, sym_vaddr, patch_buf, rel[j].rz_type);
break;
case COFF_FILE_MACHINE_ARMNT:
switch (rel[j].rz_type) {
case COFF_REL_ARM_BRANCH24T:
case COFF_REL_ARM_BLX23T:
reloc.type = RZ_BIN_RELOC_32;
ut16 hiword;
if (!rz_buf_read_le16_at(bin->b, reloc.paddr, &hiword)) {
break;
}
ut16 loword;
if (!rz_buf_read_le16_at(bin->b, reloc.paddr + 2, &loword)) {
break;
}
ut64 dst = sym_vaddr - reloc.vaddr - 4;
if (dst & 1) {
break;
}
loword |= (ut16)(dst >> 1) & 0x7ff;
hiword |= (ut16)(dst >> 12) & 0x7ff;
rz_write_le16(patch_buf, hiword);
rz_write_le16(patch_buf + 2, loword);
plen = 4;
break;
}
plen = handle_arm_relocs(bin, &reloc, sym_vaddr, patch_buf, rel[j].rz_type);
break;
case COFF_FILE_MACHINE_ARM64:
switch (rel[j].rz_type) {
case COFF_REL_ARM64_BRANCH26:
reloc.type = RZ_BIN_RELOC_32;
ut32 data;
if (!rz_buf_read_le32_at(bin->b, reloc.paddr, &data)) {
break;
}
ut64 dst = sym_vaddr - reloc.vaddr;
data |= (ut32)((dst >> 2) & 0x3ffffffULL);
rz_write_le32(patch_buf, data);
plen = 4;
break;
}
plen = handle_arm64_relocs(bin, &reloc, sym_vaddr, patch_buf, rel[j].rz_type);
break;
default:
RZ_LOG_WARN("Unimplemented/unknown COFF architecture type: %d\n", bin->hdr.f_magic);
break;
}
}
Expand Down
12 changes: 6 additions & 6 deletions test/db/formats/coff
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ nth paddr vaddr bind type size lib name
0 0x00000064 0x00000000 LOCAL SECT 4 .text
0 0x00000064 0x00000000 GLOBAL FUNC 4 main
0 0x0000008b 0x00000030 LOCAL SECT 4 .data
vaddr paddr target type name
-----------------------------------------------------------
0x00000009 0x0000006d 0x00000030 ADD_32 .data
0x00000010 0x00000074 0x00000030 ADD_32 .data + 0x0000000f
0x0000001c 0x00000080 0x00000058 ADD_32 MessageBoxA
0x00000023 0x00000087 0x00000060 ADD_32 ExitProcess
vaddr paddr target type name
--------------------------------------------------------------------------
0x00000009 0x0000006d 0x00000030 IMAGE_REL_AMD64_REL32 .data
0x00000010 0x00000074 0x00000030 IMAGE_REL_AMD64_REL32 .data + 0x0000000f
0x0000001c 0x00000080 0x00000058 IMAGE_REL_AMD64_REL32 MessageBoxA
0x00000023 0x00000087 0x00000060 IMAGE_REL_AMD64_REL32 ExitProcess
EOF
RUN

Expand Down
Loading