aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--disas/capstone.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/disas/capstone.c b/disas/capstone.c
index b48f83958d..0a9ef9c892 100644
--- a/disas/capstone.c
+++ b/disas/capstone.c
@@ -17,6 +17,39 @@
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
@@ -42,13 +75,20 @@ 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_X86) {
+ switch (info->cap_arch) {
+ case CS_ARCH_SYSZ:
+ cs_option(*handle, CS_OPT_SKIPDATA_SETUP,
+ (uintptr_t)&cap_skipdata_s390x);
+ break;
+
+ case CS_ARCH_X86:
/*
* We don't care about errors (if for some reason the library
* is compiled without AT&T syntax); the user will just have
* to deal with the Intel syntax.
*/
cs_option(*handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
+ break;
}
/* Allocate temp space for cs_disasm_iter. */