hppa: use capstone disassembler
This commit is contained in:
parent
ac6276d220
commit
6cacb99e98
14 changed files with 1070 additions and 21 deletions
19
librz/arch/isa/hppa/hppa.h
Normal file
19
librz/arch/isa/hppa/hppa.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// SPDX-FileCopyrightText: 2024-2025 Anton Kochkov <anton.kochkov@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_types.h>
|
||||
#include <capstone.h>
|
||||
|
||||
#ifndef RZ_HPPA_H
|
||||
#define RZ_HPPA_H
|
||||
|
||||
typedef struct {
|
||||
csh h;
|
||||
cs_mode mode;
|
||||
cs_insn *insn;
|
||||
ut32 count;
|
||||
ut32 word;
|
||||
RzPVector /*<RzAsmTokenPattern *>*/ *token_patterns;
|
||||
} RzAsmHPPAContext;
|
||||
|
||||
#endif // RZ_HPPA_H
|
||||
117
librz/arch/isa/hppa/hppa.inc
Normal file
117
librz/arch/isa/hppa/hppa.inc
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
// SPDX-FileCopyrightText: 2023 billow <billow.fun@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2024-2025 Anton Kochkov <anton.kochkov@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
#include <capstone/hppa.h>
|
||||
#include "hppa.h"
|
||||
|
||||
static inline cs_mode hppa_cpu_to_cs_mode(const char *cpu_type) {
|
||||
if (RZ_STR_ISEMPTY(cpu_type)) {
|
||||
return CS_MODE_HPPA_11;
|
||||
}
|
||||
if (!strcmp(cpu_type, "hppa1.1")) {
|
||||
return CS_MODE_HPPA_11;
|
||||
}
|
||||
if (!strcmp(cpu_type, "hppa2.0")) {
|
||||
return CS_MODE_HPPA_20;
|
||||
}
|
||||
if (!strcmp(cpu_type, "hppa2.0w")) {
|
||||
return CS_MODE_HPPA_20W;
|
||||
}
|
||||
return CS_MODE_HPPA_11;
|
||||
}
|
||||
|
||||
static inline bool hppa_setup_cs_handle(RzAsmHPPAContext *ctx, const char *cpu, const char *features, bool big_endian) {
|
||||
const cs_mode mode = hppa_cpu_to_cs_mode(cpu) | (big_endian ? CS_MODE_BIG_ENDIAN : CS_MODE_LITTLE_ENDIAN);
|
||||
if (mode != ctx->mode) {
|
||||
cs_close(&ctx->h);
|
||||
ctx->h = 0;
|
||||
ctx->mode = mode;
|
||||
}
|
||||
|
||||
if (ctx->h != 0) {
|
||||
return true;
|
||||
}
|
||||
cs_err err = cs_open(CS_ARCH_HPPA, mode, &ctx->h);
|
||||
if (err) {
|
||||
RZ_LOG_ERROR("Failed on cs_open() with error returned: %u\n", err);
|
||||
return false;
|
||||
}
|
||||
err = cs_option(ctx->h, CS_OPT_DETAIL,
|
||||
RZ_STR_ISNOTEMPTY(features) || features == NULL ? CS_OPT_ON : CS_OPT_OFF);
|
||||
if (err) {
|
||||
RZ_LOG_ERROR("Failed on cs_open() with error returned: %u\n", err);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline ut8 hppa_op_count(const cs_insn *insn) {
|
||||
return insn->detail->hppa.op_count;
|
||||
}
|
||||
|
||||
static inline const cs_hppa_op *hppa_op_get(const cs_insn *insn, int idx) {
|
||||
if (idx >= hppa_op_count(insn)) {
|
||||
RZ_LOG_WARN("Failed to get operand%d [%d]: \"%s %s\"\n",
|
||||
idx, hppa_op_count(insn), insn->mnemonic, insn->op_str);
|
||||
rz_warn_if_reached();
|
||||
return NULL;
|
||||
}
|
||||
return &insn->detail->hppa.operands[idx];
|
||||
}
|
||||
|
||||
static inline const char *hppa_op_as_reg(const RzAsmHPPAContext *ctx, int idx) {
|
||||
const cs_hppa_op *op = hppa_op_get(ctx->insn, idx);
|
||||
if (op->type != HPPA_OP_REG) {
|
||||
RZ_LOG_WARN("Failed to get operand%d [%d]: \"%s %s\" [reg]\n",
|
||||
idx, hppa_op_count(ctx->insn), ctx->insn->mnemonic, ctx->insn->op_str);
|
||||
rz_warn_if_reached();
|
||||
return NULL;
|
||||
}
|
||||
return cs_reg_name(ctx->h, op->reg);
|
||||
}
|
||||
|
||||
static inline const char *hppa_op_as_mem(const RzAsmHPPAContext *ctx, int idx) {
|
||||
const cs_hppa_op *op = hppa_op_get(ctx->insn, idx);
|
||||
if (op->type != HPPA_OP_MEM) {
|
||||
RZ_LOG_WARN("Failed to get operand%d [%d]: \"%s %s\" [reg]\n",
|
||||
idx, hppa_op_count(ctx->insn), ctx->insn->mnemonic, ctx->insn->op_str);
|
||||
rz_warn_if_reached();
|
||||
return NULL;
|
||||
}
|
||||
return cs_reg_name(ctx->h, op->reg);
|
||||
}
|
||||
|
||||
static inline st64 hppa_op_as_imm(const RzAsmHPPAContext *ctx, int idx) {
|
||||
const cs_hppa_op *op = hppa_op_get(ctx->insn, idx);
|
||||
if (op->type != HPPA_OP_IMM) {
|
||||
RZ_LOG_WARN("Failed to get operand%d [%d]: \"%s %s\" [imm]\n",
|
||||
idx, hppa_op_count(ctx->insn), ctx->insn->mnemonic, ctx->insn->op_str);
|
||||
rz_warn_if_reached();
|
||||
return 0;
|
||||
}
|
||||
return op->imm;
|
||||
}
|
||||
|
||||
static inline st64 hppa_op_as_disp(const RzAsmHPPAContext *ctx, int idx) {
|
||||
const cs_hppa_op *op = hppa_op_get(ctx->insn, idx);
|
||||
if (op->type != HPPA_OP_DISP) {
|
||||
RZ_LOG_WARN("Failed to get operand%d [%d]: \"%s %s\" [imm]\n",
|
||||
idx, hppa_op_count(ctx->insn), ctx->insn->mnemonic, ctx->insn->op_str);
|
||||
rz_warn_if_reached();
|
||||
return 0;
|
||||
}
|
||||
return op->imm;
|
||||
}
|
||||
|
||||
static inline st64 hppa_op_as_target(const RzAsmHPPAContext *ctx, int idx) {
|
||||
const cs_hppa_op *op = hppa_op_get(ctx->insn, idx);
|
||||
if (op->type != HPPA_OP_TARGET) {
|
||||
RZ_LOG_WARN("Failed to get operand%d [%d]: \"%s %s\" [imm]\n",
|
||||
idx, hppa_op_count(ctx->insn), ctx->insn->mnemonic, ctx->insn->op_str);
|
||||
rz_warn_if_reached();
|
||||
return 0;
|
||||
}
|
||||
return op->imm;
|
||||
}
|
||||
|
|
@ -338,6 +338,7 @@ if capstone_dep.version() == 'next'
|
|||
# plugins
|
||||
arch_plugins_list += [
|
||||
'alpha_cs',
|
||||
'hppa_cs',
|
||||
'loongarch_cs',
|
||||
'xtensa_cs',
|
||||
]
|
||||
|
|
@ -346,6 +347,7 @@ if capstone_dep.version() == 'next'
|
|||
arch_plugin_sources += [
|
||||
'p/arch_alpha.c',
|
||||
'p/arch_loongarch_cs.c',
|
||||
'p/arch_hppa_cs.c',
|
||||
'p/arch_xtensa_cs.c',
|
||||
]
|
||||
|
||||
|
|
|
|||
504
librz/arch/p/analysis/analysis_hppa_cs.c
Normal file
504
librz/arch/p/analysis/analysis_hppa_cs.c
Normal file
|
|
@ -0,0 +1,504 @@
|
|||
// SPDX-FileCopyrightText: 2024 Anton Kochkov <anton.kochkov@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_types.h>
|
||||
#include <rz_lib.h>
|
||||
#include <rz_asm.h>
|
||||
#include <capstone/capstone.h>
|
||||
|
||||
#include <hppa/hppa.inc>
|
||||
|
||||
static char *hppa_reg_profile(RzAnalysis *analysis) {
|
||||
if (analysis->bits == 64) {
|
||||
const char *p =
|
||||
"=PC pc\n"
|
||||
"=SP r30\n"
|
||||
"=A0 r26\n"
|
||||
"=A1 r25\n"
|
||||
"=A2 r24\n"
|
||||
"=A3 r23\n"
|
||||
"=R0 ret0\n"
|
||||
"gpr r0 .64 0 0\n"
|
||||
"gpr r1 .64 8 0\n"
|
||||
"gpr r2 .64 16 0\n"
|
||||
"gpr r3 .64 24 0\n"
|
||||
"gpr r4 .64 32 0\n"
|
||||
"gpr r5 .64 40 0\n"
|
||||
"gpr r6 .64 48 0\n"
|
||||
"gpr r7 .64 56 0\n"
|
||||
"gpr r8 .64 64 0\n"
|
||||
"gpr r9 .64 72 0\n"
|
||||
"gpr r10 .64 80 0\n"
|
||||
"gpr r11 .64 88 0\n"
|
||||
"gpr r12 .64 96 0\n"
|
||||
"gpr r13 .64 104 0\n"
|
||||
"gpr r14 .64 112 0\n"
|
||||
"gpr r15 .64 120 0\n"
|
||||
"gpr r16 .64 128 0\n"
|
||||
"gpr r17 .64 136 0\n"
|
||||
"gpr r18 .64 144 0\n"
|
||||
"gpr r19 .64 152 0\n"
|
||||
"gpr r20 .64 160 0\n"
|
||||
"gpr r21 .64 168 0\n"
|
||||
"gpr r22 .64 176 0\n"
|
||||
"gpr r23 .64 184 0\n"
|
||||
"gpr r24 .64 192 0\n"
|
||||
"gpr r25 .64 200 0\n"
|
||||
"gpr r26 .64 208 0\n"
|
||||
"gpr r27 .64 216 0\n"
|
||||
"gpr r28 .64 224 0\n"
|
||||
"gpr r29 .64 232 0\n"
|
||||
"gpr r30 .64 240 0\n"
|
||||
"gpr r31 .64 248 0\n"
|
||||
"ctr sr0 .64 256 0\n"
|
||||
"ctr sr1 .64 264 0\n"
|
||||
"ctr sr2 .64 272 0\n"
|
||||
"ctr sr3 .64 280 0\n"
|
||||
"ctr sr4 .64 288 0\n"
|
||||
"ctr sr5 .64 296 0\n"
|
||||
"ctr sr6 .64 304 0\n"
|
||||
"ctr sr7 .64 312 0\n"
|
||||
"flg psw .64 320 0\n";
|
||||
return strdup(p);
|
||||
} else {
|
||||
const char *p =
|
||||
"=PC pc\n"
|
||||
"=SP r30\n"
|
||||
"=A0 r26\n"
|
||||
"=A1 r25\n"
|
||||
"=A2 r24\n"
|
||||
"=A3 r23\n"
|
||||
"gpr r0 .32 0 0\n"
|
||||
"gpr r1 .32 4 0\n"
|
||||
"gpr r2 .32 8 0\n"
|
||||
"gpr r3 .32 12 0\n"
|
||||
"gpr r4 .32 16 0\n"
|
||||
"gpr r5 .32 20 0\n"
|
||||
"gpr r6 .32 24 0\n"
|
||||
"gpr r7 .32 28 0\n"
|
||||
"gpr r8 .32 32 0\n"
|
||||
"gpr r9 .32 36 0\n"
|
||||
"gpr r10 .32 40 0\n"
|
||||
"gpr r11 .32 44 0\n"
|
||||
"gpr r12 .32 48 0\n"
|
||||
"gpr r13 .32 52 0\n"
|
||||
"gpr r14 .32 56 0\n"
|
||||
"gpr r15 .32 60 0\n"
|
||||
"gpr r16 .32 64 0\n"
|
||||
"gpr r17 .32 68 0\n"
|
||||
"gpr r18 .32 72 0\n"
|
||||
"gpr r19 .32 76 0\n"
|
||||
"gpr r20 .32 80 0\n"
|
||||
"gpr r21 .32 84 0\n"
|
||||
"gpr r22 .32 88 0\n"
|
||||
"gpr r23 .32 92 0\n"
|
||||
"gpr r24 .32 96 0\n"
|
||||
"gpr r25 .32 100 0\n"
|
||||
"gpr r26 .32 104 0\n"
|
||||
"gpr r27 .32 108 0\n"
|
||||
"gpr r28 .32 112 0\n"
|
||||
"gpr r29 .32 116 0\n"
|
||||
"gpr r30 .32 120 0\n"
|
||||
"gpr r31 .32 124 0\n"
|
||||
"ctr sr0 .32 128 0\n"
|
||||
"ctr sr1 .32 132 0\n"
|
||||
"ctr sr2 .32 136 0\n"
|
||||
"ctr sr3 .32 140 0\n"
|
||||
"ctr sr4 .32 144 0\n"
|
||||
"ctr sr5 .32 148 0\n"
|
||||
"ctr sr6 .32 152 0\n"
|
||||
"ctr sr7 .32 156 0\n"
|
||||
"flg psw .32 160 0\n";
|
||||
return strdup(p);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void hppa_fillval(const RzReg *rz_reg, csh handle, RzAnalysisValue *av, cs_hppa_op *hop) {
|
||||
switch (hop->type) {
|
||||
case HPPA_OP_INVALID:
|
||||
default:
|
||||
av->type = RZ_ANALYSIS_VAL_UNK;
|
||||
break;
|
||||
case HPPA_OP_IMM:
|
||||
case HPPA_OP_DISP:
|
||||
case HPPA_OP_TARGET:
|
||||
av->type = RZ_ANALYSIS_VAL_IMM;
|
||||
av->imm = hop->imm;
|
||||
break;
|
||||
case HPPA_OP_REG:
|
||||
case HPPA_OP_IDX_REG:
|
||||
av->type = RZ_ANALYSIS_VAL_REG;
|
||||
av->reg = rz_reg_get(rz_reg, cs_reg_name(handle, hop->reg), RZ_REG_TYPE_ANY);
|
||||
break;
|
||||
case HPPA_OP_MEM:
|
||||
av->type = RZ_ANALYSIS_VAL_MEM;
|
||||
// FIXME: Handle also the space
|
||||
av->reg = rz_reg_get(rz_reg, cs_reg_name(handle, hop->mem.base), RZ_REG_TYPE_ANY);
|
||||
av->delta = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void hppa_fillvals(const RzAsmHPPAContext *ctx, RzAnalysis *a, RzAnalysisOp *op) {
|
||||
uint8_t srci = 0;
|
||||
cs_hppa *hc = &ctx->insn->detail->hppa;
|
||||
for (uint8_t i = 0; i < hc->op_count; ++i) {
|
||||
cs_hppa_op *hop = &hc->operands[i];
|
||||
RzAnalysisValue *av = rz_analysis_value_new();
|
||||
hppa_fillval(a->reg, ctx->h, av, hop);
|
||||
if (hop->access & CS_AC_READ) {
|
||||
av->access |= RZ_ANALYSIS_ACC_R;
|
||||
op->src[srci++] = av;
|
||||
}
|
||||
if (hop->access & CS_AC_WRITE) {
|
||||
av->access |= RZ_ANALYSIS_ACC_W;
|
||||
if (srci > 0 && av == op->src[srci - 1]) {
|
||||
av = rz_mem_dup(av, sizeof(RzAnalysisValue));
|
||||
}
|
||||
op->dst = av;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static RzStructuredData *hppa_opex(csh handle, cs_insn *insn) {
|
||||
if (!insn->detail) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RzStructuredData *root = rz_structured_data_new_map();
|
||||
if (!root) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RzStructuredData *opex = rz_structured_data_map_add_map(root, "opex");
|
||||
if (!opex) {
|
||||
rz_structured_data_free(root);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RzStructuredData *operands = rz_structured_data_map_add_array(opex, "operands");
|
||||
cs_hppa *hpc = &insn->detail->hppa;
|
||||
for (st32 i = 0; i < hpc->op_count; i++) {
|
||||
cs_hppa_op *op = hpc->operands + i;
|
||||
RzStructuredData *operand = rz_structured_data_array_add_map(operands);
|
||||
switch (op->type) {
|
||||
case HPPA_OP_REG: {
|
||||
rz_structured_data_map_add_string(operand, "type", "reg");
|
||||
rz_structured_data_map_add_string(operand, "value", cs_reg_name(handle, op->reg));
|
||||
break;
|
||||
}
|
||||
case HPPA_OP_IDX_REG: {
|
||||
rz_structured_data_map_add_string(operand, "type", "idx_reg");
|
||||
rz_structured_data_map_add_string(operand, "value", cs_reg_name(handle, op->reg));
|
||||
break;
|
||||
}
|
||||
case HPPA_OP_IMM: {
|
||||
rz_structured_data_map_add_string(operand, "type", "imm");
|
||||
rz_structured_data_map_add_signed(operand, "value", op->imm);
|
||||
break;
|
||||
}
|
||||
case HPPA_OP_DISP: {
|
||||
rz_structured_data_map_add_string(operand, "type", "disp");
|
||||
rz_structured_data_map_add_signed(operand, "value", op->imm);
|
||||
break;
|
||||
}
|
||||
case HPPA_OP_TARGET: {
|
||||
rz_structured_data_map_add_string(operand, "type", "target");
|
||||
rz_structured_data_map_add_signed(operand, "value", op->imm);
|
||||
break;
|
||||
}
|
||||
case HPPA_OP_MEM: {
|
||||
rz_structured_data_map_add_string(operand, "type", "mem");
|
||||
if (op->mem.base != HPPA_REG_INVALID) {
|
||||
rz_structured_data_map_add_string(operand, "base", cs_reg_name(handle, op->mem.base));
|
||||
}
|
||||
if (op->mem.space != HPPA_REG_INVALID) {
|
||||
rz_structured_data_map_add_string(operand, "space", cs_reg_name(handle, op->mem.space));
|
||||
} else {
|
||||
rz_structured_data_map_add_string(operand, "space", "unavailable");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
rz_structured_data_map_add_string(operand, "type", "invalid");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
static void hppa_op_set_type(const RzAsmHPPAContext *ctx, RzAnalysisOp *op) {
|
||||
switch (ctx->insn->id) {
|
||||
default:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_UNK;
|
||||
break;
|
||||
case HPPA_INS_NOP:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_NOP;
|
||||
break;
|
||||
case HPPA_INS_ADD:
|
||||
case HPPA_INS_ADDI:
|
||||
case HPPA_INS_ADDIO:
|
||||
case HPPA_INS_ADDIT:
|
||||
case HPPA_INS_ADDITO:
|
||||
case HPPA_INS_ADDIL:
|
||||
case HPPA_INS_ADDC:
|
||||
case HPPA_INS_ADDCO:
|
||||
case HPPA_INS_ADDL:
|
||||
case HPPA_INS_ADDO:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_ADD;
|
||||
break;
|
||||
case HPPA_INS_ADDB:
|
||||
case HPPA_INS_ADDIB:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_JMP;
|
||||
op->jump = ctx->insn->address + hppa_op_as_target(ctx, 2);
|
||||
break;
|
||||
case HPPA_INS_ADDBT:
|
||||
case HPPA_INS_ADDBF:
|
||||
case HPPA_INS_ADDIBT:
|
||||
case HPPA_INS_ADDIBF:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
|
||||
op->jump = ctx->insn->address + hppa_op_as_target(ctx, 2);
|
||||
op->fail = ctx->insn->address + ctx->insn->size;
|
||||
break;
|
||||
case HPPA_INS_AND:
|
||||
case HPPA_INS_ANDCM:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_AND;
|
||||
break;
|
||||
case HPPA_INS_BB:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
|
||||
op->jump = ctx->insn->address + hppa_op_as_target(ctx, 2);
|
||||
op->fail = ctx->insn->address + ctx->insn->size;
|
||||
break;
|
||||
case HPPA_INS_BE:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_IRCALL;
|
||||
op->reg = hppa_op_as_mem(ctx, 1);
|
||||
break;
|
||||
case HPPA_INS_BL:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_IRCALL;
|
||||
op->jump = ctx->insn->address + hppa_op_as_target(ctx, 0);
|
||||
break;
|
||||
case HPPA_INS_BLE:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_IRCALL;
|
||||
op->reg = hppa_op_as_mem(ctx, 1);
|
||||
break;
|
||||
case HPPA_INS_BLR:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_IRJMP;
|
||||
op->reg = hppa_op_as_reg(ctx, 0);
|
||||
break;
|
||||
case HPPA_INS_BV:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_IRCALL;
|
||||
// FIXME: Should be result of the *two* registers actually
|
||||
op->reg = hppa_op_as_mem(ctx, 1);
|
||||
break;
|
||||
case HPPA_INS_BVB:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
|
||||
op->jump = ctx->insn->address + hppa_op_as_target(ctx, 1);
|
||||
break;
|
||||
case HPPA_INS_GATE:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_JMP;
|
||||
op->jump = hppa_op_as_target(ctx, 0);
|
||||
break;
|
||||
case HPPA_INS_LDB:
|
||||
case HPPA_INS_LDBS:
|
||||
case HPPA_INS_LDCD:
|
||||
case HPPA_INS_LDCW:
|
||||
case HPPA_INS_LDCWS:
|
||||
case HPPA_INS_LDD:
|
||||
case HPPA_INS_LDDA:
|
||||
case HPPA_INS_LDH:
|
||||
case HPPA_INS_LDHS:
|
||||
case HPPA_INS_LDI:
|
||||
case HPPA_INS_LDW:
|
||||
case HPPA_INS_LDWA:
|
||||
case HPPA_INS_LDWAS:
|
||||
case HPPA_INS_LDWM:
|
||||
case HPPA_INS_LDWS:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_LOAD;
|
||||
const cs_hppa_op *op1 = hppa_op_get(ctx->insn, 1);
|
||||
if (op1->type == HPPA_OP_REG && op1->reg == HPPA_REG_GR30 /* SP */) {
|
||||
op->stackop = RZ_ANALYSIS_STACK_GET;
|
||||
op->stackptr = 0;
|
||||
}
|
||||
if (op1->type == HPPA_OP_IMM) {
|
||||
op->ptr = (st64)hppa_op_as_disp(ctx, 0);
|
||||
}
|
||||
break;
|
||||
case HPPA_INS_LDSID:
|
||||
case HPPA_INS_LDHX:
|
||||
case HPPA_INS_LDBX:
|
||||
case HPPA_INS_LDCWX:
|
||||
case HPPA_INS_LDWAX:
|
||||
case HPPA_INS_LDWX:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_LOAD;
|
||||
break;
|
||||
case HPPA_INS_LDIL:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
|
||||
break;
|
||||
case HPPA_INS_LCI:
|
||||
case HPPA_INS_LDO:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_LEA;
|
||||
break;
|
||||
case HPPA_INS_MOVB:
|
||||
case HPPA_INS_MOVIB:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
|
||||
op->jump = ctx->insn->address + hppa_op_as_target(ctx, 2);
|
||||
op->fail = ctx->insn->address + ctx->insn->size;
|
||||
break;
|
||||
case HPPA_INS_OR:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_OR;
|
||||
break;
|
||||
case HPPA_INS_CALL:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_CALL;
|
||||
op->jump = hppa_op_as_target(ctx, 0);
|
||||
break;
|
||||
case HPPA_INS_COMIB:
|
||||
case HPPA_INS_COMIBT:
|
||||
case HPPA_INS_COMIBF:
|
||||
case HPPA_INS_COMB:
|
||||
case HPPA_INS_COMBT:
|
||||
case HPPA_INS_COMBF:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
|
||||
op->jump = ctx->insn->address + hppa_op_as_target(ctx, 2);
|
||||
op->fail = ctx->insn->address + ctx->insn->size;
|
||||
break;
|
||||
case HPPA_INS_STB:
|
||||
case HPPA_INS_STBS:
|
||||
case HPPA_INS_STBY:
|
||||
case HPPA_INS_STBYS:
|
||||
case HPPA_INS_STD:
|
||||
case HPPA_INS_STDA:
|
||||
case HPPA_INS_STDBY:
|
||||
case HPPA_INS_STH:
|
||||
case HPPA_INS_STHS:
|
||||
case HPPA_INS_STW:
|
||||
case HPPA_INS_STWA:
|
||||
case HPPA_INS_STWAS:
|
||||
case HPPA_INS_STWS:
|
||||
case HPPA_INS_STWM:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_STORE;
|
||||
const cs_hppa_op *op2 = hppa_op_get(ctx->insn, 2);
|
||||
if (op2->type == HPPA_OP_REG && op2->reg == HPPA_REG_GR30 /* SP */) {
|
||||
op->stackop = RZ_ANALYSIS_STACK_SET;
|
||||
op->stackptr = 0;
|
||||
}
|
||||
if (op2->type == HPPA_OP_IMM) {
|
||||
op->ptr = (st64)hppa_op_as_disp(ctx, 1);
|
||||
}
|
||||
break;
|
||||
case HPPA_INS_SUB:
|
||||
case HPPA_INS_SUBB:
|
||||
case HPPA_INS_SUBBO:
|
||||
case HPPA_INS_SUBI:
|
||||
case HPPA_INS_SUBIO:
|
||||
case HPPA_INS_SUBO:
|
||||
case HPPA_INS_SUBT:
|
||||
case HPPA_INS_SUBTO:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_SUB;
|
||||
break;
|
||||
case HPPA_INS_XOR:
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_XOR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
hppa_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask) {
|
||||
if (!(a && op && data && len > 0)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
RzAsmHPPAContext *ctx = a->plugin_data;
|
||||
if (!hppa_setup_cs_handle(ctx, a->cpu, NULL, a->big_endian)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
op->size = 4;
|
||||
|
||||
ctx->insn = NULL;
|
||||
ctx->count = cs_disasm(ctx->h, (const ut8 *)data, len, addr, 1, &ctx->insn);
|
||||
if (ctx->count <= 0 || !ctx->insn) {
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_ILL;
|
||||
if (mask & RZ_ANALYSIS_OP_MASK_DISASM) {
|
||||
op->mnemonic = strdup("invalid");
|
||||
}
|
||||
goto beach;
|
||||
}
|
||||
|
||||
if (mask & RZ_ANALYSIS_OP_MASK_DISASM) {
|
||||
op->mnemonic = rz_str_newf("%s%s%s",
|
||||
ctx->insn->mnemonic, ctx->insn->op_str[0] ? " " : "", ctx->insn->op_str);
|
||||
}
|
||||
op->size = ctx->insn->size;
|
||||
op->id = (int)ctx->insn->id;
|
||||
op->addr = ctx->insn->address;
|
||||
hppa_op_set_type(ctx, op);
|
||||
if (mask & RZ_ANALYSIS_OP_MASK_OPEX) {
|
||||
op->opex = hppa_opex(ctx->h, ctx->insn);
|
||||
}
|
||||
if (mask & RZ_ANALYSIS_OP_MASK_VAL) {
|
||||
hppa_fillvals(ctx, a, op);
|
||||
}
|
||||
|
||||
beach:
|
||||
cs_free(ctx->insn, ctx->count);
|
||||
return op->size;
|
||||
}
|
||||
|
||||
static int hppa_archinfo(RzAnalysis *a, RzAnalysisInfoType query) {
|
||||
switch (query) {
|
||||
case RZ_ANALYSIS_ARCHINFO_MIN_OP_SIZE:
|
||||
return 4;
|
||||
case RZ_ANALYSIS_ARCHINFO_MAX_OP_SIZE:
|
||||
return 4;
|
||||
case RZ_ANALYSIS_ARCHINFO_TEXT_ALIGN:
|
||||
case RZ_ANALYSIS_ARCHINFO_DATA_ALIGN:
|
||||
case RZ_ANALYSIS_ARCHINFO_CAN_USE_POINTERS:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static bool hppa_init(void **u) {
|
||||
if (!u) {
|
||||
return false;
|
||||
}
|
||||
RzAsmHPPAContext *ctx = RZ_NEW0(RzAsmHPPAContext);
|
||||
if (!ctx) {
|
||||
return false;
|
||||
}
|
||||
*u = ctx;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool hppa_fini(void *u) {
|
||||
if (!u) {
|
||||
return true;
|
||||
}
|
||||
RzAsmHPPAContext *ctx = u;
|
||||
cs_close(&ctx->h);
|
||||
free(u);
|
||||
return true;
|
||||
}
|
||||
|
||||
RzAnalysisPlugin rz_analysis_plugin_hppa_cs = {
|
||||
.name = "hppa",
|
||||
.desc = "Capstone HP PA-RISC analysis plugin",
|
||||
.author = "xvilka",
|
||||
.license = "LGPL3",
|
||||
.arch = "hppa",
|
||||
.bits = 32 | 64,
|
||||
.get_reg_profile = hppa_reg_profile,
|
||||
.archinfo = hppa_archinfo,
|
||||
.op = hppa_op,
|
||||
.init = hppa_init,
|
||||
.fini = hppa_fini,
|
||||
};
|
||||
|
||||
#ifndef RZ_PLUGIN_INCORE
|
||||
RZ_API RzLibStruct rizin_plugin = {
|
||||
.type = RZ_LIB_TYPE_ANALYSIS,
|
||||
.data = &rz_analysis_plugin_hppa_cs,
|
||||
.version = RZ_VERSION
|
||||
};
|
||||
#endif
|
||||
9
librz/arch/p/arch_hppa_cs.c
Normal file
9
librz/arch/p/arch_hppa_cs.c
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// SPDX-FileCopyrightText: 2024 RizinOrg <info@rizin.re>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <deprecated_arch_helper.h>
|
||||
|
||||
#include "analysis/analysis_hppa_cs.c"
|
||||
#include "asm/asm_hppa_cs.c"
|
||||
|
||||
RZ_ARCH_PLUGIN_DEFINE_DEPRECATED(hppa_cs);
|
||||
123
librz/arch/p/asm/asm_hppa_cs.c
Normal file
123
librz/arch/p/asm/asm_hppa_cs.c
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
// SPDX-FileCopyrightText: 2024 Anton Kochkov <anton.kochkov@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_asm.h>
|
||||
#include <rz_lib.h>
|
||||
#include <capstone/capstone.h>
|
||||
|
||||
static int disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) {
|
||||
if (!buf || !op || !a->plugin_data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
RzAsmHPPAContext *ctx = a->plugin_data;
|
||||
if (!hppa_setup_cs_handle(ctx, a->cpu, a->features, a->big_endian)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
op->size = 4;
|
||||
|
||||
ctx->insn = NULL;
|
||||
ctx->count = cs_disasm(ctx->h, buf, len, a->pc, 1, &ctx->insn);
|
||||
if (ctx->count <= 0) {
|
||||
RZ_LOG_ERROR("HPPA: disasm error @ 0x%08" PFMT64x ", len = %d\n", a->pc, len);
|
||||
rz_asm_op_set_asm(op, "invalid");
|
||||
goto beach;
|
||||
}
|
||||
|
||||
op->size = ctx->insn->size;
|
||||
rz_asm_op_setf_asm(op, "%s%s%s",
|
||||
ctx->insn->mnemonic, RZ_STR_ISNOTEMPTY(ctx->insn->op_str) ? " " : "", ctx->insn->op_str);
|
||||
|
||||
op->asm_toks = rz_asm_tokenize_asm_regex(&op->buf_asm, ctx->token_patterns);
|
||||
|
||||
beach:
|
||||
cs_free(ctx->insn, ctx->count);
|
||||
ctx->insn = NULL;
|
||||
ctx->count = 0;
|
||||
return op->size;
|
||||
}
|
||||
|
||||
#define TOKEN(_type, _pat) \
|
||||
do { \
|
||||
RzAsmTokenPattern *pat = RZ_NEW0(RzAsmTokenPattern); \
|
||||
pat->type = RZ_ASM_TOKEN_##_type; \
|
||||
pat->pattern = strdup(_pat); \
|
||||
rz_pvector_push(pvec, pat); \
|
||||
} while (0)
|
||||
|
||||
static RZ_OWN RzPVector /*<RzAsmTokenPattern *>*/ *get_token_patterns() {
|
||||
RzPVector *pvec = rz_pvector_new(rz_asm_token_pattern_free);
|
||||
if (!pvec) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TOKEN(META, "(\\[|\\]|-)");
|
||||
TOKEN(META, "(\\+[rc]?)");
|
||||
|
||||
TOKEN(NUMBER, "(0x[[:digit:]abcdef]+)");
|
||||
|
||||
TOKEN(REGISTER, "([cfstr]{1,2}[[:digit:]]{1,2})|(sp|psw|pc|rp|dp|ret0|ret1|rctr|pidr1|pidr2|pidr3|ccr|sar|iva|eiem|itmr|pcsq|pcoq|iir|isr|ior|ipsw|eirr|flags)");
|
||||
|
||||
TOKEN(MNEMONIC, "([[:alpha:]]+[[:alnum:]\\,]*([[:alpha:]]+|(<|>|=|\\*| )+))");
|
||||
|
||||
TOKEN(SEPARATOR, "([[:blank:]]+)|([,;\\(\\)\\{\\}:])");
|
||||
|
||||
TOKEN(NUMBER, "([[:digit:]]+)");
|
||||
|
||||
return pvec;
|
||||
}
|
||||
|
||||
static bool init(void **u) {
|
||||
if (!u) {
|
||||
return false;
|
||||
}
|
||||
// u = RzAsm.plugin_data
|
||||
RzAsmHPPAContext *ctx = NULL;
|
||||
if (*u) {
|
||||
rz_mem_memzero(*u, sizeof(RzAsmHPPAContext));
|
||||
ctx = *u;
|
||||
} else {
|
||||
ctx = RZ_NEW0(RzAsmHPPAContext);
|
||||
if (!ctx) {
|
||||
return false;
|
||||
}
|
||||
*u = ctx;
|
||||
}
|
||||
ctx->token_patterns = get_token_patterns();
|
||||
rz_asm_compile_token_patterns(ctx->token_patterns);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool fini(void *u) {
|
||||
if (!u) {
|
||||
return true;
|
||||
}
|
||||
RzAsmHPPAContext *ctx = u;
|
||||
cs_close(&ctx->h);
|
||||
rz_pvector_free(ctx->token_patterns);
|
||||
free(u);
|
||||
return true;
|
||||
}
|
||||
|
||||
RzAsmPlugin rz_asm_plugin_hppa_cs = {
|
||||
.name = "hppa",
|
||||
.arch = "hppa",
|
||||
.author = "xvilka",
|
||||
.license = "LGPL3",
|
||||
.bits = 32 | 64,
|
||||
.endian = RZ_SYS_ENDIAN_LITTLE | RZ_SYS_ENDIAN_BIG,
|
||||
.cpus = "hppa1.1,hppa2.0,hppa2.0w",
|
||||
.desc = "HP PA-RISC Capstone-based disassembler",
|
||||
.disassemble = &disassemble,
|
||||
.init = &init,
|
||||
.fini = &fini,
|
||||
};
|
||||
|
||||
#ifndef RZ_PLUGIN_INCORE
|
||||
RZ_API RzLibStruct rizin_plugin = {
|
||||
.type = RZ_LIB_TYPE_ASM,
|
||||
.data = &rz_asm_plugin_hppa_cs,
|
||||
.version = RZ_VERSION
|
||||
};
|
||||
#endif
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
#define SPARC_OFFSET_PLT_ENTRY_FROM_GOT_ADDR -0x6
|
||||
#define X86_OFFSET_PLT_ENTRY_FROM_GOT_ADDR -0x6
|
||||
#define X86_PLT_ENTRY_SIZE 0x10
|
||||
#define PARISC_PLT_ENTRY_SIZE 0x10
|
||||
|
||||
#define UNHANDL_IMPORT(NAME, NUM) \
|
||||
RZ_LOG_WARN(NAME ": Unhandled ELF relocation for import %d\n", NUM); \
|
||||
|
|
@ -64,6 +65,35 @@ static ut64 get_import_addr_mips(ELFOBJ *bin, RzBinElfReloc *rel) {
|
|||
return plt_addr;
|
||||
}
|
||||
|
||||
static ut64 get_import_addr_parisc(ELFOBJ *bin, RzBinElfReloc *rel) {
|
||||
// Get PLT section
|
||||
RzBinElfSection *plt_sec = Elf_(rz_bin_elf_get_section_with_name)(bin, ".plt");
|
||||
if (!plt_sec) {
|
||||
return UT64_MAX;
|
||||
}
|
||||
ut64 plt_addr = plt_sec->rva;
|
||||
ut64 got_addr = 0;
|
||||
|
||||
// Get GOT section
|
||||
RzBinElfSection *got_sec = Elf_(rz_bin_elf_get_section_with_name)(bin, ".got");
|
||||
if (got_sec) {
|
||||
got_addr = got_sec->rva;
|
||||
}
|
||||
|
||||
switch (rel->type) {
|
||||
case R_PARISC_IPLT:
|
||||
// IPLT uses direct PLT entries
|
||||
return plt_addr + (rel->sym + 1) * PARISC_PLT_ENTRY_SIZE;
|
||||
default:
|
||||
// For other relocation types, try GOT first, then PLT
|
||||
if (got_sec) {
|
||||
const ut64 got_entry_size = 8; // 64-bit pointers
|
||||
return got_addr + rel->sym * got_entry_size;
|
||||
}
|
||||
return plt_addr + (rel->sym + 1) * PARISC_PLT_ENTRY_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Determines and returns the import address for the given relocation
|
||||
* for the Hexagon architecture.
|
||||
|
|
@ -350,6 +380,8 @@ static ut64 get_import_addr_aux(ELFOBJ *bin, RzBinElfReloc *reloc) {
|
|||
case EM_MIPS_X:
|
||||
case EM_IMG1:
|
||||
return get_import_addr_mips(bin, reloc);
|
||||
case EM_PARISC:
|
||||
return get_import_addr_parisc(bin, reloc);
|
||||
case EM_RISCV:
|
||||
return get_import_addr_riscv(bin, reloc);
|
||||
case EM_SPARC:
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ struct class_translation {
|
|||
const char *name;
|
||||
};
|
||||
|
||||
struct cpu_mips_translation {
|
||||
struct cpu_arch_translation {
|
||||
Elf_(Word) arch;
|
||||
const char *name;
|
||||
};
|
||||
|
|
@ -233,7 +233,7 @@ static const struct class_translation class_translation_table[] = {
|
|||
{ ELFCLASS64, "ELF64" }
|
||||
};
|
||||
|
||||
static const struct cpu_mips_translation gnu_mips_mach_translation_table[] = {
|
||||
static const struct cpu_arch_translation gnu_mips_mach_translation_table[] = {
|
||||
{ EF_MIPS_MACH_3900, "3900 " },
|
||||
{ EF_MIPS_MACH_4010, "4010 " },
|
||||
{ EF_MIPS_MACH_4100, "4100 " },
|
||||
|
|
@ -272,7 +272,7 @@ static const struct mips_bits_translation mips_bits_translation_table[] = {
|
|||
{ EF_MIPS_ARCH_64R6, 64 },
|
||||
};
|
||||
|
||||
static const struct cpu_mips_translation gnu_mips_arch_translation_table32[] = {
|
||||
static const struct cpu_arch_translation gnu_mips_arch_translation_table32[] = {
|
||||
{ EF_MIPS_ARCH_1, "mips32" },
|
||||
{ EF_MIPS_ARCH_2, "mips2" },
|
||||
{ EF_MIPS_ARCH_3, "mips3" },
|
||||
|
|
@ -286,7 +286,7 @@ static const struct cpu_mips_translation gnu_mips_arch_translation_table32[] = {
|
|||
{ EF_MIPS_ARCH_64R6, "mips64r6" },
|
||||
};
|
||||
|
||||
static const struct cpu_mips_translation gnu_mips_arch_translation_table64[] = {
|
||||
static const struct cpu_arch_translation gnu_mips_arch_translation_table64[] = {
|
||||
{ EF_MIPS_ARCH_1, "mips64" }, // also used for generic mips, so we default to mips64
|
||||
{ EF_MIPS_ARCH_2, "mips64r2" },
|
||||
{ EF_MIPS_ARCH_3, "mips64r3" },
|
||||
|
|
@ -300,6 +300,13 @@ static const struct cpu_mips_translation gnu_mips_arch_translation_table64[] = {
|
|||
{ EF_MIPS_ARCH_64R6, "mips64r6" },
|
||||
};
|
||||
|
||||
static const struct cpu_arch_translation cpu_hppa_translation_table[] = {
|
||||
{ EFA_PARISC_1_0, "hppa1.0" },
|
||||
{ EFA_PARISC_1_1, "hppa2.0" }, // In practice many ELF file set as 1.1 version
|
||||
// contain 2.0 opcodes
|
||||
{ EFA_PARISC_2_0, "hppa2.0" },
|
||||
};
|
||||
|
||||
static const struct arch_translation arch_translation_table[] = {
|
||||
{ EM_ALPHA, "alpha" },
|
||||
{ EM_ARC, "arc" },
|
||||
|
|
@ -754,6 +761,10 @@ static bool arch_is_arcompact(ELFOBJ *bin) {
|
|||
bin->ehdr.e_machine == EM_ARC_COMPACT3;
|
||||
}
|
||||
|
||||
static bool arch_is_parisc(ELFOBJ *bin) {
|
||||
return bin->ehdr.e_machine == EM_PARISC;
|
||||
}
|
||||
|
||||
static char *read_elf_intrp(ELFOBJ *bin, ut64 addr, size_t size) {
|
||||
char *str = malloc(size + 1);
|
||||
if (!str) {
|
||||
|
|
@ -1060,6 +1071,18 @@ static char *get_abi_mips(ELFOBJ *bin) {
|
|||
return rz_strbuf_drain_nofree(&sb);
|
||||
}
|
||||
|
||||
static char *get_cpu_hppa(ELFOBJ *bin) {
|
||||
Elf_(Word) hppa_arch = bin->ehdr.e_flags & EF_PARISC_ARCH;
|
||||
|
||||
for (size_t i = 0; i < RZ_ARRAY_SIZE(cpu_hppa_translation_table); i++) {
|
||||
if (hppa_arch == cpu_hppa_translation_table[i].arch) {
|
||||
return strdup(cpu_hppa_translation_table[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
return strdup(" Unknown HP PARISC ISA");
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief List all imported lib
|
||||
* \param elf binary
|
||||
|
|
@ -1647,6 +1670,8 @@ RZ_OWN char *Elf_(rz_bin_elf_get_cpu)(RZ_NONNULL ELFOBJ *bin) {
|
|||
// Capstone has only v8 and v9 for now.
|
||||
// So no finer distinction necessary.
|
||||
return bin->ehdr.e_machine == EM_SPARC ? strdup("v8") : strdup("v9");
|
||||
} else if (arch_is_parisc(bin)) {
|
||||
return get_cpu_hppa(bin);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -1082,6 +1082,22 @@ static RzBinReloc *reloc_convert_alpha(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT
|
|||
}
|
||||
}
|
||||
|
||||
static RzBinReloc *reloc_convert_parisc(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT) {
|
||||
ut64 P = rel->vaddr;
|
||||
|
||||
switch (rel->type) {
|
||||
case R_PARISC_NONE:
|
||||
return reloc_convert_set(bin, rel, 0, "R_PARISC_NONE");
|
||||
case R_PARISC_DIR32: ADD(32, 0, "R_PARISC_DIR32", RZ_RELOC_BASE_UNKNOWN);
|
||||
case R_PARISC_DIR64: ADD(64, 0, "R_PARISC_DIR64", RZ_RELOC_BASE_UNKNOWN);
|
||||
case R_PARISC_COPY: ADD(64, 0, "R_PARISC_COPY", RZ_RELOC_BASE_UNKNOWN); // copy symbol at runtime
|
||||
case R_PARISC_IPLT: ADD(64, -P, "R_PARISC_IPLT", RZ_RELOC_BASE_PLT_SYMBOL);
|
||||
case R_PARISC_EPLT: ADD(64, -P, "R_PARISC_EPLT", RZ_RELOC_BASE_PLT_SYMBOL);
|
||||
|
||||
// FIXME: Quite a few relocatons missing here.
|
||||
default: UNSUPP("PARISC");
|
||||
}
|
||||
}
|
||||
static RzBinReloc *reloc_convert_hexagon(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT) {
|
||||
ut64 P = rel->vaddr;
|
||||
|
||||
|
|
@ -1430,7 +1446,8 @@ RZ_OWN RzBinReloc *Elf_(rz_bin_elf_convert_relocation)(RZ_NONNULL ELFOBJ *bin, R
|
|||
case EM_IAMCU: ARCH_MISSING("EM_IAMCU");
|
||||
case EM_860: ARCH_MISSING("EM_860");
|
||||
case EM_S370: ARCH_MISSING("EM_S370");
|
||||
case EM_PARISC: ARCH_MISSING("EM_PARISC");
|
||||
case EM_PARISC:
|
||||
return reloc_convert_parisc(bin, rel, GOT);
|
||||
case EM_VPP500: ARCH_MISSING("EM_VPP500");
|
||||
case EM_960: ARCH_MISSING("EM_960");
|
||||
case EM_S390: ARCH_MISSING("EM_S390");
|
||||
|
|
|
|||
|
|
@ -2011,6 +2011,47 @@ static void patch_reloc_alpha(RZ_INOUT RzBuffer *buf_patched, const ut64 patch_a
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Patches the opcode at a given address depending on the relocation type.
|
||||
*
|
||||
* NOTE: Some relocation symbols are not yet implemented
|
||||
*
|
||||
* \param buf_patched Buffer from which the opcode is read and the patched opcode is written to.
|
||||
* \param patch_addr The address of the opcode being patched.
|
||||
* \param rel_type The relocation type.
|
||||
* \param big_endian The endianness - true if BE, false if LE
|
||||
* \param fs Formular values to calculate the new relocation value.
|
||||
*/
|
||||
static void patch_reloc_parisc(RZ_INOUT RzBuffer *buf_patched, const ut64 patch_addr, const int rel_type, bool big_endian, RelocFormularSymbols *fs) {
|
||||
rz_return_if_fail(buf_patched && fs);
|
||||
ut8 buf[8] = { 0 };
|
||||
ut64 val = 0;
|
||||
|
||||
switch (rel_type) {
|
||||
default:
|
||||
UNHANDL_DEF("PARISC", rel_type);
|
||||
return;
|
||||
case R_PARISC_COPY:
|
||||
/* fall-thru */
|
||||
case R_PARISC_NONE:
|
||||
return;
|
||||
case R_PARISC_DIR32: // S + A
|
||||
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
|
||||
val = rz_read_ble32(buf, big_endian);
|
||||
val += fs->S + fs->A;
|
||||
rz_write_ble32(buf, val, big_endian);
|
||||
rz_buf_write_at(buf_patched, patch_addr, buf, 4);
|
||||
return;
|
||||
case R_PARISC_DIR64: // S + A
|
||||
rz_buf_read_at(buf_patched, patch_addr, buf, 8);
|
||||
val = rz_read_ble64(buf, big_endian);
|
||||
val += fs->S + fs->A;
|
||||
rz_write_ble64(buf, val, big_endian);
|
||||
rz_buf_write_at(buf_patched, patch_addr, buf, 8);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#undef UNHANDL
|
||||
#undef UNHANDL_DEF
|
||||
|
||||
|
|
@ -2080,13 +2121,15 @@ void Elf_(rz_bin_elf_patch_relocation)(RZ_NONNULL ELFOBJ *bin, RZ_NONNULL RzBinE
|
|||
case EM_SPARCV9:
|
||||
patch_reloc_sparc(bin->buf_patched, patch_addr, rel->type, big_endian, &formular_sym);
|
||||
break;
|
||||
case EM_PARISC:
|
||||
patch_reloc_parisc(bin->buf_patched, patch_addr, rel->type, big_endian, &formular_sym);
|
||||
break;
|
||||
case EM_M32: ARCH_MISSING("EM_M32");
|
||||
case EM_68K: ARCH_MISSING("EM_68K");
|
||||
case EM_88K: ARCH_MISSING("EM_88K");
|
||||
case EM_IAMCU: ARCH_MISSING("EM_IAMCU");
|
||||
case EM_860: ARCH_MISSING("EM_860");
|
||||
case EM_S370: ARCH_MISSING("EM_S370");
|
||||
case EM_PARISC: ARCH_MISSING("EM_PARISC");
|
||||
case EM_VPP500: ARCH_MISSING("EM_VPP500");
|
||||
case EM_960: ARCH_MISSING("EM_960");
|
||||
case EM_PPC: ARCH_MISSING("EM_PPC");
|
||||
|
|
|
|||
158
test/db/analysis/hppa
Normal file
158
test/db/analysis/hppa
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
NAME=hppa analysis graph
|
||||
FILE=bins/hppa/elf-Linux-hppa-bash
|
||||
CMDS=<<EOF
|
||||
aaa
|
||||
s sym.array_keys_to_word_list
|
||||
pdf
|
||||
agf
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
/ sym.array_keys_to_word_list();
|
||||
| 0x000607ec stw rp, -0x14(sp)
|
||||
| 0x000607f0 stw,ma r5, 0x80(sp)
|
||||
| 0x000607f4 ldo -0x70(sp), r1
|
||||
| 0x000607f8 stw r4, -0x7c(sp)
|
||||
| 0x000607fc stw r3, -0x78(sp)
|
||||
| ,=< 0x00060800 movb,<> r26, r5, 0x6082c
|
||||
| | 0x00060804 fstd,ma fr12, 8(r1)
|
||||
| | 0x00060808 ldo 0(flags), r4
|
||||
| | 0x0006080c or r4, flags, ret0
|
||||
| | 0x00060810 ldo -0x70(sp), r1
|
||||
| | 0x00060814 ldw -0x94(sp), rp
|
||||
| | 0x00060818 ldw -0x7c(sp), r4
|
||||
| | 0x0006081c ldw -0x78(sp), r3
|
||||
| | 0x00060820 fldd,ma 8(r1), fr12
|
||||
| | 0x00060824 bve (rp)
|
||||
| | 0x00060828 ldw,mb -0x80(sp), r5
|
||||
| `-> 0x0006082c ldw 0x10(r5), ret0
|
||||
| 0x00060830 ldw 0x14(r5), r19
|
||||
| 0x00060834 or,* ret0, r19, ret0
|
||||
| 0x00060838 cmpib,= 0, ret0, 0x6080c
|
||||
| 0x0006083c ldo 0(flags), r4
|
||||
| 0x00060840 ldw 0x18(r5), ret0
|
||||
| 0x00060844 ldw 0xc(ret0), r3
|
||||
| 0x00060848 cmpb,= r3, ret0, 0x60810
|
||||
| 0x0006084c or r4, flags, ret0
|
||||
| 0x00060850 ldw 0(r3), r25
|
||||
| 0x00060854 ldw 4(r3), r26
|
||||
| 0x00060858 b,l sym.itos, flags
|
||||
| 0x0006085c or flags, flags, flags
|
||||
| 0x00060860 stw ret0, -0x10(sp)
|
||||
| 0x00060864 fldw -0x10(sp), fr12
|
||||
| 0x00060868 b,l sym.make_bare_word, r31
|
||||
| 0x0006086c or ret0, flags, r26
|
||||
| 0x00060870 or r4, flags, r25
|
||||
| 0x00060874 b,l sym.make_word_list, r31
|
||||
| 0x00060878 or ret0, flags, r26
|
||||
| 0x0006087c fstw fr12, -0x10(sp)
|
||||
| 0x00060880 ldw -0x10(sp), r26
|
||||
| 0x00060884 b,l 0x76aec, flags
|
||||
| 0x00060888 or ret0, flags, r4
|
||||
| 0x0006088c ldw 0xc(r3), r3
|
||||
| 0x00060890 ldw 0x18(r5), ret0
|
||||
| 0x00060894 cmpb,<> r3, ret0, 0x60850
|
||||
| 0x00060898 or flags, flags, flags
|
||||
| 0x0006089c cmpib,= 0, r4, 0x60810
|
||||
| 0x000608a0 or r4, flags, ret0
|
||||
| 0x000608a4 ldw 0(r4), ret0
|
||||
| 0x000608a8 cmpib,= 0, ret0, 0x6080c
|
||||
| 0x000608ac or r4, flags, r26
|
||||
| 0x000608b0 ldo -0x70(sp), r1
|
||||
| 0x000608b4 ldw -0x94(sp), rp
|
||||
| 0x000608b8 ldw -0x7c(sp), r4
|
||||
| 0x000608bc ldw -0x78(sp), r3
|
||||
| 0x000608c0 fldd,ma 8(r1), fr12
|
||||
| 0x000608c4 b,l sym.list_reverse, flags
|
||||
| 0x000608c8 ldw,mb -0x80(sp), r5
|
||||
\ 0x000608cc or flags, flags, flags
|
||||
.--------------------------------.
|
||||
| 0x607ec |
|
||||
| sym.array_keys_to_word_list(); |
|
||||
| stw rp, -0x14(sp) |
|
||||
| stw,ma r5, 0x80(sp) |
|
||||
| ldo -0x70(sp), r1 |
|
||||
| stw r4, -0x7c(sp) |
|
||||
| stw r3, -0x78(sp) |
|
||||
| movb,<> r26, r5, 0x6082c |
|
||||
`--------------------------------'
|
||||
f t
|
||||
| |
|
||||
| '--------------.
|
||||
.------' |
|
||||
| |
|
||||
.----------------------. |
|
||||
| 0x60804 | |
|
||||
| fstd,ma fr12, 8(r1) | |
|
||||
| ldo 0(flags), r4 | |
|
||||
| or r4, flags, ret0 | |
|
||||
| ldo -0x70(sp), r1 | |
|
||||
| ldw -0x94(sp), rp | |
|
||||
| ldw -0x7c(sp), r4 | |
|
||||
| ldw -0x78(sp), r3 | |
|
||||
| fldd,ma 8(r1), fr12 | |
|
||||
| bve (rp) | |
|
||||
| ldw,mb -0x80(sp), r5 | |
|
||||
`----------------------' |
|
||||
v |
|
||||
| |
|
||||
'------. |
|
||||
| .--------------'
|
||||
| |
|
||||
.-----------------------------.
|
||||
| 0x6082c |
|
||||
| ldw 0x10(r5), ret0 |
|
||||
| ldw 0x14(r5), r19 |
|
||||
| or,* ret0, r19, ret0 |
|
||||
| cmpib,= 0, ret0, 0x6080c |
|
||||
| ldo 0(flags), r4 |
|
||||
| ldw 0x18(r5), ret0 |
|
||||
| ldw 0xc(ret0), r3 |
|
||||
| cmpb,= r3, ret0, 0x60810 |
|
||||
| or r4, flags, ret0 |
|
||||
| ldw 0(r3), r25 |
|
||||
| ldw 4(r3), r26 |
|
||||
| b,l sym.itos, flags |
|
||||
| or flags, flags, flags |
|
||||
| stw ret0, -0x10(sp) |
|
||||
| fldw -0x10(sp), fr12 |
|
||||
| b,l sym.make_bare_word, r31 |
|
||||
| or ret0, flags, r26 |
|
||||
| or r4, flags, r25 |
|
||||
| b,l sym.make_word_list, r31 |
|
||||
| or ret0, flags, r26 |
|
||||
| fstw fr12, -0x10(sp) |
|
||||
| ldw -0x10(sp), r26 |
|
||||
| b,l 0x76aec, flags |
|
||||
| or ret0, flags, r4 |
|
||||
| ldw 0xc(r3), r3 |
|
||||
| ldw 0x18(r5), ret0 |
|
||||
| cmpb,<> r3, ret0, 0x60850 |
|
||||
| or flags, flags, flags |
|
||||
| cmpib,= 0, r4, 0x60810 |
|
||||
| or r4, flags, ret0 |
|
||||
| ldw 0(r4), ret0 |
|
||||
| cmpib,= 0, ret0, 0x6080c |
|
||||
| or r4, flags, r26 |
|
||||
| ldo -0x70(sp), r1 |
|
||||
| ldw -0x94(sp), rp |
|
||||
| ldw -0x7c(sp), r4 |
|
||||
| ldw -0x78(sp), r3 |
|
||||
| fldd,ma 8(r1), fr12 |
|
||||
| b,l sym.list_reverse, flags |
|
||||
| ldw,mb -0x80(sp), r5 |
|
||||
| or flags, flags, flags |
|
||||
`-----------------------------'
|
||||
v
|
||||
|
|
||||
'.
|
||||
|
|
||||
.---------------------------.
|
||||
| 0x608d0 |
|
||||
| sym.array_to_word_list(); |
|
||||
| stw rp, -0x14(sp) |
|
||||
| stw,ma r5, 0x40(sp) |
|
||||
| stw r4, -0x3c(sp) |
|
||||
| movb,<> r26, r5, 0x60900 |
|
||||
`---------------------------'
|
||||
EOF
|
||||
RUN
|
||||
|
|
@ -22,7 +22,7 @@ adAeI 16 gb LGPL3 GameBoy(TM) (z80-like) (by condret)
|
|||
_dAeI 16 h8300 LGPL3 Hitachi/Renesas H8/300 disassembly plugin
|
||||
_dA__ 16 h8500 LGPL3 Hitachi/Renesas H8/500 disassembler (by billow)
|
||||
_dA_I 32 hexagon LGPL3 Qualcomm Hexagon (QDSP6) V6 (by Rot127)
|
||||
_d___ 32 hppa GPL3 HP PA-RISC
|
||||
_dA__ 32 64 hppa LGPL3 HP PA-RISC Capstone-based disassembler (by xvilka)
|
||||
_dA__ 4 i4004 LGPL3 Intel 4004 disassembler
|
||||
_dA__ 8 i8080 BSD Intel 8080 disassembler
|
||||
adA__ 32 java LGPL-3 Java bytecode disassembler (by deroad)
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -790,16 +790,16 @@ hppa7100
|
|||
32
|
||||
true
|
||||
;-- section.0.__TEXT.__text:
|
||||
0x000039e8 ldw 0(sp),r26 ; [00] -r-x section size 10588 named 0.__TEXT.__text
|
||||
0x000039ec ldo 7f(sp),sp
|
||||
0x000039f0 ldil L%3800,r1
|
||||
0x000039f4 be 1fc(sr4,r1)
|
||||
0x000039f8 depwi 0,31,6,sp
|
||||
0x000039fc stw rp,-14(sp)
|
||||
0x00003a00 stw,ma r5,80(sp)
|
||||
0x00003a04 stw r4,-7c(sp)
|
||||
0x00003a08 stw r3,-78(sp)
|
||||
0x00003a0c copy r26,r4
|
||||
0x000039e8 ldw 0(sp), r26 ; [00] -r-x section size 10588 named 0.__TEXT.__text
|
||||
0x000039ec ldo 0x7f(sp), sp
|
||||
0x000039f0 ldil 0x3800, r1
|
||||
0x000039f4 be 0x1fc(sr4,r1)
|
||||
0x000039f8 depi 0, 0x1f, 6, sp
|
||||
0x000039fc stw rp, -0x14(sp)
|
||||
0x00003a00 stwm r5, 0x80(sp)
|
||||
0x00003a04 stw r4, -0x7c(sp)
|
||||
0x00003a08 stw r3, -0x78(sp)
|
||||
0x00003a0c or r26, flags, r4
|
||||
Backed up flag space into 'flags.sparc_32_all.sdb'. You can restore the flags with the 'ko' command.
|
||||
sparc
|
||||
all
|
||||
|
|
|
|||
Loading…
Reference in a new issue