diff --git a/.cirrus.yml b/.cirrus.yml index 90645fede6..de0727cb09 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -3,10 +3,10 @@ env: freebsd_12_task: freebsd_instance: - image: freebsd-12-0-release-amd64 + image_family: freebsd-12-1 cpu: 8 memory: 8G - install_script: pkg install -y + install_script: ASSUME_ALWAYS_YES=yes pkg bootstrap -f ; pkg install -y bash bison curl cyrus-sasl git glib gmake gnutls gsed nettle perl5 pixman pkgconf png usbredir script: diff --git a/.travis.yml b/.travis.yml index 2fd63eceaa..fe708792ca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,9 +9,8 @@ compiler: cache: # There is one cache per branch and compiler version. # characteristics of each job are used to identify the cache: - # - OS name (currently, linux, osx, or windows) + # - OS name (currently only linux) # - OS distribution (for Linux, xenial, trusty, or precise) - # - macOS image name (e.g., xcode7.2) # - Names and values of visible environment variables set in .travis.yml or Settings panel timeout: 1200 ccache: true @@ -113,6 +112,7 @@ script: $(exit $BUILD_RC); fi after_script: + - df -h - if command -v ccache ; then ccache --show-stats ; fi @@ -270,31 +270,6 @@ jobs: - TEST_CMD="" - # MacOSX builds - cirrus.yml also tests some MacOS builds including latest Xcode - - - name: "OSX Xcode 10.3" - env: - - BASE_CONFIG="--disable-docs --enable-tools" - - CONFIG="--target-list=i386-softmmu,ppc-softmmu,ppc64-softmmu,m68k-softmmu,x86_64-softmmu" - os: osx - osx_image: xcode10.3 - compiler: clang - addons: - homebrew: - packages: - - ccache - - glib - - pixman - - gnu-sed - - python - update: true - before_script: - - brew link --overwrite python - - export PATH="/usr/local/opt/ccache/libexec:$PATH" - - mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR} - - ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; } - - # Python builds - name: "GCC Python 3.5 (x86_64-softmmu)" env: @@ -483,7 +458,7 @@ jobs: - genisoimage env: - TEST_CMD="make check check-tcg V=1" - - CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS},ppc64le-linux-user" + - CONFIG="--disable-containers --target-list=ppc64-softmmu,ppc64le-linux-user" - name: "[s390x] GCC check-tcg" arch: s390x diff --git a/bsd-user/main.c b/bsd-user/main.c index 770c2b267a..28f122b80e 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -738,7 +738,7 @@ int main(int argc, char **argv) CPUState *cpu; int optind; const char *r; - int gdbstub_port = 0; + const char *gdbstub = NULL; char **target_environ, **wrk; envlist_t *envlist = NULL; char *trace_file = NULL; @@ -814,7 +814,7 @@ int main(int argc, char **argv) exit(1); } } else if (!strcmp(r, "g")) { - gdbstub_port = atoi(argv[optind++]); + gdbstub = g_strdup(argv[optind++]); } else if (!strcmp(r, "r")) { qemu_uname_release = argv[optind++]; } else if (!strcmp(r, "cpu")) { @@ -1124,8 +1124,8 @@ int main(int argc, char **argv) #error unsupported target CPU #endif - if (gdbstub_port) { - gdbserver_start (gdbstub_port); + if (gdbstub) { + gdbserver_start(gdbstub); gdb_handlesig(cpu, 0); } cpu_loop(env); diff --git a/configure b/configure index 23b5e93752..0d69c360c0 100755 --- a/configure +++ b/configure @@ -303,7 +303,7 @@ libs_qga="" debug_info="yes" stack_protector="" use_containers="yes" -gdb_bin=$(command -v "gdb") +gdb_bin=$(command -v "gdb-multiarch" || command -v "gdb") if test -e "$source_path/.git" then @@ -7825,7 +7825,7 @@ case "$target_name" in ;; m68k) bflt="yes" - gdb_xml_files="cf-core.xml cf-fp.xml m68k-fp.xml" + gdb_xml_files="cf-core.xml cf-fp.xml m68k-core.xml m68k-fp.xml" TARGET_SYSTBL_ABI=common ;; microblaze|microblazeel) diff --git a/gdb-xml/m68k-core.xml b/gdb-xml/m68k-core.xml new file mode 100644 index 0000000000..5b092d26de --- /dev/null +++ b/gdb-xml/m68k-core.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdbstub.c b/gdbstub.c index 171e150950..6950fd243f 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -355,6 +355,7 @@ typedef struct GDBState { int signal; #ifdef CONFIG_USER_ONLY int fd; + char *socket_path; int running_state; #else CharBackend chr; @@ -398,8 +399,6 @@ static void reset_gdbserver_state(void) bool gdb_has_xml; #ifdef CONFIG_USER_ONLY -/* XXX: This is not thread safe. Do we care? */ -static int gdbserver_fd = -1; static int get_char(void) { @@ -2964,7 +2963,10 @@ void gdb_exit(CPUArchState *env, int code) return; } #ifdef CONFIG_USER_ONLY - if (gdbserver_fd < 0 || gdbserver_state.fd < 0) { + if (gdbserver_state.socket_path) { + unlink(gdbserver_state.socket_path); + } + if (gdbserver_state.fd < 0) { return; } #endif @@ -3011,7 +3013,7 @@ gdb_handlesig(CPUState *cpu, int sig) char buf[256]; int n; - if (gdbserver_fd < 0 || gdbserver_state.fd < 0) { + if (!gdbserver_state.init || gdbserver_state.fd < 0) { return sig; } @@ -3060,7 +3062,7 @@ void gdb_signalled(CPUArchState *env, int sig) { char buf[4]; - if (gdbserver_fd < 0 || gdbserver_state.fd < 0) { + if (!gdbserver_state.init || gdbserver_state.fd < 0) { return; } @@ -3068,7 +3070,66 @@ void gdb_signalled(CPUArchState *env, int sig) put_packet(buf); } -static bool gdb_accept(void) +static void gdb_accept_init(int fd) +{ + init_gdbserver_state(); + create_default_process(&gdbserver_state); + gdbserver_state.processes[0].attached = true; + gdbserver_state.c_cpu = gdb_first_attached_cpu(); + gdbserver_state.g_cpu = gdbserver_state.c_cpu; + gdbserver_state.fd = fd; + gdb_has_xml = false; +} + +static bool gdb_accept_socket(int gdb_fd) +{ + int fd; + + for(;;) { + fd = accept(gdb_fd, NULL, NULL); + if (fd < 0 && errno != EINTR) { + perror("accept socket"); + return false; + } else if (fd >= 0) { + qemu_set_cloexec(fd); + break; + } + } + + gdb_accept_init(fd); + return true; +} + +static int gdbserver_open_socket(const char *path) +{ + struct sockaddr_un sockaddr; + int fd, ret; + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + perror("create socket"); + return -1; + } + + sockaddr.sun_family = AF_UNIX; + pstrcpy(sockaddr.sun_path, sizeof(sockaddr.sun_path) - 1, path); + ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)); + if (ret < 0) { + perror("bind socket"); + close(fd); + return -1; + } + ret = listen(fd, 1); + if (ret < 0) { + perror("listen socket"); + close(fd); + return -1; + } + + return fd; +} + +static bool gdb_accept_tcp(int gdb_fd) { struct sockaddr_in sockaddr; socklen_t len; @@ -3076,7 +3137,7 @@ static bool gdb_accept(void) for(;;) { len = sizeof(sockaddr); - fd = accept(gdbserver_fd, (struct sockaddr *)&sockaddr, &len); + fd = accept(gdb_fd, (struct sockaddr *)&sockaddr, &len); if (fd < 0 && errno != EINTR) { perror("accept"); return false; @@ -3093,17 +3154,11 @@ static bool gdb_accept(void) return false; } - init_gdbserver_state(); - create_default_process(&gdbserver_state); - gdbserver_state.processes[0].attached = true; - gdbserver_state.c_cpu = gdb_first_attached_cpu(); - gdbserver_state.g_cpu = gdbserver_state.c_cpu; - gdbserver_state.fd = fd; - gdb_has_xml = false; + gdb_accept_init(fd); return true; } -static int gdbserver_open(int port) +static int gdbserver_open_port(int port) { struct sockaddr_in sockaddr; int fd, ret; @@ -3132,27 +3187,41 @@ static int gdbserver_open(int port) close(fd); return -1; } + return fd; } -int gdbserver_start(int port) +int gdbserver_start(const char *port_or_path) { - gdbserver_fd = gdbserver_open(port); - if (gdbserver_fd < 0) - return -1; - /* accept connections */ - if (!gdb_accept()) { - close(gdbserver_fd); - gdbserver_fd = -1; + int port = g_ascii_strtoull(port_or_path, NULL, 10); + int gdb_fd; + + if (port > 0) { + gdb_fd = gdbserver_open_port(port); + } else { + gdb_fd = gdbserver_open_socket(port_or_path); + } + + if (gdb_fd < 0) { return -1; } - return 0; + + if (port > 0 && gdb_accept_tcp(gdb_fd)) { + return 0; + } else if (gdb_accept_socket(gdb_fd)) { + gdbserver_state.socket_path = g_strdup(port_or_path); + return 0; + } + + /* gone wrong */ + close(gdb_fd); + return -1; } /* Disable gdb stub for child processes. */ void gdbserver_fork(CPUState *cpu) { - if (gdbserver_fd < 0 || gdbserver_state.fd < 0) { + if (!gdbserver_state.init || gdbserver_state.fd < 0) { return; } close(gdbserver_state.fd); diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h index 20e1072692..94d8f83e92 100644 --- a/include/exec/gdbstub.h +++ b/include/exec/gdbstub.h @@ -134,6 +134,17 @@ static inline int gdb_get_float32(GByteArray *array, float32 val) return sizeof(buf); } + +static inline int gdb_get_float64(GByteArray *array, float64 val) +{ + uint8_t buf[sizeof(CPU_DoubleU)]; + + stfq_p(buf, val); + g_byte_array_append(array, buf, sizeof(buf)); + + return sizeof(buf); +} + static inline int gdb_get_zeroes(GByteArray *array, size_t len) { guint oldlen = array->len; @@ -166,11 +177,15 @@ static inline uint8_t * gdb_get_reg_ptr(GByteArray *buf, int len) #endif -#ifdef CONFIG_USER_ONLY -int gdbserver_start(int); -#else -int gdbserver_start(const char *port); -#endif +/** + * gdbserver_start: start the gdb server + * @port_or_device: connection spec for gdb + * + * For CONFIG_USER this is either a tcp port or a path to a fifo. For + * system emulation you can use a full chardev spec for your gdbserver + * port. + */ +int gdbserver_start(const char *port_or_device); void gdbserver_cleanup(void); diff --git a/linux-user/main.c b/linux-user/main.c index 22578b1633..2cd443237d 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -51,7 +51,7 @@ char *exec_path; int singlestep; static const char *argv0; -static int gdbstub_port; +static const char *gdbstub; static envlist_t *envlist; static const char *cpu_model; static const char *cpu_type; @@ -310,7 +310,7 @@ static void handle_arg_seed(const char *arg) static void handle_arg_gdb(const char *arg) { - gdbstub_port = atoi(arg); + gdbstub = g_strdup(arg); } static void handle_arg_uname(const char *arg) @@ -861,10 +861,10 @@ int main(int argc, char **argv, char **envp) target_cpu_copy_regs(env, regs); - if (gdbstub_port) { - if (gdbserver_start(gdbstub_port) < 0) { - fprintf(stderr, "qemu: could not open gdbserver on port %d\n", - gdbstub_port); + if (gdbstub) { + if (gdbserver_start(gdbstub) < 0) { + fprintf(stderr, "qemu: could not open gdbserver on %s\n", + gdbstub); exit(EXIT_FAILURE); } gdb_handlesig(cpu, 0); diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c index 9445fcd6df..72c545149e 100644 --- a/target/m68k/cpu.c +++ b/target/m68k/cpu.c @@ -292,16 +292,38 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data) cc->tcg_initialize = m68k_tcg_init; cc->gdb_num_core_regs = 18; - cc->gdb_core_xml_file = "cf-core.xml"; dc->vmsd = &vmstate_m68k_cpu; } -#define DEFINE_M68K_CPU_TYPE(cpu_model, initfn) \ - { \ - .name = M68K_CPU_TYPE_NAME(cpu_model), \ - .instance_init = initfn, \ - .parent = TYPE_M68K_CPU, \ +static void m68k_cpu_class_init_cf_core(ObjectClass *c, void *data) +{ + CPUClass *cc = CPU_CLASS(c); + + cc->gdb_core_xml_file = "cf-core.xml"; +} + +#define DEFINE_M68K_CPU_TYPE_CF(model) \ + { \ + .name = M68K_CPU_TYPE_NAME(#model), \ + .instance_init = model##_cpu_initfn, \ + .parent = TYPE_M68K_CPU, \ + .class_init = m68k_cpu_class_init_cf_core \ + } + +static void m68k_cpu_class_init_m68k_core(ObjectClass *c, void *data) +{ + CPUClass *cc = CPU_CLASS(c); + + cc->gdb_core_xml_file = "m68k-core.xml"; +} + +#define DEFINE_M68K_CPU_TYPE_M68K(model) \ + { \ + .name = M68K_CPU_TYPE_NAME(#model), \ + .instance_init = model##_cpu_initfn, \ + .parent = TYPE_M68K_CPU, \ + .class_init = m68k_cpu_class_init_m68k_core \ } static const TypeInfo m68k_cpus_type_infos[] = { @@ -314,15 +336,15 @@ static const TypeInfo m68k_cpus_type_infos[] = { .class_size = sizeof(M68kCPUClass), .class_init = m68k_cpu_class_init, }, - DEFINE_M68K_CPU_TYPE("m68000", m68000_cpu_initfn), - DEFINE_M68K_CPU_TYPE("m68020", m68020_cpu_initfn), - DEFINE_M68K_CPU_TYPE("m68030", m68030_cpu_initfn), - DEFINE_M68K_CPU_TYPE("m68040", m68040_cpu_initfn), - DEFINE_M68K_CPU_TYPE("m68060", m68060_cpu_initfn), - DEFINE_M68K_CPU_TYPE("m5206", m5206_cpu_initfn), - DEFINE_M68K_CPU_TYPE("m5208", m5208_cpu_initfn), - DEFINE_M68K_CPU_TYPE("cfv4e", cfv4e_cpu_initfn), - DEFINE_M68K_CPU_TYPE("any", any_cpu_initfn), + DEFINE_M68K_CPU_TYPE_M68K(m68000), + DEFINE_M68K_CPU_TYPE_M68K(m68020), + DEFINE_M68K_CPU_TYPE_M68K(m68030), + DEFINE_M68K_CPU_TYPE_M68K(m68040), + DEFINE_M68K_CPU_TYPE_M68K(m68060), + DEFINE_M68K_CPU_TYPE_CF(m5206), + DEFINE_M68K_CPU_TYPE_CF(m5208), + DEFINE_M68K_CPU_TYPE_CF(cfv4e), + DEFINE_M68K_CPU_TYPE_CF(any), }; DEFINE_TYPES(m68k_cpus_type_infos) diff --git a/target/m68k/helper.c b/target/m68k/helper.c index cad4083895..79b0b10ea9 100644 --- a/target/m68k/helper.c +++ b/target/m68k/helper.c @@ -72,7 +72,8 @@ static int cf_fpu_gdb_get_reg(CPUM68KState *env, GByteArray *mem_buf, int n) { if (n < 8) { float_status s; - return gdb_get_reg64(mem_buf, floatx80_to_float64(env->fregs[n].d, &s)); + return gdb_get_float64(mem_buf, + floatx80_to_float64(env->fregs[n].d, &s)); } switch (n) { case 8: /* fpcontrol */ diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c index eb362dd9ae..5c11c88b2a 100644 --- a/target/ppc/gdbstub.c +++ b/target/ppc/gdbstub.c @@ -130,7 +130,7 @@ int ppc_cpu_gdb_read_register(CPUState *cs, GByteArray *buf, int n) gdb_get_regl(buf, env->gpr[n]); } else if (n < 64) { /* fprs */ - gdb_get_reg64(buf, *cpu_fpr_ptr(env, n - 32)); + gdb_get_float64(buf, *cpu_fpr_ptr(env, n - 32)); } else { switch (n) { case 64: @@ -184,7 +184,7 @@ int ppc_cpu_gdb_read_register_apple(CPUState *cs, GByteArray *buf, int n) gdb_get_reg64(buf, env->gpr[n]); } else if (n < 64) { /* fprs */ - gdb_get_reg64(buf, *cpu_fpr_ptr(env, n - 32)); + gdb_get_float64(buf, *cpu_fpr_ptr(env, n - 32)); } else if (n < 96) { /* Altivec */ gdb_get_reg64(buf, n - 64); diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c index fd763e588e..2b6e832c4c 100644 --- a/target/ppc/translate_init.inc.c +++ b/target/ppc/translate_init.inc.c @@ -9881,7 +9881,7 @@ static int gdb_get_float_reg(CPUPPCState *env, GByteArray *buf, int n) { uint8_t *mem_buf; if (n < 32) { - gdb_get_reg64(buf, *cpu_fpr_ptr(env, n)); + gdb_get_float64(buf, *cpu_fpr_ptr(env, n)); mem_buf = gdb_get_reg_ptr(buf, 8); ppc_maybe_bswap_register(env, mem_buf, 8); return 8; diff --git a/tests/guest-debug/run-test.py b/tests/guest-debug/run-test.py index 8c49ee2f22..d9af9573b9 100755 --- a/tests/guest-debug/run-test.py +++ b/tests/guest-debug/run-test.py @@ -15,6 +15,8 @@ import argparse import subprocess import shutil import shlex +import os +from tempfile import TemporaryDirectory def get_args(): parser = argparse.ArgumentParser(description="A gdbstub test runner") @@ -41,17 +43,41 @@ if __name__ == '__main__': print("We need gdb to run the test") exit(-1) + socket_dir = TemporaryDirectory("qemu-gdbstub") + socket_name = os.path.join(socket_dir.name, "gdbstub.socket") + # Launch QEMU with binary if "system" in args.qemu: cmd = "%s %s %s -s -S" % (args.qemu, args.qargs, args.binary) else: - cmd = "%s %s -g 1234 %s" % (args.qemu, args.qargs, args.binary) + cmd = "%s %s -g %s %s" % (args.qemu, args.qargs, socket_name, + args.binary) inferior = subprocess.Popen(shlex.split(cmd)) # Now launch gdb with our test and collect the result - gdb_cmd = "%s %s -ex 'target remote localhost:1234' -x %s" % (args.gdb, args.binary, args.test) + gdb_cmd = "%s %s" % (args.gdb, args.binary) + # run quietly and ignore .gdbinit + gdb_cmd += " -q -n -batch" + # disable prompts in case of crash + gdb_cmd += " -ex 'set confirm off'" + # connect to remote + if "system" in args.qemu: + gdb_cmd += " -ex 'target remote localhost:1234'" + else: + gdb_cmd += " -ex 'target remote %s'" % (socket_name) + # finally the test script itself + gdb_cmd += " -x %s" % (args.test) + + print("GDB CMD: %s" % (gdb_cmd)) result = subprocess.call(gdb_cmd, shell=True); + # A negative result is the result of an internal gdb failure like + # a crash. We force a return of 0 so we don't fail the test on + # account of broken external tools. + if result < 0: + print("GDB crashed? SKIPPING") + exit(0) + exit(result) diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target index d99b2a9ece..312f36cde5 100644 --- a/tests/tcg/aarch64/Makefile.target +++ b/tests/tcg/aarch64/Makefile.target @@ -54,9 +54,6 @@ sve-ioctls: CFLAGS+=-march=armv8.1-a+sve ifneq ($(HAVE_GDB_BIN),) GDB_SCRIPT=$(SRC_PATH)/tests/guest-debug/run-test.py -AARCH64_TESTS += gdbstub-sysregs gdbstub-sve-ioctls - -.PHONY: gdbstub-sysregs gdbstub-sve-ioctls run-gdbstub-sysregs: sysregs $(call run-test, $@, $(GDB_SCRIPT) \ --gdb $(HAVE_GDB_BIN) \ @@ -70,6 +67,8 @@ run-gdbstub-sve-ioctls: sve-ioctls --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \ --bin $< --test $(AARCH64_SRC)/gdbstub/test-sve-ioctl.py, \ "basic gdbstub SVE ZLEN support") + +EXTRA_RUNS += run-gdbstub-sysregs run-gdbstub-sve-ioctls endif endif diff --git a/tests/tcg/aarch64/gdbstub/test-sve-ioctl.py b/tests/tcg/aarch64/gdbstub/test-sve-ioctl.py index 984fbeb277..972cf73c31 100644 --- a/tests/tcg/aarch64/gdbstub/test-sve-ioctl.py +++ b/tests/tcg/aarch64/gdbstub/test-sve-ioctl.py @@ -58,9 +58,6 @@ def run_test(): # try: inferior = gdb.selected_inferior() - if inferior.was_attached == False: - print("SKIPPING (failed to attach)", file=sys.stderr) - exit(0) arch = inferior.architecture() report(arch.name() == "aarch64", "connected to aarch64") except (gdb.error, AttributeError): @@ -70,7 +67,6 @@ except (gdb.error, AttributeError): try: # These are not very useful in scripts gdb.execute("set pagination off") - gdb.execute("set confirm off") # Run the actual tests run_test() diff --git a/tests/tcg/aarch64/gdbstub/test-sve.py b/tests/tcg/aarch64/gdbstub/test-sve.py index dbe7f2aa93..b96bdbb99a 100644 --- a/tests/tcg/aarch64/gdbstub/test-sve.py +++ b/tests/tcg/aarch64/gdbstub/test-sve.py @@ -59,9 +59,6 @@ def run_test(): # try: inferior = gdb.selected_inferior() - if inferior.was_attached == False: - print("SKIPPING (failed to attach)", file=sys.stderr) - exit(0) arch = inferior.architecture() report(arch.name() == "aarch64", "connected to aarch64") except (gdb.error, AttributeError): @@ -71,7 +68,6 @@ except (gdb.error, AttributeError): try: # These are not very useful in scripts gdb.execute("set pagination off") - gdb.execute("set confirm off") # Run the actual tests run_test() diff --git a/tests/tcg/cris/Makefile.target b/tests/tcg/cris/Makefile.target index 24c7f2e761..e72d3cbdb2 100644 --- a/tests/tcg/cris/Makefile.target +++ b/tests/tcg/cris/Makefile.target @@ -23,6 +23,7 @@ CRIS_RUNS = $(patsubst %, run-%, $(CRIS_USABLE_TESTS)) # override the list of tests, as we can't build the multiarch tests TESTS = $(CRIS_USABLE_TESTS) +EXTRA_RUNS = VPATH = $(CRIS_SRC) AS = $(CC) -x assembler-with-cpp diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target index 035b09c853..51fb75ecfd 100644 --- a/tests/tcg/multiarch/Makefile.target +++ b/tests/tcg/multiarch/Makefile.target @@ -42,5 +42,19 @@ run-test-mmap-%: test-mmap $(call run-test, test-mmap-$*, $(QEMU) -p $* $<,\ "$< ($* byte pages) on $(TARGET_NAME)") +ifneq ($(HAVE_GDB_BIN),) +GDB_SCRIPT=$(SRC_PATH)/tests/guest-debug/run-test.py + +run-gdbstub-sha1: sha1 + $(call run-test, $@, $(GDB_SCRIPT) \ + --gdb $(HAVE_GDB_BIN) \ + --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \ + --bin $< --test $(MULTIARCH_SRC)/gdbstub/sha1.py, \ + "basic gdbstub support") + +EXTRA_RUNS += run-gdbstub-sha1 +endif + + # Update TESTS TESTS += $(MULTIARCH_TESTS) diff --git a/tests/tcg/multiarch/gdbstub/sha1.py b/tests/tcg/multiarch/gdbstub/sha1.py new file mode 100644 index 0000000000..734553b98b --- /dev/null +++ b/tests/tcg/multiarch/gdbstub/sha1.py @@ -0,0 +1,81 @@ +from __future__ import print_function +# +# A very simple smoke test for debugging the SHA1 userspace test on +# each target. +# +# This is launched via tests/guest-debug/run-test.py +# + +import gdb +import sys + +initial_vlen = 0 +failcount = 0 + +def report(cond, msg): + "Report success/fail of test" + if cond: + print("PASS: %s" % (msg)) + else: + print("FAIL: %s" % (msg)) + global failcount + failcount += 1 + +def check_break(sym_name): + "Setup breakpoint, continue and check we stopped." + sym, ok = gdb.lookup_symbol(sym_name) + bp = gdb.Breakpoint(sym_name) + + gdb.execute("c") + + # hopefully we came back + end_pc = gdb.parse_and_eval('$pc') + report(bp.hit_count == 1, + "break @ %s (%s %d hits)" % (end_pc, sym.value(), bp.hit_count)) + + bp.delete() + +def run_test(): + "Run through the tests one by one" + + check_break("SHA1Init") + + # check step and inspect values + gdb.execute("next") + val_ctx = gdb.parse_and_eval("context->state[0]") + exp_ctx = 0x67452301 + report(int(val_ctx) == exp_ctx, "context->state[0] == %x" % exp_ctx); + + gdb.execute("next") + val_ctx = gdb.parse_and_eval("context->state[1]") + exp_ctx = 0xEFCDAB89 + report(int(val_ctx) == exp_ctx, "context->state[1] == %x" % exp_ctx); + + # finally check we don't barf inspecting registers + gdb.execute("info registers") + +# +# This runs as the script it sourced (via -x, via run-test.py) +# +try: + inferior = gdb.selected_inferior() + arch = inferior.architecture() + print("ATTACHED: %s" % arch.name()) +except (gdb.error, AttributeError): + print("SKIPPING (not connected)", file=sys.stderr) + exit(0) + +try: + # These are not very useful in scripts + gdb.execute("set pagination off") + gdb.execute("set confirm off") + + # Run the actual tests + run_test() +except (gdb.error): + print ("GDB Exception: %s" % (sys.exc_info()[0])) + failcount += 1 + pass + +print("All tests complete: %d failures" % failcount) +exit(failcount)