Capstone disassembler
-----BEGIN PGP SIGNATURE----- iQEcBAABAgAGBQJZ8bGHAAoJEGTfOOivfiFfOXQH/jc3BbQ+ulxvQSgA3rI2JE1e Ww5FK5HEs4qZU3hz4EtE2Cd5p7qV5I4tWRtbxzc6BGBwLsfz3a60Abx7726sZiH0 ZuULTsWXQ/71XfZHQysgOSoy36G8xj/1yvrMWHjDCfWp/pzz479YXWSSn2TWEHpI jI6nKP5ALdv5XTAaglGaNzqVeWgjKXJn4O8qZFS7axj7hndzLFguymfm8rV8DAdd LRuYWOizzzJ0dcaO/HHyLTzSl7rR0g+DmcOAuFCREy4f+r6tXijwiirB5f7ZJiqc hgEBq/6NfztW2+pAUSxqI2Kuq1zVETTpZORH1+UxvVk9GPu1ouYldMx0NrYhDtc= =fC5W -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/rth/tags/pull-dis-20171026' into staging Capstone disassembler # gpg: Signature made Thu 26 Oct 2017 10:57:27 BST # gpg: using RSA key 0x64DF38E8AF7E215F # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * remotes/rth/tags/pull-dis-20171026: disas: Add capstone as submodule disas: Remove monitor_disas_is_physical ppc: Support Capstone in disas_set_info arm: Support Capstone in disas_set_info i386: Support Capstone in disas_set_info disas: Support the Capstone disassembler library disas: Remove unused flags arguments target/arm: Don't set INSN_ARM_BE32 for CONFIG_USER_ONLY target/arm: Move BE32 disassembler fixup target/ppc: Convert to disas_set_info hook target/i386: Convert to disas_set_info hook Signed-off-by: Peter Maydell <peter.maydell@linaro.org> # Conflicts: # target/i386/cpu.c # target/ppc/translate_init.c
This commit is contained in:
		
						commit
						6e6430a821
					
				
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							| @ -37,3 +37,6 @@ | ||||
| [submodule "ui/keycodemapdb"] | ||||
| 	path = ui/keycodemapdb | ||||
| 	url = git://git.qemu.org/keycodemapdb.git | ||||
| [submodule "capstone"] | ||||
| 	path = capstone | ||||
| 	url = git://git.qemu.org/capstone.git | ||||
|  | ||||
							
								
								
									
										15
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								Makefile
									
									
									
									
									
								
							| @ -383,6 +383,21 @@ subdir-dtc: .git-submodule-status dtc/libfdt dtc/tests | ||||
| dtc/%: .git-submodule-status | ||||
| 	mkdir -p $@ | ||||
| 
 | ||||
| # Overriding CFLAGS causes us to lose defines added in the sub-makefile.
 | ||||
| # Not overriding CFLAGS leads to mis-matches between compilation modes.
 | ||||
| # Therefore we replicate some of the logic in the sub-makefile.
 | ||||
| # Remove all the extra -Warning flags that QEMU uses that Capstone doesn't;
 | ||||
| # no need to annoy QEMU developers with such things.
 | ||||
| CAP_CFLAGS = $(patsubst -W%,,$(CFLAGS) $(QEMU_CFLAGS)) | ||||
| CAP_CFLAGS += -DCAPSTONE_USE_SYS_DYN_MEM | ||||
| CAP_CFLAGS += -DCAPSTONE_HAS_ARM | ||||
| CAP_CFLAGS += -DCAPSTONE_HAS_ARM64 | ||||
| CAP_CFLAGS += -DCAPSTONE_HAS_POWERPC | ||||
| CAP_CFLAGS += -DCAPSTONE_HAS_X86 | ||||
| 
 | ||||
| subdir-capstone: .git-submodule-status | ||||
| 	$(call quiet-command,$(MAKE) -C $(SRC_PATH)/capstone CAPSTONE_SHARED=no BUILDDIR="$(BUILD_DIR)/capstone" CC="$(CC)" AR="$(AR)" LD="$(LD)" CFLAGS="$(CAP_CFLAGS)" $(SUBDIR_MAKEFLAGS) $(BUILD_DIR)/capstone/$(LIBCAPSTONE)) | ||||
| 
 | ||||
| $(SUBDIR_RULES): libqemuutil.a $(common-obj-y) $(chardev-obj-y) \ | ||||
| 	$(qom-obj-y) $(crypto-aes-obj-$(CONFIG_USER_ONLY)) | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										1
									
								
								capstone
									
									
									
									
									
										Submodule
									
								
							
							
								
								
								
								
								
								
									
									
								
							
						
						
									
										1
									
								
								capstone
									
									
									
									
									
										Submodule
									
								
							| @ -0,0 +1 @@ | ||||
| Subproject commit 22ead3e0bfdb87516656453336160e0a37b066bf | ||||
							
								
								
									
										72
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										72
									
								
								configure
									
									
									
									
										vendored
									
									
								
							| @ -375,6 +375,7 @@ opengl_dmabuf="no" | ||||
| cpuid_h="no" | ||||
| avx2_opt="no" | ||||
| zlib="yes" | ||||
| capstone="" | ||||
| lzo="" | ||||
| snappy="" | ||||
| bzip2="" | ||||
| @ -1294,6 +1295,14 @@ for opt do | ||||
|           error_exit "vhost-user isn't available on win32" | ||||
|       fi | ||||
|   ;; | ||||
|   --disable-capstone) capstone="no" | ||||
|   ;; | ||||
|   --enable-capstone) capstone="yes" | ||||
|   ;; | ||||
|   --enable-capstone=git) capstone="git" | ||||
|   ;; | ||||
|   --enable-capstone=system) capstone="system" | ||||
|   ;; | ||||
|   *) | ||||
|       echo "ERROR: unknown option $opt" | ||||
|       echo "Try '$0 --help' for more information" | ||||
| @ -1541,6 +1550,7 @@ disabled with --disable-FEATURE, default is enabled if available: | ||||
|   vxhs            Veritas HyperScale vDisk backend support | ||||
|   crypto-afalg    Linux AF_ALG crypto backend driver | ||||
|   vhost-user      vhost-user support | ||||
|   capstone        capstone disassembler support | ||||
| 
 | ||||
| NOTE: The object files are built at the place where configure is launched | ||||
| EOF | ||||
| @ -4410,6 +4420,58 @@ EOF | ||||
|   fi | ||||
| fi | ||||
| 
 | ||||
| ########################################## | ||||
| # capstone | ||||
| 
 | ||||
| case "$capstone" in | ||||
|   "" | yes) | ||||
|     if $pkg_config capstone; then | ||||
|       capstone=system | ||||
|     elif test -e "${source_path}/.git" ; then | ||||
|       capstone=git | ||||
|     elif test -e "${source_path}/capstone/Makefile" ; then | ||||
|       capstone=internal | ||||
|     elif test -z "$capstone" ; then | ||||
|       capstone=no | ||||
|     else | ||||
|       feature_not_found "capstone" "Install capstone devel or git submodule" | ||||
|     fi | ||||
|     ;; | ||||
| 
 | ||||
