From patchwork Thu Nov 9 07:52:42 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 118385 Delivered-To: patch@linaro.org Received: by 10.80.225.132 with SMTP id k4csp622494edl; Wed, 8 Nov 2017 23:55:06 -0800 (PST) X-Google-Smtp-Source: ABhQp+RY36lj4zvGWwCvBmDCMN1v3DMdDzvq1S8OQUkkvSfKug+RTAgmFU3W1qI8VJJePenwYSB6 X-Received: by 10.37.60.130 with SMTP id j124mr2034978yba.127.1510214105899; Wed, 08 Nov 2017 23:55:05 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1510214105; cv=none; d=google.com; s=arc-20160816; b=N/arbrUuUDGyM3tBsgYxluzRIYJ913fgNrcC0juNu8C05duInnb+x0jXVH3+u+hqpg yq1KotPnnzNbqGzabnvuIJCARsbSYlc6g8oZBtIsrfZFZTKuCfaIQd0uaIXUrPG5Q+4r SVZzhvNXGJaXxCrJcEJiU0cMo90IpP1pWxHE0twEpMWB7omTl2TnVtD2VyohiSkm7HRk MyinzEL4am8iTOpdBgLb8YZX61DeMOK8CB24hsk15iIAWU2uGAigjMccgySZ/JErw8B8 XE1MC/CppWS99e783DCsYceX/I5TwsB4MT9wjaPk2JVPpuI+FJEx2lDXTftWt0L5b0Gc uUQw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=bfAQ2yQr6PvXFnkTZcTggGt9Hq3L4y7mdonLePtVO7c=; b=SXWtRtw4Ue4Lr33UbDxdc6aTLIXBfrF8rw0ic9QrMZVU+cFvN7zKwCIt6OQq5kMcUc LOPdbXtUmSsLjIj/hQulFhBM79NdRGFTU7PJWSU5NN4FGKrNKfataql1p1A7c0nrK5Ms M/QUKdhIwANWWpTu/BYH9uUgDV9o/mmYAaCS/v9bhTdVWWTOcoOzsEoyldTy14OKn3BA xEfrREHBX8F33SYMOnaF+G072dEYzW4TDH0XQUPsozCkgIyauFwfGnropKLHOh7xGdKw 55x81MrCVz0W4IFEOn7ts3jvLkFLCZe5hVO8iM/QhQHPt3KITfkJ2D6LVnVhPoyzWvmP 7gTw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=EpZZtnrz; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id p65si1535293ywh.193.2017.11.08.23.55.05 for (version=TLS1 cipher=AES128-SHA bits=128/128); Wed, 08 Nov 2017 23:55:05 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=EpZZtnrz; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:35632 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eChg1-0003fQ-Ax for patch@linaro.org; Thu, 09 Nov 2017 02:55:05 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57036) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eChdr-0002W5-14 for qemu-devel@nongnu.org; Thu, 09 Nov 2017 02:52:52 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eChdp-0000W9-Ca for qemu-devel@nongnu.org; Thu, 09 Nov 2017 02:52:51 -0500 Received: from mail-wm0-x242.google.com ([2a00:1450:400c:c09::242]:55979) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eChdp-0000Vi-2w for qemu-devel@nongnu.org; Thu, 09 Nov 2017 02:52:49 -0500 Received: by mail-wm0-x242.google.com with SMTP id b189so757844wmd.4 for ; Wed, 08 Nov 2017 23:52:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=bfAQ2yQr6PvXFnkTZcTggGt9Hq3L4y7mdonLePtVO7c=; b=EpZZtnrzlTEXPU1lav+IFBZNwoASQJdiYONL4OFZgkRQzAi0uM3P3g5MBhekcVeHe9 HFPzimh9bD/8Q5018AjaOrkzukyKplVUIAuYh5HAQVmqX1oH1XUsMM//sZzl10Aa/q4x VsDGOUpfJZqN285KTfzRL5/GHL2G+lGjbyFPI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=bfAQ2yQr6PvXFnkTZcTggGt9Hq3L4y7mdonLePtVO7c=; b=WhXtjYWYkh9DQ8ZapBg6UENPDq1x6RONin6NnRuBSCMJnUmM9xBn/ovbesXMjVx5aP nqXZWFEjCDfTs4lSQLj0E92B5yKGAboKJ6S+GZ67PIb3qNhZdiay5AEoeffCHb/jeOCh 8uLsIWwQNzI+KRIC1XHZo0/DpaVf/eMc2GLbtS1VvCTEa/1unZ+GlG2jPFG7qOTcpHHu zO6svao7rsyJ/M9zARRQpOVD+4S65g6eo1fREshuoPRbBLTqx/7mCFwbJdGAIw7VX5mb 8tehDimD5O58/bcyf6943LYCuhNmmtv7K1U2xM/y3m/djX3p/7dq/WXwKpMJHi5USr+l Qf3w== X-Gm-Message-State: AJaThX5scXtNvu3d0bKsGyeS42X91x1bqCFVJOhLgtN13zUFnydYPT74 YJI/BrzQEzra0O/wMCH7rdB0uIFmyeg= X-Received: by 10.28.147.84 with SMTP id v81mr2228263wmd.102.1510213967678; Wed, 08 Nov 2017 23:52:47 -0800 (PST) Received: from cloudburst.twiddle.net (93-45-2-58.ip99.fastwebnet.it. [93.45.2.58]) by smtp.gmail.com with ESMTPSA id g65sm2856109wmf.5.2017.11.08.23.52.46 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 08 Nov 2017 23:52:46 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 9 Nov 2017 08:52:42 +0100 Message-Id: <20171109075243.4794-2-richard.henderson@linaro.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20171109075243.4794-1-richard.henderson@linaro.org> References: <20171109075243.4794-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:400c:c09::242 Subject: [Qemu-devel] [PULL 1/2] disas: Dump insn bytes along with capstone disassembly X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" This feature is present for some targets in the bfd disassembler(s). Implement it generically for all capstone users. Suggested-by: Peter Maydell Signed-off-by: Richard Henderson --- include/disas/bfd.h | 2 ++ disas.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++------- target/arm/cpu.c | 6 ++++ target/i386/cpu.c | 2 ++ 4 files changed, 94 insertions(+), 12 deletions(-) -- 2.13.6 diff --git a/include/disas/bfd.h b/include/disas/bfd.h index 1f88c9e9d5..46c7ec3376 100644 --- a/include/disas/bfd.h +++ b/include/disas/bfd.h @@ -374,6 +374,8 @@ typedef struct disassemble_info { /* Options for Capstone disassembly. */ int cap_arch; int cap_mode; + int cap_insn_unit; + int cap_insn_split; } disassemble_info; diff --git a/disas.c b/disas.c index 92b389d25f..d4ad1089ef 100644 --- a/disas.c +++ b/disas.c @@ -220,6 +220,77 @@ static cs_err cap_disas_start(disassemble_info *info, csh *handle) return CS_ERR_OK; } +static void cap_dump_insn_units(disassemble_info *info, cs_insn *insn, + int i, int n) +{ + fprintf_function print = info->fprintf_func; + FILE *stream = info->stream; + + switch (info->cap_insn_unit) { + case 4: + if (info->endian == BFD_ENDIAN_BIG) { + for (; i < n; i += 4) { + print(stream, " %08x", ldl_be_p(insn->bytes + i)); + + } + } else { + for (; i < n; i += 4) { + print(stream, " %08x", ldl_le_p(insn->bytes + i)); + } + } + break; + + case 2: + if (info->endian == BFD_ENDIAN_BIG) { + for (; i < n; i += 2) { + print(stream, " %04x", lduw_be_p(insn->bytes + i)); + } + } else { + for (; i < n; i += 2) { + print(stream, " %04x", lduw_le_p(insn->bytes + i)); + } + } + break; + + default: + for (; i < n; i++) { + print(stream, " %02x", insn->bytes[i]); + } + break; + } +} + +static void cap_dump_insn(disassemble_info *info, cs_insn *insn) +{ + fprintf_function print = info->fprintf_func; + int i, n, split; + + print(info->stream, "0x%08" PRIx64 ": ", insn->address); + + n = insn->size; + split = info->cap_insn_split; + + /* Dump the first SPLIT bytes of the instruction. */ + cap_dump_insn_units(info, insn, 0, MIN(n, split)); + + /* Add padding up to SPLIT so that mnemonics line up. */ + if (n < split) { + int width = (split - n) / info->cap_insn_unit; + width *= (2 * info->cap_insn_unit + 1); + print(info->stream, "%*s", width, ""); + } + + /* Print the actual instruction. */ + print(info->stream, " %-8s %s\n", insn->mnemonic, insn->op_str); + + /* Dump any remaining part of the insn on subsequent lines. */ + for (i = split; i < n; i += split) { + print(info->stream, "0x%08" PRIx64 ": ", insn->address + i); + cap_dump_insn_units(info, insn, i, MIN(n, i + split)); + print(info->stream, "\n"); + } +} + /* Disassemble SIZE bytes at PC for the target. */ static bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size) { @@ -242,10 +313,7 @@ static bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size) size -= tsize; while (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) { - (*info->fprintf_func)(info->stream, - "0x%08" PRIx64 ": %-12s %s\n", - insn->address, insn->mnemonic, - insn->op_str); + cap_dump_insn(info, insn); } /* If the target memory is not consumed, go back for more... */ @@ -290,10 +358,7 @@ static bool cap_disas_host(disassemble_info *info, void *code, size_t size) pc = (uintptr_t)code; while (cs_disasm_iter(handle, &cbuf, &size, &pc, insn)) { - (*info->fprintf_func)(info->stream, - "0x%08" PRIx64 ": %-12s %s\n", - insn->address, insn->mnemonic, - insn->op_str); + cap_dump_insn(info, insn); } if (size != 0) { (*info->fprintf_func)(info->stream, @@ -337,10 +402,7 @@ static bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count) csize += tsize; if (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) { - (*info->fprintf_func)(info->stream, - "0x%08" PRIx64 ": %-12s %s\n", - insn->address, insn->mnemonic, - insn->op_str); + cap_dump_insn(info, insn); if (--count <= 0) { break; } @@ -376,6 +438,8 @@ void target_disas(FILE *out, CPUState *cpu, target_ulong code, s.info.print_address_func = generic_print_address; s.info.cap_arch = -1; s.info.cap_mode = 0; + s.info.cap_insn_unit = 4; + s.info.cap_insn_split = 4; #ifdef TARGET_WORDS_BIGENDIAN s.info.endian = BFD_ENDIAN_BIG; @@ -427,6 +491,8 @@ void disas(FILE *out, void *code, unsigned long size) s.info.buffer_length = size; s.info.cap_arch = -1; s.info.cap_mode = 0; + s.info.cap_insn_unit = 4; + s.info.cap_insn_split = 4; #ifdef HOST_WORDS_BIGENDIAN s.info.endian = BFD_ENDIAN_BIG; @@ -440,11 +506,15 @@ void disas(FILE *out, void *code, unsigned long size) print_insn = print_insn_i386; s.info.cap_arch = CS_ARCH_X86; s.info.cap_mode = CS_MODE_32; + s.info.cap_insn_unit = 1; + s.info.cap_insn_split = 8; #elif defined(__x86_64__) s.info.mach = bfd_mach_x86_64; print_insn = print_insn_i386; s.info.cap_arch = CS_ARCH_X86; s.info.cap_mode = CS_MODE_64; + s.info.cap_insn_unit = 1; + s.info.cap_insn_split = 8; #elif defined(_ARCH_PPC) s.info.disassembler_options = (char *)"any"; print_insn = print_insn_ppc; @@ -537,6 +607,8 @@ void monitor_disas(Monitor *mon, CPUState *cpu, s.info.buffer_vma = pc; s.info.cap_arch = -1; s.info.cap_mode = 0; + s.info.cap_insn_unit = 4; + s.info.cap_insn_split = 4; #ifdef TARGET_WORDS_BIGENDIAN s.info.endian = BFD_ENDIAN_BIG; diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 47c8b2a85c..7f7a3d1e32 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -489,13 +489,19 @@ static void arm_disas_set_info(CPUState *cpu, disassemble_info *info) info->print_insn = print_insn_arm_a64; #endif info->cap_arch = CS_ARCH_ARM64; + info->cap_insn_unit = 4; + info->cap_insn_split = 4; } else { int cap_mode; if (env->thumb) { info->print_insn = print_insn_thumb1; + info->cap_insn_unit = 2; + info->cap_insn_split = 4; cap_mode = CS_MODE_THUMB; } else { info->print_insn = print_insn_arm; + info->cap_insn_unit = 4; + info->cap_insn_split = 4; cap_mode = CS_MODE_ARM; } if (arm_feature(env, ARM_FEATURE_V8)) { diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 6f21a5e518..1edcf29e27 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -4109,6 +4109,8 @@ static void x86_disas_set_info(CPUState *cs, disassemble_info *info) info->cap_mode = (env->hflags & HF_CS64_MASK ? CS_MODE_64 : env->hflags & HF_CS32_MASK ? CS_MODE_32 : CS_MODE_16); + info->cap_insn_unit = 1; + info->cap_insn_split = 8; } static Property x86_cpu_properties[] = {