From 6cacb99e985ce43266d8bc4e2aa1caf5c2234a65 Mon Sep 17 00:00:00 2001 From: Anton Kochkov Date: Sat, 4 May 2024 18:48:21 +0800 Subject: [PATCH] hppa: use capstone disassembler --- librz/arch/isa/hppa/hppa.h | 19 + librz/arch/isa/hppa/hppa.inc | 117 +++++ librz/arch/meson.build | 2 + librz/arch/p/analysis/analysis_hppa_cs.c | 504 +++++++++++++++++++ librz/arch/p/arch_hppa_cs.c | 9 + librz/arch/p/asm/asm_hppa_cs.c | 123 +++++ librz/bin/format/elf/elf_imports.c | 32 ++ librz/bin/format/elf/elf_info.c | 33 +- librz/bin/format/elf/elf_relocs_conversion.c | 19 +- librz/bin/format/elf/elf_relocs_patching.c | 45 +- test/db/analysis/hppa | 158 ++++++ test/db/cmd/cmd_aL | 2 +- test/db/cmd/cmd_list | 8 +- test/db/cmd/cmd_open | 20 +- 14 files changed, 1070 insertions(+), 21 deletions(-) create mode 100644 librz/arch/isa/hppa/hppa.h create mode 100644 librz/arch/isa/hppa/hppa.inc create mode 100644 librz/arch/p/analysis/analysis_hppa_cs.c create mode 100644 librz/arch/p/arch_hppa_cs.c create mode 100644 librz/arch/p/asm/asm_hppa_cs.c create mode 100644 test/db/analysis/hppa diff --git a/librz/arch/isa/hppa/hppa.h b/librz/arch/isa/hppa/hppa.h new file mode 100644 index 0000000000..463ce45d4e --- /dev/null +++ b/librz/arch/isa/hppa/hppa.h @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: 2024-2025 Anton Kochkov +// SPDX-License-Identifier: LGPL-3.0-only + +#include +#include + +#ifndef RZ_HPPA_H +#define RZ_HPPA_H + +typedef struct { + csh h; + cs_mode mode; + cs_insn *insn; + ut32 count; + ut32 word; + RzPVector /**/ *token_patterns; +} RzAsmHPPAContext; + +#endif // RZ_HPPA_H diff --git a/librz/arch/isa/hppa/hppa.inc b/librz/arch/isa/hppa/hppa.inc new file mode 100644 index 0000000000..95ecb173bd --- /dev/null +++ b/librz/arch/isa/hppa/hppa.inc @@ -0,0 +1,117 @@ +// SPDX-FileCopyrightText: 2023 billow +// SPDX-FileCopyrightText: 2024-2025 Anton Kochkov +// SPDX-License-Identifier: LGPL-3.0-only + +#include +#include +#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; +} diff --git a/librz/arch/meson.build b/librz/arch/meson.build index b6e4f346a6..f378b70b55 100644 --- a/librz/arch/meson.build +++ b/librz/arch/meson.build @@ -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', ] diff --git a/librz/arch/p/analysis/analysis_hppa_cs.c b/librz/arch/p/analysis/analysis_hppa_cs.c new file mode 100644 index 0000000000..a621bf90dc --- /dev/null +++ b/librz/arch/p/analysis/analysis_hppa_cs.c @@ -0,0 +1,504 @@ +// SPDX-FileCopyrightText: 2024 Anton Kochkov +// SPDX-License-Identifier: LGPL-3.0-only + +#include +#include +#include +#include + +#include + +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 diff --git a/librz/arch/p/arch_hppa_cs.c b/librz/arch/p/arch_hppa_cs.c new file mode 100644 index 0000000000..58ec66cbc8 --- /dev/null +++ b/librz/arch/p/arch_hppa_cs.c @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2024 RizinOrg +// SPDX-License-Identifier: LGPL-3.0-only + +#include + +#include "analysis/analysis_hppa_cs.c" +#include "asm/asm_hppa_cs.c" + +RZ_ARCH_PLUGIN_DEFINE_DEPRECATED(hppa_cs); diff --git a/librz/arch/p/asm/asm_hppa_cs.c b/librz/arch/p/asm/asm_hppa_cs.c new file mode 100644 index 0000000000..c86bf41d81 --- /dev/null +++ b/librz/arch/p/asm/asm_hppa_cs.c @@ -0,0 +1,123 @@ +// SPDX-FileCopyrightText: 2024 Anton Kochkov +// SPDX-License-Identifier: LGPL-3.0-only + +#include +#include +#include + +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 /**/ *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 diff --git a/librz/bin/format/elf/elf_imports.c b/librz/bin/format/elf/elf_imports.c index 596f2db4ae..8e2ad89821 100644 --- a/librz/bin/format/elf/elf_imports.c +++ b/librz/bin/format/elf/elf_imports.c @@ -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: diff --git a/librz/bin/format/elf/elf_info.c b/librz/bin/format/elf/elf_info.c index 98b13eeec2..ba528ccb55 100644 --- a/librz/bin/format/elf/elf_info.c +++ b/librz/bin/format/elf/elf_info.c @@ -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; diff --git a/librz/bin/format/elf/elf_relocs_conversion.c b/librz/bin/format/elf/elf_relocs_conversion.c index 4bdfb775e8..ca243753d2 100644 --- a/librz/bin/format/elf/elf_relocs_conversion.c +++ b/librz/bin/format/elf/elf_relocs_conversion.c @@ -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"); diff --git a/librz/bin/format/elf/elf_relocs_patching.c b/librz/bin/format/elf/elf_relocs_patching.c index 3e3b57fb37..8fbc5f9b69 100644 --- a/librz/bin/format/elf/elf_relocs_patching.c +++ b/librz/bin/format/elf/elf_relocs_patching.c @@ -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"); diff --git a/test/db/analysis/hppa b/test/db/analysis/hppa new file mode 100644 index 0000000000..17feef41dc --- /dev/null +++ b/test/db/analysis/hppa @@ -0,0 +1,158 @@ +NAME=hppa analysis graph +FILE=bins/hppa/elf-Linux-hppa-bash +CMDS=< 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 diff --git a/test/db/cmd/cmd_aL b/test/db/cmd/cmd_aL index 17457a96e7..f40faeb0fd 100644 --- a/test/db/cmd/cmd_aL +++ b/test/db/cmd/cmd_aL @@ -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) diff --git a/test/db/cmd/cmd_list b/test/db/cmd/cmd_list index faa4251770..7cf6bf8539 100644 --- a/test/db/cmd/cmd_list +++ b/test/db/cmd/cmd_list @@ -662,7 +662,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) @@ -709,7 +709,7 @@ _dA__ 16 xap PD Cambridge Consultants XAP4 RISC (CSR) disas _dA__ 32 xcore BSD XCore Capstone-based disassembler (by pancake) _dAeI 32 xtensa LGPL3 Tensilica Xtensa Capstone-based disassembler (by billow) adA__ 8 z80 GPL3 Zilog Z80 disassembler (by condret) -["6502":{"bits":"8 16 ","license":"LGPL3","description":"6502/NES/C64/Tamagotchi/T-1000 CPU","features":"_dAeI"},"8051":{"bits":"8 ","license":"PD","description":"Intel 8051 disassembler","features":"adAeI"},"alpha":{"bits":"64","license":"LGPL3","description":"DEC Alpha Capstone-based disassembler","features":"_dA__"},"amd29k":{"bits":"32 ","license":"LGPL3","description":"AMD 29k RISC disassembler","features":"_dA__","author":"deroad"},"arc":{"bits":"16 32 ","license":"GPL3","description":"Argonaut RISC Core","features":"_dA__"},"arm":{"bits":"16 32 64","license":"BSD","description":"ARM Capstone-based disassembler","features":"adAeI"},"arm.as":{"bits":"16 32 64","license":"LGPL3","description":"as ARM Assembler (use RZ_ARM32_AS and RZ_ARM64_AS environment)","features":"a____","author":"pancake"},"avr":{"bits":"8 16 ","license":"LGPL3","description":"Atmel AVR disassembler","features":"adAeI"},"bf":{"bits":"16 32 64","license":"LGPL3","description":"Brainfuck","features":"adA_I","author":"pancake, nibble","version":"4.0.0"},"chip8":{"bits":"32 ","license":"LGPL3","description":"Chip8 disassembler","features":"_dA__"},"cil":{"bits":"16 32 64","license":"LGPL3","description":".NET CIL/MSIL (Common Intermediate Language) bytecode disassembler","features":"_dA__"},"cr16":{"bits":"16 ","license":"LGPL3","description":"CompactRISC CR16 disassembler","features":"_dA__"},"cris":{"bits":"32 ","license":"GPL3","description":"Axis Communications 32-bit embedded processor disassembler","features":"_dA__","author":"pancake"},"dalvik":{"bits":"32 64","license":"LGPL3","description":"Dalvik (Android VM) bytecode disassembler","features":"adA__"},"dcpu16":{"bits":"16 ","license":"PD","description":"Mojang's DCPU-16 disassembler","features":"ad___"},"ebc":{"bits":"32 64","license":"LGPL3","description":"EFI bytecode disassembler","features":"_dA__","author":"Fedor Sakharov"},"gb":{"bits":"16 ","license":"LGPL3","description":"GameBoy(TM) (z80-like)","features":"adAeI","author":"condret"},"h8300":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/300 disassembly plugin","features":"_dAeI"},"h8500":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/500 disassembler","features":"_dA__","author":"billow"},"hexagon":{"bits":"32 ","license":"LGPL3","description":"Qualcomm Hexagon (QDSP6) V6","features":"_dA_I","author":"Rot127"},"hppa":{"bits":"32 ","license":"GPL3","description":"HP PA-RISC","features":"_d___"},"i4004":{"bits":"4 ","license":"LGPL3","description":"Intel 4004 disassembler","features":"_dA__"},"i8080":{"bits":"8 ","license":"BSD","description":"Intel 8080 disassembler","features":"_dA__"},"java":{"bits":"32 ","license":"LGPL-3","description":"Java bytecode disassembler","features":"adA__","author":"deroad"},"lanai":{"bits":"32 ","license":"GPL3","description":"Google LANAI disassembler","features":"_d___"},"lh5801":{"bits":"8 ","license":"LGPL3","description":"SHARP LH5801 disassembler","features":"_d___"},"lm32":{"bits":"32 ","license":"BSD","description":"Lattice Micro 32 ISA disassembler","features":"_d___","author":"Felix Held"},"loongarch":{"bits":"32 64","license":"LGPL3","description":"Loongson LoongArch disassembler","features":"_dA__"},"luac":{"bits":"8 ","license":"LGPL3","description":"Lua bytecode (LUAC) disassembler","features":"adA__"},"m680x":{"bits":"8 32 ","license":"BSD","description":"Motorola 680X Capstone-based disassembler","features":"_dA__"},"m68k":{"bits":"32 ","license":"BSD","description":"Motorola 68K Capstone-based disassembler","features":"_dA__"},"malbolge":{"bits":"32 ","license":"LGPL3","description":"Malbolge Ternary VM bytecode disassembler","features":"_dA__","author":"condret"},"mcore":{"bits":"32 ","license":"LGPL3","description":"Motorola MCORE disassembler","features":"_dA__"},"mcs96":{"bits":"16 ","license":"LGPL3","description":"Intel MCS-96 disassembler","features":"_dA__","author":"condret"},"mips":{"bits":"16 32 64","license":"BSD","description":"MIPS Capstone-based disassembler","features":"adAeI"},"msp430":{"bits":"16 ","license":"LGPL3","description":"Texas Instruments MSP430 disassembler","features":"_dA_I"},"null":{"bits":"16 32 64","license":"MIT","description":"NULL (empty) disassembler","features":"adA__","author":"pancake","version":"1.0.0"},"or1k":{"bits":"32 ","license":"LGPL3","description":"OpenRISC 1000 disassembler","features":"_dA__"},"pic":{"bits":"16 32 ","license":"LGPL3","description":"Microchip PIC disassembler","features":"_dAeI"},"ppc":{"bits":"32 64","license":"BSD","description":"PowerPC Capstone-based disassembler","features":"_dAeI","author":"pancake"},"ppc.as":{"bits":"32 64","license":"LGPL3","description":"as PPC Assembler (use RZ_PPC_AS environment)","features":"a____","author":"eagleoflqj"},"propeller":{"bits":"32 ","license":"LGPL3","description":"Parallax Propeller disassembler","features":"_dA__"},"pyc":{"bits":"8 16 ","license":"LGPL3","description":"Python bytecode (PYC) disassembler","features":"_dA__"},"riscv":{"bits":"32 64","license":"GPL3","description":"RISC-V disassembler","features":"_dAe_"},"riscv.cs":{"bits":"32 64","license":"BSD","description":"RISC-V Capstone-based disassembler","features":"_dA__"},"rl78":{"bits":"32 ","license":"LGPL3","description":"Renesas RL78 disassembler","features":"adA__","author":"Bastian Engel"},"rsp":{"bits":"32 ","license":"LGPL3","description":"Nintendo N64 Reality Signal Processor disassembler","features":"_dA__"},"rx":{"bits":"32 ","license":"LGPL3","description":"Renesas RX Family disassembler","features":"_dA__","author":"Heersin"},"sh":{"bits":"32 ","license":"LGPL3","description":"Hitachi/Renesas SuperH-4 disassembler","features":"adAeI","author":"DMaroo"},"snes":{"bits":"8 16 ","license":"LGPL3","description":"SuperNES CPU disassembler","features":"_dA__"},"sparc":{"bits":"32 64","license":"BSD","description":"Sun SPARC Capstone-based disassembler","features":"_dA_I"},"spc700":{"bits":"16 ","license":"LGPL3","description":"Sony SPC700 (Nintendo SuperNES sound-chip) disassembler","features":"_dA__"},"sysz":{"bits":"32 64","license":"BSD","description":"IBM SystemZ (S/390) Capstone-based disassembler","features":"_dA__"},"tms320":{"bits":"32 ","license":"LGPL3","description":"Texas Instruments TMS320 DSP family (c54x,c55x,c55x+,c64x) disassembler","features":"_dA__"},"tricore":{"bits":"32 ","license":"BSD","description":"Siemens TriCore Capstone-based disassembler","features":"_dA_I","author":"billow"},"v810":{"bits":"32 ","license":"LGPL3","description":"NEC V810 disassembler","features":"_dAeI","author":"pancake"},"v850":{"bits":"32 ","license":"LGPL3","description":"NEC/Renesas V850 disassembler","features":"_dAeI"},"vax":{"bits":"8 32 ","license":"GPL3","description":"DEC VAX disassembler","features":"_dA__"},"wasm":{"bits":"32 ","license":"MIT","description":"WebAssembly disassembler","features":"adA__","author":"cgvwzq","version":"0.1.0"},"x86":{"bits":"16 32 64","license":"MIT","description":"X86/X86_64 Zydis-based disassembler","features":"_dAeI"},"x86.as":{"bits":"16 32 64","license":"LGPL3","description":"Intel X86 GNU Assembler (Use RZ_X86_AS env)","features":"a____"},"x86.nasm":{"bits":"16 32 64","license":"LGPL3","description":"X86 nasm assembler","features":"a____"},"x86.nz":{"bits":"16 32 64","license":"LGPL3","description":"x86 handmade assembler","features":"a____"},"xap":{"bits":"16 ","license":"PD","description":"Cambridge Consultants XAP4 RISC (CSR) disassembler","features":"_dA__"},"xcore":{"bits":"32 ","license":"BSD","description":"XCore Capstone-based disassembler","features":"_dA__","author":"pancake"},"xtensa":{"bits":"32 ","license":"LGPL3","description":"Tensilica Xtensa Capstone-based disassembler","features":"_dAeI","author":"billow"},"z80":{"bits":"8 ","license":"GPL3","description":"Zilog Z80 disassembler","features":"adA__","author":"condret"}] +["6502":{"bits":"8 16 ","license":"LGPL3","description":"6502/NES/C64/Tamagotchi/T-1000 CPU","features":"_dAeI"},"8051":{"bits":"8 ","license":"PD","description":"Intel 8051 disassembler","features":"adAeI"},"alpha":{"bits":"64","license":"LGPL3","description":"DEC Alpha Capstone-based disassembler","features":"_dA__"},"amd29k":{"bits":"32 ","license":"LGPL3","description":"AMD 29k RISC disassembler","features":"_dA__","author":"deroad"},"arc":{"bits":"16 32 ","license":"GPL3","description":"Argonaut RISC Core","features":"_dA__"},"arm":{"bits":"16 32 64","license":"BSD","description":"ARM Capstone-based disassembler","features":"adAeI"},"arm.as":{"bits":"16 32 64","license":"LGPL3","description":"as ARM Assembler (use RZ_ARM32_AS and RZ_ARM64_AS environment)","features":"a____","author":"pancake"},"avr":{"bits":"8 16 ","license":"LGPL3","description":"Atmel AVR disassembler","features":"adAeI"},"bf":{"bits":"16 32 64","license":"LGPL3","description":"Brainfuck","features":"adA_I","author":"pancake, nibble","version":"4.0.0"},"chip8":{"bits":"32 ","license":"LGPL3","description":"Chip8 disassembler","features":"_dA__"},"cil":{"bits":"16 32 64","license":"LGPL3","description":".NET CIL/MSIL (Common Intermediate Language) bytecode disassembler","features":"_dA__"},"cr16":{"bits":"16 ","license":"LGPL3","description":"CompactRISC CR16 disassembler","features":"_dA__"},"cris":{"bits":"32 ","license":"GPL3","description":"Axis Communications 32-bit embedded processor disassembler","features":"_dA__","author":"pancake"},"dalvik":{"bits":"32 64","license":"LGPL3","description":"Dalvik (Android VM) bytecode disassembler","features":"adA__"},"dcpu16":{"bits":"16 ","license":"PD","description":"Mojang's DCPU-16 disassembler","features":"ad___"},"ebc":{"bits":"32 64","license":"LGPL3","description":"EFI bytecode disassembler","features":"_dA__","author":"Fedor Sakharov"},"gb":{"bits":"16 ","license":"LGPL3","description":"GameBoy(TM) (z80-like)","features":"adAeI","author":"condret"},"h8300":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/300 disassembly plugin","features":"_dAeI"},"h8500":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/500 disassembler","features":"_dA__","author":"billow"},"hexagon":{"bits":"32 ","license":"LGPL3","description":"Qualcomm Hexagon (QDSP6) V6","features":"_dA_I","author":"Rot127"},"hppa":{"bits":"32 64","license":"LGPL3","description":"HP PA-RISC Capstone-based disassembler","features":"_dA__","author":"xvilka"},"i4004":{"bits":"4 ","license":"LGPL3","description":"Intel 4004 disassembler","features":"_dA__"},"i8080":{"bits":"8 ","license":"BSD","description":"Intel 8080 disassembler","features":"_dA__"},"java":{"bits":"32 ","license":"LGPL-3","description":"Java bytecode disassembler","features":"adA__","author":"deroad"},"lanai":{"bits":"32 ","license":"GPL3","description":"Google LANAI disassembler","features":"_d___"},"lh5801":{"bits":"8 ","license":"LGPL3","description":"SHARP LH5801 disassembler","features":"_d___"},"lm32":{"bits":"32 ","license":"BSD","description":"Lattice Micro 32 ISA disassembler","features":"_d___","author":"Felix Held"},"loongarch":{"bits":"32 64","license":"LGPL3","description":"Loongson LoongArch disassembler","features":"_dA__"},"luac":{"bits":"8 ","license":"LGPL3","description":"Lua bytecode (LUAC) disassembler","features":"adA__"},"m680x":{"bits":"8 32 ","license":"BSD","description":"Motorola 680X Capstone-based disassembler","features":"_dA__"},"m68k":{"bits":"32 ","license":"BSD","description":"Motorola 68K Capstone-based disassembler","features":"_dA__"},"malbolge":{"bits":"32 ","license":"LGPL3","description":"Malbolge Ternary VM bytecode disassembler","features":"_dA__","author":"condret"},"mcore":{"bits":"32 ","license":"LGPL3","description":"Motorola MCORE disassembler","features":"_dA__"},"mcs96":{"bits":"16 ","license":"LGPL3","description":"Intel MCS-96 disassembler","features":"_dA__","author":"condret"},"mips":{"bits":"16 32 64","license":"BSD","description":"MIPS Capstone-based disassembler","features":"adAeI"},"msp430":{"bits":"16 ","license":"LGPL3","description":"Texas Instruments MSP430 disassembler","features":"_dA_I"},"null":{"bits":"16 32 64","license":"MIT","description":"NULL (empty) disassembler","features":"adA__","author":"pancake","version":"1.0.0"},"or1k":{"bits":"32 ","license":"LGPL3","description":"OpenRISC 1000 disassembler","features":"_dA__"},"pic":{"bits":"16 32 ","license":"LGPL3","description":"Microchip PIC disassembler","features":"_dAeI"},"ppc":{"bits":"32 64","license":"BSD","description":"PowerPC Capstone-based disassembler","features":"_dAeI","author":"pancake"},"ppc.as":{"bits":"32 64","license":"LGPL3","description":"as PPC Assembler (use RZ_PPC_AS environment)","features":"a____","author":"eagleoflqj"},"propeller":{"bits":"32 ","license":"LGPL3","description":"Parallax Propeller disassembler","features":"_dA__"},"pyc":{"bits":"8 16 ","license":"LGPL3","description":"Python bytecode (PYC) disassembler","features":"_dA__"},"riscv":{"bits":"32 64","license":"GPL3","description":"RISC-V disassembler","features":"_dAe_"},"riscv.cs":{"bits":"32 64","license":"BSD","description":"RISC-V Capstone-based disassembler","features":"_dA__"},"rl78":{"bits":"32 ","license":"LGPL3","description":"Renesas RL78 disassembler","features":"adA__","author":"Bastian Engel"},"rsp":{"bits":"32 ","license":"LGPL3","description":"Nintendo N64 Reality Signal Processor disassembler","features":"_dA__"},"rx":{"bits":"32 ","license":"LGPL3","description":"Renesas RX Family disassembler","features":"_dA__","author":"Heersin"},"sh":{"bits":"32 ","license":"LGPL3","description":"Hitachi/Renesas SuperH-4 disassembler","features":"adAeI","author":"DMaroo"},"snes":{"bits":"8 16 ","license":"LGPL3","description":"SuperNES CPU disassembler","features":"_dA__"},"sparc":{"bits":"32 64","license":"BSD","description":"Sun SPARC Capstone-based disassembler","features":"_dA_I"},"spc700":{"bits":"16 ","license":"LGPL3","description":"Sony SPC700 (Nintendo SuperNES sound-chip) disassembler","features":"_dA__"},"sysz":{"bits":"32 64","license":"BSD","description":"IBM SystemZ (S/390) Capstone-based disassembler","features":"_dA__"},"tms320":{"bits":"32 ","license":"LGPL3","description":"Texas Instruments TMS320 DSP family (c54x,c55x,c55x+,c64x) disassembler","features":"_dA__"},"tricore":{"bits":"32 ","license":"BSD","description":"Siemens TriCore Capstone-based disassembler","features":"_dA_I","author":"billow"},"v810":{"bits":"32 ","license":"LGPL3","description":"NEC V810 disassembler","features":"_dAeI","author":"pancake"},"v850":{"bits":"32 ","license":"LGPL3","description":"NEC/Renesas V850 disassembler","features":"_dAeI"},"vax":{"bits":"8 32 ","license":"GPL3","description":"DEC VAX disassembler","features":"_dA__"},"wasm":{"bits":"32 ","license":"MIT","description":"WebAssembly disassembler","features":"adA__","author":"cgvwzq","version":"0.1.0"},"x86":{"bits":"16 32 64","license":"MIT","description":"X86/X86_64 Zydis-based disassembler","features":"_dAeI"},"x86.as":{"bits":"16 32 64","license":"LGPL3","description":"Intel X86 GNU Assembler (Use RZ_X86_AS env)","features":"a____"},"x86.nasm":{"bits":"16 32 64","license":"LGPL3","description":"X86 nasm assembler","features":"a____"},"x86.nz":{"bits":"16 32 64","license":"LGPL3","description":"x86 handmade assembler","features":"a____"},"xap":{"bits":"16 ","license":"PD","description":"Cambridge Consultants XAP4 RISC (CSR) disassembler","features":"_dA__"},"xcore":{"bits":"32 ","license":"BSD","description":"XCore Capstone-based disassembler","features":"_dA__","author":"pancake"},"xtensa":{"bits":"32 ","license":"LGPL3","description":"Tensilica Xtensa Capstone-based disassembler","features":"_dAeI","author":"billow"},"z80":{"bits":"8 ","license":"GPL3","description":"Zilog Z80 disassembler","features":"adA__","author":"condret"}] name bits features license version author description --------------------------------------------------------------------------------------------------------------------------------- _dAeI 8 16 6502 LGPL3 6502/NES/C64/Tamagotchi/T-1000 CPU @@ -732,7 +732,7 @@ adAeI 16 gb LGPL3 condret GameBoy(TM) (z80-like) _dAeI 16 h8300 LGPL3 Hitachi/Renesas H8/300 disassembly plugin _dA__ 16 h8500 LGPL3 billow Hitachi/Renesas H8/500 disassembler _dA_I 32 hexagon LGPL3 Rot127 Qualcomm Hexagon (QDSP6) V6 -_d___ 32 hppa GPL3 HP PA-RISC +_dA__ 32 64 hppa LGPL3 xvilka HP PA-RISC Capstone-based disassembler _dA__ 4 i4004 LGPL3 Intel 4004 disassembler _dA__ 8 i8080 BSD Intel 8080 disassembler adA__ 32 java LGPL-3 deroad Java bytecode disassembler @@ -1055,7 +1055,7 @@ NAME=Print the asm/analysis plugins in JSON FILE== CMDS=Laj EXPECT=<