|   system) | ||||
|     if ! $pkg_config capstone; then | ||||
|       feature_not_found "capstone" "Install capstone devel" | ||||
|     fi | ||||
|     ;; | ||||
| esac | ||||
| 
 | ||||
| case "$capstone" in | ||||
|   git | internal) | ||||
|     if test "$capstone" = git; then | ||||
|       git_submodules="${git_submodules} capstone" | ||||
|     fi | ||||
|     mkdir -p capstone | ||||
|     QEMU_CFLAGS="$QEMU_CFLAGS -I\$(SRC_PATH)/capstone/include" | ||||
|     if test "$mingw32" = "yes"; then | ||||
|       LIBCAPSTONE=capstone.lib | ||||
|     else | ||||
|       LIBCAPSTONE=libcapstone.a | ||||
|     fi | ||||
|     LIBS="-L\$(BUILD_DIR)/capstone -lcapstone $LIBS" | ||||
|     ;; | ||||
| 
 | ||||
|   system) | ||||
|     QEMU_CFLAGS="$QEMU_CFLAGS $($pkg_config --cflags capstone)" | ||||
|     LIBS="$($pkg_config --libs capstone) $LIBS" | ||||
|     ;; | ||||
| 
 | ||||
|   no) | ||||
|     ;; | ||||
|   *) | ||||
|     error_exit "Unknown state for capstone: $capstone" | ||||
|     ;; | ||||
| esac | ||||
| 
 | ||||
| ########################################## | ||||
| # check if we have fdatasync | ||||
| 
 | ||||
| @ -5468,6 +5530,7 @@ echo "jemalloc support  $jemalloc" | ||||
| echo "avx2 optimization $avx2_opt" | ||||
| echo "replication support $replication" | ||||
| echo "VxHS block device $vxhs" | ||||
| echo "capstone          $capstone" | ||||
| 
 | ||||
| if test "$sdl_too_old" = "yes"; then | ||||
| echo "-> Your SDL version is too old - please upgrade to have SDL support" | ||||
| @ -6142,6 +6205,9 @@ fi | ||||
| if test "$ivshmem" = "yes" ; then | ||||
|   echo "CONFIG_IVSHMEM=y" >> $config_host_mak | ||||
| fi | ||||
| if test "$capstone" != "no" ; then | ||||
|   echo "CONFIG_CAPSTONE=y" >> $config_host_mak | ||||
| fi | ||||
| 
 | ||||
| # Hold two types of flag: | ||||
| #   CONFIG_THREAD_SETNAME_BYTHREAD  - we've got a way of setting the name on | ||||
| @ -6624,6 +6690,12 @@ done # for target in $targets | ||||
| if [ "$dtc_internal" = "yes" ]; then | ||||
|   echo "config-host.h: subdir-dtc" >> $config_host_mak | ||||
| fi | ||||
| if [ "$capstone" = "git" -o "$capstone" = "internal" ]; then | ||||
|   echo "config-host.h: subdir-capstone" >> $config_host_mak | ||||
| fi | ||||
| if test -n "$LIBCAPSTONE"; then | ||||
|   echo "LIBCAPSTONE=$LIBCAPSTONE" >> $config_host_mak | ||||
| fi | ||||
| 
 | ||||
| if test "$numa" = "yes"; then | ||||
|   echo "CONFIG_NUMA=y" >> $config_host_mak | ||||
|  | ||||
							
								
								
									
										308
									
								
								disas.c
									
									
									
									
									
								
							
							
						
						
									
										308
									
								
								disas.c
									
									
									
									
									
								
							| @ -6,6 +6,7 @@ | ||||
| 
 | ||||
| #include "cpu.h" | ||||
| #include "disas/disas.h" | ||||
| #include "disas/capstone.h" | ||||
| 
 | ||||
| typedef struct CPUDebug { | ||||
|     struct disassemble_info info; | ||||
| @ -171,15 +172,195 @@ static int print_insn_od_target(bfd_vma pc, disassemble_info *info) | ||||
|     return print_insn_objdump(pc, info, "OBJD-T"); | ||||
| } | ||||
| 
 | ||||
| /* Disassemble this for me please... (debugging). 'flags' has the following
 | ||||
|    values: | ||||
|     i386 - 1 means 16 bit code, 2 means 64 bit code | ||||
|     ppc  - bits 0:15 specify (optionally) the machine instruction set; | ||||
|            bit 16 indicates little endian. | ||||
|     other targets - unused | ||||
|  */ | ||||
| #ifdef CONFIG_CAPSTONE | ||||
| /* Temporary storage for the capstone library.  This will be alloced via
 | ||||
|    malloc with a size private to the library; thus there's no reason not | ||||
|    to share this across calls and across host vs target disassembly.  */ | ||||
| static __thread cs_insn *cap_insn; | ||||
| 
 | ||||
| /* 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 | ||||
|    parameters via cs_option(CS_OPT_MODE, new_mode), but we cannot change | ||||
|    CS_ARCH_* in this way.  Thus we would need to be able to close and | ||||
|    re-open the target handle with a different arch for the target in order | ||||
|    to handle AArch64 vs AArch32 mode switching.  */ | ||||
| static cs_err cap_disas_start(disassemble_info *info, csh *handle) | ||||
| { | ||||
|     cs_mode cap_mode = info->cap_mode; | ||||
|     cs_err err; | ||||
| 
 | ||||
|     cap_mode += (info->endian == BFD_ENDIAN_BIG ? CS_MODE_BIG_ENDIAN | ||||
|                  : CS_MODE_LITTLE_ENDIAN); | ||||
| 
 | ||||
|     err = cs_open(info->cap_arch, cap_mode, handle); | ||||
|     if (err != CS_ERR_OK) { | ||||
|         return err; | ||||
|     } | ||||
| 
 | ||||
|     /* ??? There probably ought to be a better place to put this.  */ | ||||
|     if (info->cap_arch == 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); | ||||
|     } | ||||
| 
 | ||||
|     /* "Disassemble" unknown insns as ".byte W,X,Y,Z".  */ | ||||
|     cs_option(*handle, CS_OPT_SKIPDATA, CS_OPT_ON); | ||||
| 
 | ||||
|     /* Allocate temp space for cs_disasm_iter.  */ | ||||
|     if (cap_insn == NULL) { | ||||
|         cap_insn = cs_malloc(*handle); | ||||
|         if (cap_insn == NULL) { | ||||
|             cs_close(handle); | ||||
|             return CS_ERR_MEM; | ||||
|         } | ||||
|     } | ||||
|     return CS_ERR_OK; | ||||
| } | ||||
| 
 | ||||
| /* Disassemble SIZE bytes at PC for the target.  */ | ||||
| static bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size) | ||||
| { | ||||
|     uint8_t cap_buf[1024]; | ||||
|     csh handle; | ||||
|     cs_insn *insn; | ||||
|     size_t csize = 0; | ||||
| 
 | ||||
|     if (cap_disas_start(info, &handle) != CS_ERR_OK) { | ||||
|         return false; | ||||
|     } | ||||
|     insn = cap_insn; | ||||
| 
 | ||||
|     while (1) { | ||||
|         size_t tsize = MIN(sizeof(cap_buf) - csize, size); | ||||
|         const uint8_t *cbuf = cap_buf; | ||||
| 
 | ||||
|         target_read_memory(pc + csize, cap_buf + csize, tsize, info); | ||||
|         csize += tsize; | ||||
|         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); | ||||
|         } | ||||
| 
 | ||||
