Capstone assumes any s390x unknown instruction is 2 bytes.
Instead, use the ilen field in the first two bits of
the instruction to stay in sync with the insn stream.
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
disas.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/disas.c b/disas.c
index 845c40fca8..1095bad049 100644
--- a/disas.c
+++ b/disas.c
@@ -178,6 +178,39 @@ static int print_insn_od_target(bfd_vma pc, disassemble_info *info)
to share this across calls and across host vs target disassembly. */
static __thread cs_insn *cap_insn;
+/*
+ * The capstone library always skips 2 bytes for S390X.
+ * This is less than ideal, since we can tell from the first two bits
+ * the size of the insn and thus stay in sync with the insn stream.
+ */
+static size_t CAPSTONE_API
+cap_skipdata_s390x_cb(const uint8_t *code, size_t code_size,
+ size_t offset, void *user_data)
+{
+ size_t ilen;
+
+ /* See get_ilen() in target/s390x/internal.h. */
+ switch (code[offset] >> 6) {
+ case 0:
+ ilen = 2;
+ break;
+ case 1:
+ case 2:
+ ilen = 4;
+ break;
+ default:
+ ilen = 6;
+ break;
+ }
+
+ return ilen;
+}
+
+static const cs_opt_skipdata cap_skipdata_s390x = {
+ .mnemonic = ".byte",
+ .callback = cap_skipdata_s390x_cb
+};
+
/* Initialize the Capstone library. */
/* ??? It would be nice to cache this. We would need one handle for the
host and one for the target. For most targets we can reset specific
@@ -208,6 +241,10 @@ static cs_err cap_disas_start(disassemble_info *info, csh *handle)
/* "Disassemble" unknown insns as ".byte W,X,Y,Z". */
cs_option(*handle, CS_OPT_SKIPDATA, CS_OPT_ON);
+ if (info->cap_arch == CS_ARCH_SYSZ) {
+ cs_option(*handle, CS_OPT_SKIPDATA_SETUP,
+ (uintptr_t)&cap_skipdata_s390x);
+ }
/* Allocate temp space for cs_disasm_iter. */
if (cap_insn == NULL) {
--
2.20.1
On 1/3/20 10:25 PM, Richard Henderson wrote:
> Capstone assumes any s390x unknown instruction is 2 bytes.
> Instead, use the ilen field in the first two bits of
> the instruction to stay in sync with the insn stream.
>
> Reviewed-by: Thomas Huth <thuth@redhat.com>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> ---
> disas.c | 37 +++++++++++++++++++++++++++++++++++++
> 1 file changed, 37 insertions(+)
>
> diff --git a/disas.c b/disas.c
> index 845c40fca8..1095bad049 100644
> --- a/disas.c
> +++ b/disas.c
> @@ -178,6 +178,39 @@ static int print_insn_od_target(bfd_vma pc, disassemble_info *info)
> to share this across calls and across host vs target disassembly. */
> static __thread cs_insn *cap_insn;
>
> +/*
> + * The capstone library always skips 2 bytes for S390X.
> + * This is less than ideal, since we can tell from the first two bits
> + * the size of the insn and thus stay in sync with the insn stream.
> + */
> +static size_t CAPSTONE_API
> +cap_skipdata_s390x_cb(const uint8_t *code, size_t code_size,
> + size_t offset, void *user_data)
> +{
> + size_t ilen;
> +
> + /* See get_ilen() in target/s390x/internal.h. */
> + switch (code[offset] >> 6) {
> + case 0:
> + ilen = 2;
> + break;
> + case 1:
> + case 2:
> + ilen = 4;
> + break;
> + default:
> + ilen = 6;
> + break;
> + }
> +
> + return ilen;
> +}
> +
> +static const cs_opt_skipdata cap_skipdata_s390x = {
> + .mnemonic = ".byte",
> + .callback = cap_skipdata_s390x_cb
> +};
> +
> /* Initialize the Capstone library. */
> /* ??? It would be nice to cache this. We would need one handle for the
> host and one for the target. For most targets we can reset specific
> @@ -208,6 +241,10 @@ static cs_err cap_disas_start(disassemble_info *info, csh *handle)
>
> /* "Disassemble" unknown insns as ".byte W,X,Y,Z". */
> cs_option(*handle, CS_OPT_SKIPDATA, CS_OPT_ON);
> + if (info->cap_arch == CS_ARCH_SYSZ) {
> + cs_option(*handle, CS_OPT_SKIPDATA_SETUP,
> + (uintptr_t)&cap_skipdata_s390x);
> + }
>
> /* Allocate temp space for cs_disasm_iter. */
> if (cap_insn == NULL) {
>
© 2016 - 2026 Red Hat, Inc.