|         /* If the target memory is not consumed, go back for more... */ | ||||
|         if (size != 0) { | ||||
|             /* ... taking care to move any remaining fractional insn
 | ||||
|                to the beginning of the buffer.  */ | ||||
|             if (csize != 0) { | ||||
|                 memmove(cap_buf, cbuf, csize); | ||||
|             } | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         /* Since the target memory is consumed, we should not have
 | ||||
|            a remaining fractional insn.  */ | ||||
|         if (csize != 0) { | ||||
|             (*info->fprintf_func)(info->stream, | ||||
|                 "Disassembler disagrees with translator " | ||||
|                 "over instruction decoding\n" | ||||
|                 "Please report this to qemu-devel@nongnu.org\n"); | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     cs_close(&handle); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| /* Disassemble SIZE bytes at CODE for the host.  */ | ||||
| static bool cap_disas_host(disassemble_info *info, void *code, size_t size) | ||||
| { | ||||
|     csh handle; | ||||
|     const uint8_t *cbuf; | ||||
|     cs_insn *insn; | ||||
|     uint64_t pc; | ||||
| 
 | ||||
|     if (cap_disas_start(info, &handle) != CS_ERR_OK) { | ||||
|         return false; | ||||
|     } | ||||
|     insn = cap_insn; | ||||
| 
 | ||||
|     cbuf = code; | ||||
|     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); | ||||
|     } | ||||
|     if (size != 0) { | ||||
|         (*info->fprintf_func)(info->stream, | ||||
|             "Disassembler disagrees with TCG over instruction encoding\n" | ||||
|             "Please report this to qemu-devel@nongnu.org\n"); | ||||
|     } | ||||
| 
 | ||||
|     cs_close(&handle); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| #if !defined(CONFIG_USER_ONLY) | ||||
| /* Disassemble COUNT insns at PC for the target.  */ | ||||
| static bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count) | ||||
| { | ||||
|     uint8_t cap_buf[32]; | ||||
|     csh handle; | ||||
|     cs_insn *insn; | ||||
|     size_t csize = 0; | ||||
| 
 | ||||
|     if (cap_disas_start(info, &handle) != CS_ERR_OK) { | ||||
|         return false; | ||||
|     } | ||||
|     insn = cap_insn; | ||||
| 
 | ||||
|     while (1) { | ||||
|         /* We want to read memory for one insn, but generically we do not
 | ||||
|            know how much memory that is.  We have a small buffer which is | ||||
|            known to be sufficient for all supported targets.  Try to not | ||||
|            read beyond the page, Just In Case.  For even more simplicity, | ||||
|            ignore the actual target page size and use a 1k boundary.  If | ||||
|            that turns out to be insufficient, we'll come back around the | ||||
|            loop and read more.  */ | ||||
|         uint64_t epc = QEMU_ALIGN_UP(pc + csize + 1, 1024); | ||||
|         size_t tsize = MIN(sizeof(cap_buf) - csize, epc - pc); | ||||
|         const uint8_t *cbuf = cap_buf; | ||||
| 
 | ||||
|         /* Make certain that we can make progress.  */ | ||||
|         assert(tsize != 0); | ||||
|         info->read_memory_func(pc, cap_buf + csize, tsize, info); | ||||
|         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); | ||||
|             if (--count <= 0) { | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         memmove(cap_buf, cbuf, csize); | ||||
|     } | ||||
| 
 | ||||
|     cs_close(&handle); | ||||
|     return true; | ||||
| } | ||||
| #endif /* !CONFIG_USER_ONLY */ | ||||
| #else | ||||
| # define cap_disas_target(i, p, s)  false | ||||
| # define cap_disas_host(i, p, s)  false | ||||
| # define cap_disas_monitor(i, p, c)  false | ||||
| #endif /* CONFIG_CAPSTONE */ | ||||
| 
 | ||||
| /* Disassemble this for me please... (debugging).  */ | ||||
| void target_disas(FILE *out, CPUState *cpu, target_ulong code, | ||||
|                   target_ulong size, int flags) | ||||
|                   target_ulong size) | ||||
| { | ||||
|     CPUClass *cc = CPU_GET_CLASS(cpu); | ||||
|     target_ulong pc; | ||||
| @ -193,6 +374,8 @@ void target_disas(FILE *out, CPUState *cpu, target_ulong code, | ||||
|     s.info.buffer_vma = code; | ||||
|     s.info.buffer_length = size; | ||||
|     s.info.print_address_func = generic_print_address; | ||||
|     s.info.cap_arch = -1; | ||||
|     s.info.cap_mode = 0; | ||||
| 
 | ||||
| #ifdef TARGET_WORDS_BIGENDIAN | ||||
|     s.info.endian = BFD_ENDIAN_BIG; | ||||
| @ -204,32 +387,10 @@ void target_disas(FILE *out, CPUState *cpu, target_ulong code, | ||||
|         cc->disas_set_info(cpu, &s.info); | ||||
|     } | ||||
| 
 | ||||
| #if defined(TARGET_I386) | ||||
|     if (flags == 2) { | ||||
|         s.info.mach = bfd_mach_x86_64; | ||||
|     } else if (flags == 1) { | ||||
|         s.info.mach = bfd_mach_i386_i8086; | ||||
|     } else { | ||||
|         s.info.mach = bfd_mach_i386_i386; | ||||
|     if (s.info.cap_arch >= 0 && cap_disas_target(&s.info, code, size)) { | ||||
|         return; | ||||
|     } | ||||
|     s.info.print_insn = print_insn_i386; | ||||
| #elif defined(TARGET_PPC) | ||||
|     if ((flags >> 16) & 1) { | ||||
|         s.info.endian = BFD_ENDIAN_LITTLE; | ||||
|     } | ||||
|     if (flags & 0xFFFF) { | ||||
|         /* If we have a precise definition of the instruction set, use it. */ | ||||
|         s.info.mach = flags & 0xFFFF; | ||||
|     } else { | ||||
| #ifdef TARGET_PPC64 | ||||
|         s.info.mach = bfd_mach_ppc64; | ||||
| #else | ||||
|         s.info.mach = bfd_mach_ppc; | ||||
| #endif | ||||
|     } | ||||
|     s.info.disassembler_options = (char *)"any"; | ||||
|     s.info.print_insn = print_insn_ppc; | ||||
| #endif | ||||
| 
 | ||||
|     if (s.info.print_insn == NULL) { | ||||
|         s.info.print_insn = print_insn_od_target; | ||||
|     } | ||||
| @ -237,18 +398,6 @@ void target_disas(FILE *out, CPUState *cpu, target_ulong code, | ||||
|     for (pc = code; size > 0; pc += count, size -= count) { | ||||
| 	fprintf(out, "0x" TARGET_FMT_lx ":  ", pc); | ||||
| 	count = s.info.print_insn(pc, &s.info); | ||||
| #if 0 | ||||
|         { | ||||
|             int i; | ||||
|             uint8_t b; | ||||
|             fprintf(out, " {"); | ||||
|             for(i = 0; i < count; i++) { | ||||
|                 target_read_memory(pc + i, &b, 1, &s.info); | ||||
|                 fprintf(out, " %02x", b); | ||||
|             } | ||||
|             fprintf(out, " }"); | ||||
|         } | ||||
| #endif | ||||
| 	fprintf(out, "\n"); | ||||
| 	if (count < 0) | ||||
| 	    break; | ||||
| @ -276,6 +425,8 @@ void disas(FILE *out, void *code, unsigned long size) | ||||
|     s.info.buffer = code; | ||||
|     s.info.buffer_vma = (uintptr_t)code; | ||||
|     s.info.buffer_length = size; | ||||
|     s.info.cap_arch = -1; | ||||
|     s.info.cap_mode = 0; | ||||
| 
 | ||||
| #ifdef HOST_WORDS_BIGENDIAN | ||||
|     s.info.endian = BFD_ENDIAN_BIG; | ||||
| @ -287,14 +438,23 @@ void disas(FILE *out, void *code, unsigned long size) | ||||
| #elif defined(__i386__) | ||||
|     s.info.mach = bfd_mach_i386_i386; | ||||
|     print_insn = print_insn_i386; | ||||
|     s.info.cap_arch = CS_ARCH_X86; | ||||
|     s.info.cap_mode = CS_MODE_32; | ||||
| #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; | ||||
| #elif defined(_ARCH_PPC) | ||||
|     s.info.disassembler_options = (char *)"any"; | ||||
|     print_insn = print_insn_ppc; | ||||
|     s.info.cap_arch = CS_ARCH_PPC; | ||||
| # ifdef _ARCH_PPC64 | ||||
|     s.info.cap_mode = CS_MODE_64; | ||||
| # endif | ||||
| #elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS) | ||||
|     print_insn = print_insn_arm_a64; | ||||
|     s.info.cap_arch = CS_ARCH_ARM64; | ||||
| #elif defined(__alpha__) | ||||
|     print_insn = print_insn_alpha; | ||||
| #elif defined(__sparc__) | ||||
| @ -302,6 +462,8 @@ void disas(FILE *out, void *code, unsigned long size) | ||||
|     s.info.mach = bfd_mach_sparc_v9b; | ||||
| #elif defined(__arm__) | ||||
|     print_insn = print_insn_arm; | ||||
|     s.info.cap_arch = CS_ARCH_ARM; | ||||
|     /* TCG only generates code for arm mode.  */ | ||||
| #elif defined(__MIPSEB__) | ||||
|     print_insn = print_insn_big_mips; | ||||
| #elif defined(__MIPSEL__) | ||||
| @ -313,6 +475,11 @@ void disas(FILE *out, void *code, unsigned long size) | ||||
| #elif defined(__hppa__) | ||||
|     print_insn = print_insn_hppa; | ||||
| #endif | ||||
| 
 | ||||
|     if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size)) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (print_insn == NULL) { | ||||
|         print_insn = print_insn_od_host; | ||||
|     } | ||||
| @ -345,26 +512,17 @@ const char *lookup_symbol(target_ulong orig_addr) | ||||
| 
 | ||||
| #include "monitor/monitor.h" | ||||
| 
 | ||||
| static int monitor_disas_is_physical; | ||||
| 
 | ||||
| static int | ||||
| monitor_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int length, | ||||
| physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length, | ||||
|                      struct disassemble_info *info) | ||||
| { | ||||
|     CPUDebug *s = container_of(info, CPUDebug, info); | ||||
| 
 | ||||
|     if (monitor_disas_is_physical) { | ||||
|         cpu_physical_memory_read(memaddr, myaddr, length); | ||||
|     } else { | ||||
|         cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0); | ||||
|     } | ||||
|     cpu_physical_memory_read(memaddr, myaddr, length); | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| /* Disassembler for the monitor.
 | ||||
|    See target_disas for a description of flags. */ | ||||
| /* Disassembler for the monitor.  */ | ||||
| void monitor_disas(Monitor *mon, CPUState *cpu, | ||||
|                    target_ulong pc, int nb_insn, int is_physical, int flags) | ||||
|                    target_ulong pc, int nb_insn, int is_physical) | ||||
| { | ||||
|     CPUClass *cc = CPU_GET_CLASS(cpu); | ||||
|     int count, i; | ||||
| @ -373,11 +531,12 @@ void monitor_disas(Monitor *mon, CPUState *cpu, | ||||
|     INIT_DISASSEMBLE_INFO(s.info, (FILE *)mon, monitor_fprintf); | ||||
| 
 | ||||
|     s.cpu = cpu; | ||||
|     monitor_disas_is_physical = is_physical; | ||||
|     s.info.read_memory_func = monitor_read_memory; | ||||
|     s.info.read_memory_func | ||||
|         = (is_physical ? physical_read_memory : target_read_memory); | ||||
|     s.info.print_address_func = generic_print_address; | ||||
| 
 | ||||
|     s.info.buffer_vma = pc; | ||||
|     s.info.cap_arch = -1; | ||||
|     s.info.cap_mode = 0; | ||||
| 
 | ||||
| #ifdef TARGET_WORDS_BIGENDIAN | ||||
|     s.info.endian = BFD_ENDIAN_BIG; | ||||
| @ -389,31 +548,10 @@ void monitor_disas(Monitor *mon, CPUState *cpu, | ||||
|         cc->disas_set_info(cpu, &s.info); | ||||
|     } | ||||
| 
 | ||||
| #if defined(TARGET_I386) | ||||
|     if (flags == 2) { | ||||
|         s.info.mach = bfd_mach_x86_64; | ||||
|     } else if (flags == 1) { | ||||
|         s.info.mach = bfd_mach_i386_i8086; | ||||
|     } else { | ||||
|         s.info.mach = bfd_mach_i386_i386; | ||||
|     if (s.info.cap_arch >= 0 && cap_disas_monitor(&s.info, pc, nb_insn)) { | ||||
|         return; | ||||
|     } | ||||
|     s.info.print_insn = print_insn_i386; | ||||
| #elif defined(TARGET_PPC) | ||||
|     if (flags & 0xFFFF) { | ||||
|         /* If we have a precise definition of the instruction set, use it. */ | ||||
|         s.info.mach = flags & 0xFFFF; | ||||
|     } else { | ||||
| #ifdef TARGET_PPC64 | ||||
|         s.info.mach = bfd_mach_ppc64; | ||||
| #else | ||||
|         s.info.mach = bfd_mach_ppc; | ||||
| #endif | ||||
|     } | ||||
|     if ((flags >> 16) & 1) { | ||||
|         s.info.endian = BFD_ENDIAN_LITTLE; | ||||
|     } | ||||
|     s.info.print_insn = print_insn_ppc; | ||||
| #endif | ||||
| 
 | ||||
|     if (!s.info.print_insn) { | ||||
|         monitor_printf(mon, "0x" TARGET_FMT_lx | ||||
|                        ": Asm output not supported on this arch\n", pc); | ||||
|  | ||||
							
								
								
									
										21
									
								
								disas/arm.c
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								disas/arm.c
									
									
									
									
									
								
							| @ -70,6 +70,17 @@ static void floatformat_to_double (unsigned char *data, double *dest) | ||||
|     *dest = u.f; | ||||
| } | ||||
| 
 | ||||
| static int arm_read_memory(bfd_vma memaddr, bfd_byte *b, int length, | ||||
|                            struct disassemble_info *info) | ||||
| { | ||||
|     assert((info->flags & INSN_ARM_BE32) == 0 || length == 2 || length == 4); | ||||
| 
 | ||||
|     if ((info->flags & INSN_ARM_BE32) != 0 && length == 2) { | ||||
|         memaddr ^= 2; | ||||
|     } | ||||
|     return info->read_memory_func(memaddr, b, length, info); | ||||
| } | ||||
| 
 | ||||
| /* End of qemu specific additions.  */ | ||||
| 
 | ||||
| struct opcode32 | ||||
| @ -3810,7 +3821,7 @@ find_ifthen_state (bfd_vma pc, struct disassemble_info *info, | ||||
| 	  return; | ||||
| 	} | ||||
|       addr -= 2; | ||||
|       status = info->read_memory_func (addr, (bfd_byte *)b, 2, info); | ||||
|       status = arm_read_memory (addr, (bfd_byte *)b, 2, info); | ||||
|       if (status) | ||||
| 	return; | ||||
| 
 | ||||
| @ -3882,7 +3893,7 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info) | ||||
|       info->bytes_per_chunk = size; | ||||
|       printer = print_insn_data; | ||||
| 
 | ||||
|       status = info->read_memory_func (pc, (bfd_byte *)b, size, info); | ||||
|       status = arm_read_memory (pc, (bfd_byte *)b, size, info); | ||||
|       given = 0; | ||||
|       if (little) | ||||
| 	for (i = size - 1; i >= 0; i--) | ||||
| @ -3899,7 +3910,7 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info) | ||||
|       info->bytes_per_chunk = 4; | ||||
|       size = 4; | ||||
| 
 | ||||
|       status = info->read_memory_func (pc, (bfd_byte *)b, 4, info); | ||||
|       status = arm_read_memory (pc, (bfd_byte *)b, 4, info); | ||||
|       if (little) | ||||
| 	given = (b[0]) | (b[1] << 8) | (b[2] << 16) | ((unsigned)b[3] << 24); | ||||
|       else | ||||
| @ -3915,7 +3926,7 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info) | ||||
|       info->bytes_per_chunk = 2; | ||||
|       size = 2; | ||||
| 
 | ||||
|       status = info->read_memory_func (pc, (bfd_byte *)b, 2, info); | ||||
|       status = arm_read_memory (pc, (bfd_byte *)b, 2, info); | ||||
|       if (little) | ||||
| 	given = (b[0]) | (b[1] << 8); | ||||
|       else | ||||
| @ -3929,7 +3940,7 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info) | ||||
| 	      || (given & 0xF800) == 0xF000 | ||||
| 	      || (given & 0xF800) == 0xE800) | ||||
| 	    { | ||||
| 	      status = info->read_memory_func (pc + 2, (bfd_byte *)b, 2, info); | ||||
| 	      status = arm_read_memory (pc + 2, (bfd_byte *)b, 2, info); | ||||
| 	      if (little) | ||||
| 		given = (b[0]) | (b[1] << 8) | (given << 16); | ||||
| 	      else | ||||
|  | ||||
| @ -307,12 +307,6 @@ typedef struct disassemble_info { | ||||
|     (bfd_vma memaddr, bfd_byte *myaddr, int length, | ||||
| 	     struct disassemble_info *info); | ||||
| 
 | ||||
|   /* A place to stash the real read_memory_func if read_memory_func wants to
 | ||||
|      do some funky address arithmetic or similar (e.g. for ARM BE32 mode).  */ | ||||
|   int (*read_memory_inner_func) | ||||
|     (bfd_vma memaddr, bfd_byte *myaddr, int length, | ||||
|              struct disassemble_info *info); | ||||
| 
 | ||||
|   /* Function which should be called if we get an error that we can't
 | ||||
|      recover from.  STATUS is the errno value from read_memory_func and | ||||
|      MEMADDR is the address that we were trying to read.  INFO is a | ||||
| @ -377,6 +371,10 @@ typedef struct disassemble_info { | ||||
|   /* Command line options specific to the target disassembler.  */ | ||||
|   char * disassembler_options; | ||||
| 
 | ||||
|   /* Options for Capstone disassembly.  */ | ||||
|   int cap_arch; | ||||
|   int cap_mode; | ||||
| 
 | ||||
| } disassemble_info; | ||||
| 
 | ||||
|  | ||||
| @ -479,7 +477,6 @@ int generic_symbol_at_address(bfd_vma, struct disassemble_info *); | ||||
|   (INFO).buffer_vma = 0, \ | ||||
|   (INFO).buffer_length = 0, \ | ||||
|   (INFO).read_memory_func = buffer_read_memory, \ | ||||
|   (INFO).read_memory_inner_func = NULL, \ | ||||
|   (INFO).memory_error_func = perror_memory, \ | ||||
|   (INFO).print_address_func = generic_print_address, \ | ||||
|   (INFO).print_insn = NULL, \ | ||||
|  | ||||
							
								
								
									
										38
									
								
								include/disas/capstone.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								include/disas/capstone.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| #ifndef QEMU_CAPSTONE_H | ||||
| #define QEMU_CAPSTONE_H 1 | ||||
| 
 | ||||
| #ifdef CONFIG_CAPSTONE | ||||
| 
 | ||||
| #include <capstone.h> | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| /* Just enough to allow backends to init without ifdefs.  */ | ||||
| 
 | ||||
| #define CS_ARCH_ARM     -1 | ||||
| #define CS_ARCH_ARM64   -1 | ||||
| #define CS_ARCH_MIPS    -1 | ||||
| #define CS_ARCH_X86     -1 | ||||
| #define CS_ARCH_PPC     -1 | ||||
| #define CS_ARCH_SPARC   -1 | ||||
| #define CS_ARCH_SYSZ    -1 | ||||
| 
 | ||||
| #define CS_MODE_LITTLE_ENDIAN    0 | ||||
| #define CS_MODE_BIG_ENDIAN       0 | ||||
| #define CS_MODE_ARM              0 | ||||
| #define CS_MODE_16               0 | ||||
| #define CS_MODE_32               0 | ||||
| #define CS_MODE_64               0 | ||||
| #define CS_MODE_THUMB            0 | ||||
| #define CS_MODE_MCLASS           0 | ||||
| #define CS_MODE_V8               0 | ||||
| #define CS_MODE_MICRO            0 | ||||
| #define CS_MODE_MIPS3            0 | ||||
| #define CS_MODE_MIPS32R6         0 | ||||
| #define CS_MODE_MIPSGP64         0 | ||||
| #define CS_MODE_V9               0 | ||||
| #define CS_MODE_MIPS32           0 | ||||
| #define CS_MODE_MIPS64           0 | ||||
| 
 | ||||
| #endif /* CONFIG_CAPSTONE */ | ||||
| #endif /* QEMU_CAPSTONE_H */ | ||||
| @ -9,10 +9,10 @@ | ||||
| /* Disassemble this for me please... (debugging). */ | ||||
| void disas(FILE *out, void *code, unsigned long size); | ||||
| void target_disas(FILE *out, CPUState *cpu, target_ulong code, | ||||
|                   target_ulong size, int flags); | ||||
|                   target_ulong size); | ||||
| 
 | ||||
| void monitor_disas(Monitor *mon, CPUState *cpu, | ||||
|                    target_ulong pc, int nb_insn, int is_physical, int flags); | ||||
|                    target_ulong pc, int nb_insn, int is_physical); | ||||
| 
 | ||||
| /* Look up symbol for debugging purpose.  Returns "" if unknown. */ | ||||
| const char *lookup_symbol(target_ulong orig_addr); | ||||
|  | ||||
| @ -38,9 +38,9 @@ static inline void log_cpu_state_mask(int mask, CPUState *cpu, int flags) | ||||
| #ifdef NEED_CPU_H | ||||
| /* disas() and target_disas() to qemu_logfile: */ | ||||
| static inline void log_target_disas(CPUState *cpu, target_ulong start, | ||||
|                                     target_ulong len, int flags) | ||||
|                                     target_ulong len) | ||||
| { | ||||
|     target_disas(qemu_logfile, cpu, start, len, flags); | ||||
|     target_disas(qemu_logfile, cpu, start, len); | ||||
| } | ||||
| 
 | ||||
| static inline void log_disas(void *code, unsigned long size) | ||||
|  | ||||
							
								
								
									
										29
									
								
								monitor.c
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								monitor.c
									
									
									
									
									
								
							| @ -1309,34 +1309,7 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize, | ||||
|     } | ||||
| 
 | ||||
|     if (format == 'i') { | ||||
|         int flags = 0; | ||||
| #ifdef TARGET_I386 | ||||
|         CPUArchState *env = mon_get_cpu_env(); | ||||
|         if (wsize == 2) { | ||||
|             flags = 1; | ||||
|         } else if (wsize == 4) { | ||||
|             flags = 0; | ||||
|         } else { | ||||
|             /* as default we use the current CS size */ | ||||
|             flags = 0; | ||||
|             if (env) { | ||||
| #ifdef TARGET_X86_64 | ||||
|                 if ((env->efer & MSR_EFER_LMA) && | ||||
|                     (env->segs[R_CS].flags & DESC_L_MASK)) | ||||
|                     flags = 2; | ||||
|                 else | ||||
| #endif | ||||
|                 if (!(env->segs[R_CS].flags & DESC_B_MASK)) | ||||
|                     flags = 1; | ||||
|             } | ||||
|         } | ||||
| #endif | ||||
| #ifdef TARGET_PPC | ||||
|         CPUArchState *env = mon_get_cpu_env(); | ||||
|         flags = msr_le << 16; | ||||
|         flags |= env->bfd_mach; | ||||
| #endif | ||||
|         monitor_disas(mon, cs, addr, count, is_physical, flags); | ||||
|         monitor_disas(mon, cs, addr, count, is_physical); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -3038,7 +3038,7 @@ static void alpha_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) | ||||
| static void alpha_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu) | ||||
| { | ||||
|     qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first)); | ||||
|     log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size, 1); | ||||
|     log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size); | ||||
| } | ||||
| 
 | ||||
| static const TranslatorOps alpha_tr_ops = { | ||||
|  | ||||
| @ -33,6 +33,7 @@ | ||||
| #include "sysemu/sysemu.h" | ||||
| #include "sysemu/hw_accel.h" | ||||
| #include "kvm_arm.h" | ||||
| #include "disas/capstone.h" | ||||
| 
 | ||||
| static void arm_cpu_set_pc(CPUState *cs, vaddr value) | ||||
| { | ||||
| @ -473,25 +474,11 @@ print_insn_thumb1(bfd_vma pc, disassemble_info *info) | ||||
|   return print_insn_arm(pc | 1, info); | ||||
| } | ||||
| 
 | ||||
| static int arm_read_memory_func(bfd_vma memaddr, bfd_byte *b, | ||||
|                                 int length, struct disassemble_info *info) | ||||
| { | ||||
|     assert(info->read_memory_inner_func); | ||||
|     assert((info->flags & INSN_ARM_BE32) == 0 || length == 2 || length == 4); | ||||
| 
 | ||||
|     if ((info->flags & INSN_ARM_BE32) != 0 && length == 2) { | ||||
|         assert(info->endian == BFD_ENDIAN_LITTLE); | ||||
|         return info->read_memory_inner_func(memaddr ^ 2, (bfd_byte *)b, 2, | ||||
|                                             info); | ||||
|     } else { | ||||
|         return info->read_memory_inner_func(memaddr, b, length, info); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void arm_disas_set_info(CPUState *cpu, disassemble_info *info) | ||||
| { | ||||
|     ARMCPU *ac = ARM_CPU(cpu); | ||||
|     CPUARMState *env = &ac->env; | ||||
|     bool sctlr_b; | ||||
| 
 | ||||
|     if (is_a64(env)) { | ||||
|         /* We might not be compiled with the A64 disassembler
 | ||||
| @ -501,26 +488,40 @@ static void arm_disas_set_info(CPUState *cpu, disassemble_info *info) | ||||
| #if defined(CONFIG_ARM_A64_DIS) | ||||
|         info->print_insn = print_insn_arm_a64; | ||||
| #endif | ||||
|     } else if (env->thumb) { | ||||
|         info->print_insn = print_insn_thumb1; | ||||
|         info->cap_arch = CS_ARCH_ARM64; | ||||
|     } else { | ||||
|         info->print_insn = print_insn_arm; | ||||
|         int cap_mode; | ||||
|         if (env->thumb) { | ||||
|             info->print_insn = print_insn_thumb1; | ||||
|             cap_mode = CS_MODE_THUMB; | ||||
|         } else { | ||||
|             info->print_insn = print_insn_arm; | ||||
|             cap_mode = CS_MODE_ARM; | ||||
|         } | ||||
|         if (arm_feature(env, ARM_FEATURE_V8)) { | ||||
|             cap_mode |= CS_MODE_V8; | ||||
|         } | ||||
|         if (arm_feature(env, ARM_FEATURE_M)) { | ||||
|             cap_mode |= CS_MODE_MCLASS; | ||||
|         } | ||||
|         info->cap_arch = CS_ARCH_ARM; | ||||
|         info->cap_mode = cap_mode; | ||||
|     } | ||||
|     if (bswap_code(arm_sctlr_b(env))) { | ||||
| 
 | ||||
|     sctlr_b = arm_sctlr_b(env); | ||||
|     if (bswap_code(sctlr_b)) { | ||||
| #ifdef TARGET_WORDS_BIGENDIAN | ||||
|         info->endian = BFD_ENDIAN_LITTLE; | ||||
| #else | ||||
|         info->endian = BFD_ENDIAN_BIG; | ||||
| #endif | ||||
|     } | ||||
|     if (info->read_memory_inner_func == NULL) { | ||||
|         info->read_memory_inner_func = info->read_memory_func; | ||||
|         info->read_memory_func = arm_read_memory_func; | ||||
|     } | ||||
|     info->flags &= ~INSN_ARM_BE32; | ||||
|     if (arm_sctlr_b(env)) { | ||||
| #ifndef CONFIG_USER_ONLY | ||||
|     if (sctlr_b) { | ||||
|         info->flags |= INSN_ARM_BE32; | ||||
|     } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz) | ||||
|  | ||||
| @ -11423,8 +11423,7 @@ static void aarch64_tr_disas_log(const DisasContextBase *dcbase, | ||||
|     DisasContext *dc = container_of(dcbase, DisasContext, base); | ||||
| 
 | ||||
|     qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first)); | ||||
|     log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size, | ||||
|                      4 | (bswap_code(dc->sctlr_b) ? 2 : 0)); | ||||
|     log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size); | ||||
| } | ||||
| 
 | ||||
| const TranslatorOps aarch64_translator_ops = { | ||||
|  | ||||
| @ -12372,8 +12372,7 @@ static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu) | ||||
|     DisasContext *dc = container_of(dcbase, DisasContext, base); | ||||
| 
 | ||||
|     qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first)); | ||||
|     log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size, | ||||
|                      dc->thumb | (dc->sctlr_b << 1)); | ||||
|     log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size); | ||||
| } | ||||
| 
 | ||||
| static const TranslatorOps arm_translator_ops = { | ||||
|  | ||||
| @ -3296,8 +3296,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) | ||||
|         qemu_log_lock(); | ||||
|         qemu_log("--------------\n"); | ||||
|         qemu_log("IN: %s\n", lookup_symbol(pc_start)); | ||||
|         log_target_disas(cs, pc_start, dc->pc - pc_start, | ||||
|                          env->pregs[PR_VR]); | ||||
|         log_target_disas(cs, pc_start, dc->pc - pc_start); | ||||
|         qemu_log("\nisize=%d osize=%d\n", | ||||
|                  dc->pc - pc_start, tcg_op_buf_count()); | ||||
|         qemu_log_unlock(); | ||||
|  | ||||
| @ -3902,7 +3902,7 @@ static void hppa_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) | ||||
|         break; | ||||
|     default: | ||||
|         qemu_log("IN: %s\n", lookup_symbol(tb->pc)); | ||||
|         log_target_disas(cs, tb->pc, tb->size, 1); | ||||
|         log_target_disas(cs, tb->pc, tb->size); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -51,6 +51,8 @@ | ||||
| #include "hw/i386/apic_internal.h" | ||||
| #endif | ||||
| 
 | ||||
| #include "disas/capstone.h" | ||||
| 
 | ||||
| 
 | ||||
| /* Cache topology CPUID constants: */ | ||||
| 
 | ||||
| @ -4093,6 +4095,22 @@ static bool x86_cpu_has_work(CPUState *cs) | ||||
|             !(env->hflags & HF_SMM_MASK)); | ||||
| } | ||||
| 
 | ||||
| static void x86_disas_set_info(CPUState *cs, disassemble_info *info) | ||||
| { | ||||
|     X86CPU *cpu = X86_CPU(cs); | ||||
|     CPUX86State *env = &cpu->env; | ||||
| 
 | ||||
|     info->mach = (env->hflags & HF_CS64_MASK ? bfd_mach_x86_64 | ||||
|                   : env->hflags & HF_CS32_MASK ? bfd_mach_i386_i386 | ||||
|                   : bfd_mach_i386_i8086); | ||||
|     info->print_insn = print_insn_i386; | ||||
| 
 | ||||
|     info->cap_arch = CS_ARCH_X86; | ||||
|     info->cap_mode = (env->hflags & HF_CS64_MASK ? CS_MODE_64 | ||||
|                       : env->hflags & HF_CS32_MASK ? CS_MODE_32 | ||||
|                       : CS_MODE_16); | ||||
| } | ||||
| 
 | ||||
| static Property x86_cpu_properties[] = { | ||||
| #ifdef CONFIG_USER_ONLY | ||||
|     /* apic_id = 0 by default for *-user, see commit 9886e834 */ | ||||
| @ -4215,6 +4233,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) | ||||
| #ifdef CONFIG_TCG | ||||
|     cc->tcg_initialize = tcg_x86_init; | ||||
| #endif | ||||
|     cc->disas_set_info = x86_disas_set_info; | ||||
| 
 | ||||
|     dc->user_creatable = true; | ||||
| } | ||||
|  | ||||
| @ -8548,15 +8548,9 @@ static void i386_tr_disas_log(const DisasContextBase *dcbase, | ||||
|                               CPUState *cpu) | ||||
| { | ||||
|     DisasContext *dc = container_of(dcbase, DisasContext, base); | ||||
|     int disas_flags = !dc->code32; | ||||
| 
 | ||||
|     qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first)); | ||||
| #ifdef TARGET_X86_64 | ||||
|     if (dc->code64) { | ||||
|         disas_flags = 2; | ||||
|     } | ||||
| #endif | ||||
|     log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size, disas_flags); | ||||
|     log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size); | ||||
| } | ||||
| 
 | ||||
| static const TranslatorOps i386_tr_ops = { | ||||
|  | ||||
| @ -1155,7 +1155,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) | ||||
|         && qemu_log_in_addr_range(pc_start)) { | ||||
|         qemu_log_lock(); | ||||
|         qemu_log("\n"); | ||||
|         log_target_disas(cs, pc_start, dc->pc - pc_start, 0); | ||||
|         log_target_disas(cs, pc_start, dc->pc - pc_start); | ||||
|         qemu_log("\nisize=%d osize=%d\n", | ||||
|                  dc->pc - pc_start, tcg_op_buf_count()); | ||||
|         qemu_log_unlock(); | ||||
|  | ||||
| @ -5623,7 +5623,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) | ||||
|         qemu_log_lock(); | ||||
|         qemu_log("----------------\n"); | ||||
|         qemu_log("IN: %s\n", lookup_symbol(pc_start)); | ||||
|         log_target_disas(cs, pc_start, dc->pc - pc_start, 0); | ||||
|         log_target_disas(cs, pc_start, dc->pc - pc_start); | ||||
|         qemu_log("\n"); | ||||
|         qemu_log_unlock(); | ||||
|     } | ||||
|  | ||||
| @ -1809,7 +1809,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) | ||||
|         qemu_log_lock(); | ||||
|         qemu_log("--------------\n"); | ||||
| #if DISAS_GNU | ||||
|         log_target_disas(cs, pc_start, dc->pc - pc_start, 0); | ||||
|         log_target_disas(cs, pc_start, dc->pc - pc_start); | ||||
| #endif | ||||
|         qemu_log("\nisize=%d osize=%d\n", | ||||
|                  dc->pc - pc_start, tcg_op_buf_count()); | ||||
|  | ||||
| @ -20369,7 +20369,7 @@ done_generating: | ||||
|         && qemu_log_in_addr_range(pc_start)) { | ||||
|         qemu_log_lock(); | ||||
|         qemu_log("IN: %s\n", lookup_symbol(pc_start)); | ||||
|         log_target_disas(cs, pc_start, ctx.pc - pc_start, 0); | ||||
|         log_target_disas(cs, pc_start, ctx.pc - pc_start); | ||||
|         qemu_log("\n"); | ||||
|         qemu_log_unlock(); | ||||
|     } | ||||
|  | ||||
| @ -906,7 +906,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) | ||||
|         && qemu_log_in_addr_range(tb->pc)) { | ||||
|         qemu_log_lock(); | ||||
|         qemu_log("IN: %s\n", lookup_symbol(tb->pc)); | ||||
|         log_target_disas(cs, tb->pc, dc->pc - tb->pc, 0); | ||||
|         log_target_disas(cs, tb->pc, dc->pc - tb->pc); | ||||
|         qemu_log("\n"); | ||||
|         qemu_log_unlock(); | ||||
|     } | ||||
|  | ||||
| @ -1650,7 +1650,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) | ||||
| 
 | ||||
|     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) | ||||
|         && qemu_log_in_addr_range(pc_start)) { | ||||
|         log_target_disas(cs, pc_start, tb->size, 0); | ||||
|         log_target_disas(cs, pc_start, tb->size); | ||||
|         qemu_log("\n"); | ||||
|         qemu_log_unlock(); | ||||
|     } | ||||
|  | ||||
| @ -7397,12 +7397,9 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) | ||||
| #if defined(DEBUG_DISAS) | ||||
|     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) | ||||
|         && qemu_log_in_addr_range(pc_start)) { | ||||
|         int flags; | ||||
|         flags = env->bfd_mach; | ||||
|         flags |= ctx.le_mode << 16; | ||||
|         qemu_log_lock(); | ||||
|         qemu_log("IN: %s\n", lookup_symbol(pc_start)); | ||||
|         log_target_disas(cs, pc_start, ctx.nip - pc_start, flags); | ||||
|         log_target_disas(cs, pc_start, ctx.nip - pc_start); | ||||
|         qemu_log("\n"); | ||||
|         qemu_log_unlock(); | ||||
|     } | ||||
|  | ||||
| @ -35,6 +35,7 @@ | ||||
| #include "mmu-book3s-v3.h" | ||||
| #include "sysemu/qtest.h" | ||||
| #include "qemu/cutils.h" | ||||
| #include "disas/capstone.h" | ||||
| 
 | ||||
| //#define PPC_DUMP_CPU
 | ||||
| //#define PPC_DEBUG_SPR
 | ||||
| @ -10515,6 +10516,31 @@ static gchar *ppc_gdb_arch_name(CPUState *cs) | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| static void ppc_disas_set_info(CPUState *cs, disassemble_info *info) | ||||
| { | ||||
|     PowerPCCPU *cpu = POWERPC_CPU(cs); | ||||
|     CPUPPCState *env = &cpu->env; | ||||
| 
 | ||||
|     if ((env->hflags >> MSR_LE) & 1) { | ||||
|         info->endian = BFD_ENDIAN_LITTLE; | ||||
|     } | ||||
|     info->mach = env->bfd_mach; | ||||
|     if (!env->bfd_mach) { | ||||
| #ifdef TARGET_PPC64 | ||||
|         info->mach = bfd_mach_ppc64; | ||||
| #else | ||||
|         info->mach = bfd_mach_ppc; | ||||
| #endif | ||||
|     } | ||||
|     info->disassembler_options = (char *)"any"; | ||||
|     info->print_insn = print_insn_ppc; | ||||
| 
 | ||||
|     info->cap_arch = CS_ARCH_PPC; | ||||
| #ifdef TARGET_PPC64 | ||||
|     info->cap_mode = CS_MODE_64; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| static Property ppc_cpu_properties[] = { | ||||
|     DEFINE_PROP_BOOL("pre-2.8-migration", PowerPCCPU, pre_2_8_migration, false), | ||||
|     DEFINE_PROP_BOOL("pre-2.10-migration", PowerPCCPU, pre_2_10_migration, | ||||
| @ -10581,7 +10607,8 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data) | ||||
| #ifdef CONFIG_TCG | ||||
|     cc->tcg_initialize = ppc_translate_init; | ||||
| #endif | ||||
| 
 | ||||
|     cc->disas_set_info = ppc_disas_set_info; | ||||
|   | ||||
|     dc->fw_name = "PowerPC,UNKNOWN"; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -5982,7 +5982,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) | ||||
|             qemu_log("IN: EXECUTE %016" PRIx64 "\n", dc.ex_value); | ||||
|         } else { | ||||
|             qemu_log("IN: %s\n", lookup_symbol(pc_start)); | ||||
|             log_target_disas(cs, pc_start, dc.pc - pc_start, 1); | ||||
|             log_target_disas(cs, pc_start, dc.pc - pc_start); | ||||
|             qemu_log("\n"); | ||||
|         } | ||||
|         qemu_log_unlock(); | ||||
|  | ||||
| @ -2336,7 +2336,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) | ||||
|         && qemu_log_in_addr_range(pc_start)) { | ||||
|         qemu_log_lock(); | ||||
| 	qemu_log("IN:\n");	/* , lookup_symbol(pc_start)); */ | ||||
|         log_target_disas(cs, pc_start, ctx.pc - pc_start, 0); | ||||
|         log_target_disas(cs, pc_start, ctx.pc - pc_start); | ||||
| 	qemu_log("\n"); | ||||
|         qemu_log_unlock(); | ||||
|     } | ||||
|  | ||||
| @ -5849,7 +5849,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock * tb) | ||||
|         qemu_log_lock(); | ||||
|         qemu_log("--------------\n"); | ||||
|         qemu_log("IN: %s\n", lookup_symbol(pc_start)); | ||||
|         log_target_disas(cs, pc_start, last_pc + 4 - pc_start, 0); | ||||
|         log_target_disas(cs, pc_start, last_pc + 4 - pc_start); | ||||
|         qemu_log("\n"); | ||||
|         qemu_log_unlock(); | ||||
|     } | ||||
|  | ||||
| @ -8837,7 +8837,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) | ||||
|         && qemu_log_in_addr_range(pc_start)) { | ||||
|         qemu_log_lock(); | ||||
|         qemu_log("IN: %s\n", lookup_symbol(pc_start)); | ||||
|         log_target_disas(cs, pc_start, ctx.pc - pc_start, 0); | ||||
|         log_target_disas(cs, pc_start, ctx.pc - pc_start); | ||||
|         qemu_log("\n"); | ||||
|         qemu_log_unlock(); | ||||
|     } | ||||
|  | ||||
| @ -2027,7 +2027,7 @@ done_generating: | ||||
|         qemu_log_lock(); | ||||
|         qemu_log("----------------\n"); | ||||
|         qemu_log("IN: %s\n", lookup_symbol(pc_start)); | ||||
|         log_target_disas(cs, pc_start, dc->pc - pc_start, 0); | ||||
|         log_target_disas(cs, pc_start, dc->pc - pc_start); | ||||
|         qemu_log("\n"); | ||||
|         qemu_log_unlock(); | ||||
|     } | ||||
|  | ||||
| @ -3247,7 +3247,7 @@ done: | ||||
|         qemu_log_lock(); | ||||
|         qemu_log("----------------\n"); | ||||
|         qemu_log("IN: %s\n", lookup_symbol(pc_start)); | ||||
|         log_target_disas(cs, pc_start, dc.pc - pc_start, 0); | ||||
|         log_target_disas(cs, pc_start, dc.pc - pc_start); | ||||
|         qemu_log("\n"); | ||||
|         qemu_log_unlock(); | ||||
|     } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Peter Maydell
						Peter Maydell