Testing, gdbstub and semihosting patches:
- clean-ups to docker images - drop duplicate jobs from shippable - prettier tag generation (+gtags) - generate browsable source tree - more Travis->GitLab migrations - fix checkpatch to deal with commits - gate gdbstub tests on 8.3.1, expand tests - support Xfer:auxv:read gdb packet - better gdbstub cleanup - use GDB's SVE register layout - make arm-compat-semihosting common - add riscv semihosting support - add HEAPINFO, ELAPSED, TICKFREQ, TMPNAM and ISERROR to semihosting -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmAFXkcACgkQ+9DbCVqe KkSP7Af/YNU4dWFf/N9CwvKQTSoJmBrO77HXccOJyYDS62hA8eoh83HWNll+xMV7 GxJDwQs0GS8J3oqcq1DktGgTUkCNxUfbHROjI2YXfRzoWnl0PFHY+Z/qRsq+bRhX C3CiNCS/nM/NW2Q+H6TAD1MnXkia11+hqFhXrBRKVDON83MSvm0AspS5RO5eVpxo TUTOD1YND+tAPWi5xAN+NyDuvfoY3tG4S4/DFUrHQfpS7uaHY/4qe8gMmJczveeo uzJln9M7+pV5cgUWwr1fgCkbSyGgra+KX3GNoLIGS34C88cKRXAp7ZF19A3wQpiy LXljmOinLfKuJqeRGwcnt6f8GrTn7A== =XR0h -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-and-misc-180121-2' into staging Testing, gdbstub and semihosting patches: - clean-ups to docker images - drop duplicate jobs from shippable - prettier tag generation (+gtags) - generate browsable source tree - more Travis->GitLab migrations - fix checkpatch to deal with commits - gate gdbstub tests on 8.3.1, expand tests - support Xfer:auxv:read gdb packet - better gdbstub cleanup - use GDB's SVE register layout - make arm-compat-semihosting common - add riscv semihosting support - add HEAPINFO, ELAPSED, TICKFREQ, TMPNAM and ISERROR to semihosting # gpg: Signature made Mon 18 Jan 2021 10:09:11 GMT # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full] # Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44 * remotes/stsquad/tags/pull-testing-and-misc-180121-2: (30 commits) semihosting: Implement SYS_ISERROR semihosting: Implement SYS_TMPNAM semihosting: Implement SYS_ELAPSED and SYS_TICKFREQ riscv: Add semihosting support for user mode riscv: Add semihosting support semihosting: Support SYS_HEAPINFO when env->boot_info is not set semihosting: Change internal common-semi interfaces to use CPUState * semihosting: Change common-semi API to be architecture-independent semihosting: Move ARM semihosting code to shared directories target/arm: use official org.gnu.gdb.aarch64.sve layout for registers gdbstub: ensure we clean-up when terminated gdbstub: drop gdbserver_cleanup in favour of gdb_exit gdbstub: drop CPUEnv from gdb_exit() gdbstub: add support to Xfer:auxv:read: packet gdbstub: implement a softmmu based test Revert "tests/tcg/multiarch/Makefile.target: Disable run-gdbstub-sha1 test" configure: gate our use of GDB to 8.3.1 or above test/guest-debug: echo QEMU command as well scripts/checkpatch.pl: fix git-show invocation to include diffstat gitlab: migrate the minimal tools and unit tests from Travis ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org> # Conflicts: # default-configs/targets/riscv32-linux-user.mak # default-configs/targets/riscv64-linux-user.mak
This commit is contained in:
commit
8814b1327c
3
.gitignore
vendored
3
.gitignore
vendored
@ -7,6 +7,9 @@
|
||||
cscope.*
|
||||
tags
|
||||
TAGS
|
||||
GPATH
|
||||
GRTAGS
|
||||
GTAGS
|
||||
*~
|
||||
*.ast_raw
|
||||
*.depend_raw
|
||||
|
@ -79,7 +79,6 @@ build-system-ubuntu:
|
||||
TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu
|
||||
moxie-softmmu microblazeel-softmmu mips64el-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
CONFIGURE_ARGS: --enable-docs
|
||||
artifacts:
|
||||
expire_in: 2 days
|
||||
paths:
|
||||
@ -111,7 +110,6 @@ build-system-debian:
|
||||
TARGETS: arm-softmmu avr-softmmu i386-softmmu mipsel-softmmu
|
||||
riscv64-softmmu sh4eb-softmmu sparc-softmmu xtensaeb-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
CONFIGURE_ARGS: --enable-docs
|
||||
artifacts:
|
||||
expire_in: 2 days
|
||||
paths:
|
||||
@ -126,6 +124,19 @@ check-system-debian:
|
||||
IMAGE: debian-amd64
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
# No targets are built here, just tools, docs, and unit tests. This
|
||||
# also feeds into the eventual documentation deployment steps later
|
||||
build-tools-and-docs-debian:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-amd64
|
||||
MAKE_CHECK_ARGS: check-unit check-softfloat ctags TAGS cscope
|
||||
CONFIGURE_ARGS: --disable-system --disable-user --enable-docs --enable-tools
|
||||
artifacts:
|
||||
expire_in: 2 days
|
||||
paths:
|
||||
- build
|
||||
|
||||
acceptance-system-debian:
|
||||
<<: *native_test_job_definition
|
||||
needs:
|
||||
@ -596,14 +607,21 @@ build-libvhost-user:
|
||||
- meson
|
||||
- ninja
|
||||
|
||||
# Prepare for GitLab pages deployment. Anything copied into the
|
||||
# "public" directory will be deployed to $USER.gitlab.io/$PROJECT
|
||||
pages:
|
||||
image: $CI_REGISTRY_IMAGE/qemu/ubuntu2004:latest
|
||||
image: $CI_REGISTRY_IMAGE/qemu/debian-amd64:latest
|
||||
stage: test
|
||||
needs:
|
||||
- job: build-system-ubuntu
|
||||
artifacts: true
|
||||
- job: build-tools-and-docs-debian
|
||||
script:
|
||||
- mkdir public
|
||||
- mkdir -p public
|
||||
# HTML-ised source tree
|
||||
- make gtags
|
||||
- htags -anT --tree-view=filetree -m qemu_init
|
||||
-t "Welcome to the QEMU sourcecode"
|
||||
- mv HTML public/src
|
||||
# Project documentation
|
||||
- mv build/docs/index.html public/
|
||||
- for i in devel interop specs system tools user ; do mv build/docs/$i public/ ; done
|
||||
artifacts:
|
||||
|
@ -7,20 +7,8 @@ env:
|
||||
matrix:
|
||||
- IMAGE=debian-amd64
|
||||
TARGET_LIST=x86_64-softmmu,x86_64-linux-user
|
||||
- IMAGE=debian-armel-cross
|
||||
TARGET_LIST=arm-softmmu,arm-linux-user,armeb-linux-user
|
||||
- IMAGE=debian-armhf-cross
|
||||
TARGET_LIST=arm-softmmu,arm-linux-user,armeb-linux-user
|
||||
- IMAGE=debian-arm64-cross
|
||||
TARGET_LIST=aarch64-softmmu,aarch64-linux-user
|
||||
- IMAGE=debian-s390x-cross
|
||||
TARGET_LIST=s390x-softmmu,s390x-linux-user
|
||||
- IMAGE=debian-mips-cross
|
||||
TARGET_LIST=mips-softmmu,mipsel-linux-user
|
||||
- IMAGE=debian-mips64el-cross
|
||||
TARGET_LIST=mips64el-softmmu,mips64el-linux-user
|
||||
- IMAGE=debian-ppc64el-cross
|
||||
TARGET_LIST=ppc64-softmmu,ppc64-linux-user,ppc64abi32-linux-user
|
||||
TARGET_LIST=mips-softmmu
|
||||
build:
|
||||
pre_ci_boot:
|
||||
image_name: registry.gitlab.com/qemu-project/qemu/qemu/${IMAGE}
|
||||
|
25
.travis.yml
25
.travis.yml
@ -119,15 +119,6 @@ after_script:
|
||||
|
||||
jobs:
|
||||
include:
|
||||
# Just build tools and run minimal unit and softfloat checks
|
||||
- name: "GCC check-unit and check-softfloat"
|
||||
env:
|
||||
- BASE_CONFIG="--enable-tools"
|
||||
- CONFIG="--disable-user --disable-system"
|
||||
- TEST_CMD="make check-unit check-softfloat -j${JOBS}"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
||||
|
||||
|
||||
# --enable-debug implies --enable-debug-tcg, also runs quite a bit slower
|
||||
- name: "GCC debug (main-softmmu)"
|
||||
env:
|
||||
@ -148,22 +139,6 @@ jobs:
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
||||
|
||||
|
||||
# Check we can build docs and tools (out of tree)
|
||||
- name: "tools and docs (bionic)"
|
||||
dist: bionic
|
||||
env:
|
||||
- BUILD_DIR="out-of-tree/build/dir" SRC_DIR="../../.."
|
||||
- BASE_CONFIG="--enable-tools --enable-docs"
|
||||
- CONFIG="--target-list=x86_64-softmmu,aarch64-linux-user"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- ninja-build
|
||||
- python3-sphinx
|
||||
- perl
|
||||
|
||||
|
||||
# Test with Clang for compile portability (Travis uses clang-5.0)
|
||||
- name: "Clang (user)"
|
||||
env:
|
||||
|
@ -2322,6 +2322,7 @@ R: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
S: Maintained
|
||||
F: gdbstub*
|
||||
F: gdb-xml/
|
||||
F: tests/tcg/multiarch/gdbstub/
|
||||
|
||||
Memory API
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
@ -2736,6 +2737,7 @@ Yank feature
|
||||
M: Lukas Straub <lukasstraub2@web.de>
|
||||
S: Odd fixes
|
||||
F: util/yank.c
|
||||
F: stubs/yank.c
|
||||
F: include/qemu/yank.h
|
||||
F: qapi/yank.json
|
||||
|
||||
|
46
Makefile
46
Makefile
@ -250,19 +250,49 @@ find-src-path = find "$(SRC_PATH)/" -path "$(SRC_PATH)/meson" -prune -o \( -name
|
||||
|
||||
.PHONY: ctags
|
||||
ctags:
|
||||
rm -f "$(SRC_PATH)/"tags
|
||||
$(find-src-path) -exec ctags -f "$(SRC_PATH)/"tags --append {} +
|
||||
$(call quiet-command, \
|
||||
rm -f "$(SRC_PATH)/"tags, \
|
||||
"CTAGS", "Remove old tags")
|
||||
$(call quiet-command, \
|
||||
$(find-src-path) -exec ctags \
|
||||
-f "$(SRC_PATH)/"tags --append {} +, \
|
||||
"CTAGS", "Re-index $(SRC_PATH)")
|
||||
|
||||
.PHONY: gtags
|
||||
gtags:
|
||||
$(call quiet-command, \
|
||||
rm -f "$(SRC_PATH)/"GTAGS; \
|
||||
rm -f "$(SRC_PATH)/"GRTAGS; \
|
||||
rm -f "$(SRC_PATH)/"GPATH, \
|
||||
"GTAGS", "Remove old $@ files")
|
||||
$(call quiet-command, \
|
||||
(cd $(SRC_PATH) && \
|
||||
$(find-src-path) | gtags -f -), \
|
||||
"GTAGS", "Re-index $(SRC_PATH)")
|
||||
|
||||
.PHONY: TAGS
|
||||
TAGS:
|
||||
rm -f "$(SRC_PATH)/"TAGS
|
||||
$(find-src-path) -exec etags -f "$(SRC_PATH)/"TAGS --append {} +
|
||||
$(call quiet-command, \
|
||||
rm -f "$(SRC_PATH)/"TAGS, \
|
||||
"TAGS", "Remove old $@")
|
||||
$(call quiet-command, \
|
||||
$(find-src-path) -exec etags \
|
||||
-f "$(SRC_PATH)/"TAGS --append {} +, \
|
||||
"TAGS", "Re-index $(SRC_PATH)")
|
||||
|
||||
.PHONY: cscope
|
||||
cscope:
|
||||
rm -f "$(SRC_PATH)"/cscope.*
|
||||
$(find-src-path) -print | sed -e 's,^\./,,' > "$(SRC_PATH)/cscope.files"
|
||||
cscope -b -i"$(SRC_PATH)/cscope.files" -f"$(SRC_PATH)"/cscope.out
|
||||
$(call quiet-command, \
|
||||
rm -f "$(SRC_PATH)/"cscope.* , \
|
||||
"cscope", "Remove old $@ files")
|
||||
$(call quiet-command, \
|
||||
($(find-src-path) -print | sed -e 's,^\./,,' \
|
||||
> "$(SRC_PATH)/cscope.files"), \
|
||||
"cscope", "Create file list")
|
||||
$(call quiet-command, \
|
||||
cscope -b -i"$(SRC_PATH)/cscope.files" \
|
||||
-f"$(SRC_PATH)"/cscope.out, \
|
||||
"cscope", "Re-index $(SRC_PATH)")
|
||||
|
||||
# Needed by "meson install"
|
||||
export DESTDIR
|
||||
@ -279,7 +309,7 @@ help:
|
||||
$(call print-help,all,Build all)
|
||||
$(call print-help,dir/file.o,Build specified target only)
|
||||
$(call print-help,install,Install QEMU, documentation and tools)
|
||||
$(call print-help,ctags/TAGS,Generate tags file for editors)
|
||||
$(call print-help,ctags/gtags/TAGS,Generate tags file for editors)
|
||||
$(call print-help,cscope,Generate cscope index)
|
||||
$(call print-help,sparse,Run sparse on the QEMU source)
|
||||
@echo ''
|
||||
|
@ -333,7 +333,7 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
#ifdef CONFIG_GPROF
|
||||
_mcleanup();
|
||||
#endif
|
||||
gdb_exit(cpu_env, arg1);
|
||||
gdb_exit(arg1);
|
||||
qemu_plugin_atexit_cb();
|
||||
/* XXX: should free thread stack and CPU env */
|
||||
_exit(arg1);
|
||||
@ -435,7 +435,7 @@ abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
#ifdef CONFIG_GPROF
|
||||
_mcleanup();
|
||||
#endif
|
||||
gdb_exit(cpu_env, arg1);
|
||||
gdb_exit(arg1);
|
||||
qemu_plugin_atexit_cb();
|
||||
/* XXX: should free thread stack and CPU env */
|
||||
_exit(arg1);
|
||||
@ -514,7 +514,7 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
#ifdef CONFIG_GPROF
|
||||
_mcleanup();
|
||||
#endif
|
||||
gdb_exit(cpu_env, arg1);
|
||||
gdb_exit(arg1);
|
||||
qemu_plugin_atexit_cb();
|
||||
/* XXX: should free thread stack and CPU env */
|
||||
_exit(arg1);
|
||||
|
7
configure
vendored
7
configure
vendored
@ -6166,8 +6166,11 @@ if test "$plugins" = "yes" ; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$gdb_bin" ; then
|
||||
echo "HAVE_GDB_BIN=$gdb_bin" >> $config_host_mak
|
||||
if test -n "$gdb_bin"; then
|
||||
gdb_version=$($gdb_bin --version | head -n 1)
|
||||
if version_ge ${gdb_version##* } 8.3.1; then
|
||||
echo "HAVE_GDB_BIN=$gdb_bin" >> $config_host_mak
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$secret_keyring" = "yes" ; then
|
||||
|
@ -42,4 +42,5 @@ CONFIG_FSL_IMX25=y
|
||||
CONFIG_FSL_IMX7=y
|
||||
CONFIG_FSL_IMX6UL=y
|
||||
CONFIG_SEMIHOSTING=y
|
||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||
CONFIG_ALLWINNER_H3=y
|
||||
|
@ -3,6 +3,8 @@
|
||||
# Uncomment the following lines to disable these optional devices:
|
||||
#
|
||||
#CONFIG_PCI_DEVICES=n
|
||||
CONFIG_SEMIHOSTING=y
|
||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||
|
||||
# Boards:
|
||||
#
|
||||
|
@ -3,6 +3,8 @@
|
||||
# Uncomment the following lines to disable these optional devices:
|
||||
#
|
||||
#CONFIG_PCI_DEVICES=n
|
||||
CONFIG_SEMIHOSTING=y
|
||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||
|
||||
# Boards:
|
||||
#
|
||||
|
@ -2,3 +2,4 @@ TARGET_ARCH=aarch64
|
||||
TARGET_BASE_ARCH=arm
|
||||
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
|
||||
TARGET_HAS_BFLT=y
|
||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||
|
@ -3,3 +3,4 @@ TARGET_BASE_ARCH=arm
|
||||
TARGET_WORDS_BIGENDIAN=y
|
||||
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
|
||||
TARGET_HAS_BFLT=y
|
||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||
|
@ -3,3 +3,4 @@ TARGET_SYSTBL_ABI=common,oabi
|
||||
TARGET_SYSTBL=syscall.tbl
|
||||
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
|
||||
TARGET_HAS_BFLT=y
|
||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||
|
@ -4,3 +4,4 @@ TARGET_SYSTBL=syscall.tbl
|
||||
TARGET_WORDS_BIGENDIAN=y
|
||||
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
|
||||
TARGET_HAS_BFLT=y
|
||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||
|
@ -2,3 +2,4 @@ TARGET_ARCH=riscv32
|
||||
TARGET_BASE_ARCH=riscv
|
||||
TARGET_ABI_DIR=riscv
|
||||
TARGET_XML_FILES= gdb-xml/riscv-32bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-32bit-virtual.xml
|
||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||
|
@ -2,3 +2,4 @@ TARGET_ARCH=riscv64
|
||||
TARGET_BASE_ARCH=riscv
|
||||
TARGET_ABI_DIR=riscv
|
||||
TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml
|
||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||
|
65
gdbstub.c
65
gdbstub.c
@ -1978,6 +1978,7 @@ static void handle_v_kill(GdbCmdContext *gdb_ctx, void *user_ctx)
|
||||
/* Kill the target */
|
||||
put_packet("OK");
|
||||
error_report("QEMU: Terminated via GDBstub");
|
||||
gdb_exit(0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@ -2172,6 +2173,12 @@ static void handle_query_supported(GdbCmdContext *gdb_ctx, void *user_ctx)
|
||||
";ReverseStep+;ReverseContinue+");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
if (gdbserver_state.c_cpu->opaque) {
|
||||
g_string_append(gdbserver_state.str_buf, ";qXfer:auxv:read+");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (gdb_ctx->num_params &&
|
||||
strstr(gdb_ctx->params[0].data, "multiprocess+")) {
|
||||
gdbserver_state.multiprocess = true;
|
||||
@ -2233,6 +2240,46 @@ static void handle_query_xfer_features(GdbCmdContext *gdb_ctx, void *user_ctx)
|
||||
gdbserver_state.str_buf->len, true);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USER_ONLY) && defined(CONFIG_LINUX_USER)
|
||||
static void handle_query_xfer_auxv(GdbCmdContext *gdb_ctx, void *user_ctx)
|
||||
{
|
||||
TaskState *ts;
|
||||
unsigned long offset, len, saved_auxv, auxv_len;
|
||||
const char *mem;
|
||||
|
||||
if (gdb_ctx->num_params < 2) {
|
||||
put_packet("E22");
|
||||
return;
|
||||
}
|
||||
|
||||
offset = gdb_ctx->params[0].val_ul;
|
||||
len = gdb_ctx->params[1].val_ul;
|
||||
ts = gdbserver_state.c_cpu->opaque;
|
||||
saved_auxv = ts->info->saved_auxv;
|
||||
auxv_len = ts->info->auxv_len;
|
||||
mem = (const char *)(saved_auxv + offset);
|
||||
if (offset > auxv_len) {
|
||||
put_packet("E00");
|
||||
return;
|
||||
}
|
||||
|
||||
if (len > (MAX_PACKET_LENGTH - 5) / 2) {
|
||||
len = (MAX_PACKET_LENGTH - 5) / 2;
|
||||
}
|
||||
|
||||
if (len < auxv_len - offset) {
|
||||
g_string_assign(gdbserver_state.str_buf, "m");
|
||||
memtox(gdbserver_state.str_buf, mem, len);
|
||||
} else {
|
||||
g_string_assign(gdbserver_state.str_buf, "l");
|
||||
memtox(gdbserver_state.str_buf, mem, auxv_len - offset);
|
||||
}
|
||||
|
||||
put_packet_binary(gdbserver_state.str_buf->str,
|
||||
gdbserver_state.str_buf->len, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void handle_query_attached(GdbCmdContext *gdb_ctx, void *user_ctx)
|
||||
{
|
||||
put_packet(GDB_ATTACHED);
|
||||
@ -2338,6 +2385,14 @@ static GdbCmdParseEntry gdb_gen_query_table[] = {
|
||||
.cmd_startswith = 1,
|
||||
.schema = "s:l,l0"
|
||||
},
|
||||
#if defined(CONFIG_USER_ONLY) && defined(CONFIG_LINUX_USER)
|
||||
{
|
||||
.handler = handle_query_xfer_auxv,
|
||||
.cmd = "Xfer:auxv:read::",
|
||||
.cmd_startswith = 1,
|
||||
.schema = "l,l0"
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.handler = handle_query_attached,
|
||||
.cmd = "Attached:",
|
||||
@ -2485,6 +2540,7 @@ static int gdb_handle_packet(const char *line_buf)
|
||||
case 'k':
|
||||
/* Kill the target */
|
||||
error_report("QEMU: Terminated via GDBstub");
|
||||
gdb_exit(0);
|
||||
exit(0);
|
||||
case 'D':
|
||||
{
|
||||
@ -3014,7 +3070,7 @@ static void gdb_read_byte(uint8_t ch)
|
||||
}
|
||||
|
||||
/* Tell the remote gdb that the process has exited. */
|
||||
void gdb_exit(CPUArchState *env, int code)
|
||||
void gdb_exit(int code)
|
||||
{
|
||||
char buf[4];
|
||||
|
||||
@ -3493,13 +3549,6 @@ int gdbserver_start(const char *device)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gdbserver_cleanup(void)
|
||||
{
|
||||
if (gdbserver_state.init) {
|
||||
put_packet("W00");
|
||||
}
|
||||
}
|
||||
|
||||
static void register_types(void)
|
||||
{
|
||||
type_register_static(&char_gdb_type_info);
|
||||
|
@ -1,3 +1,7 @@
|
||||
|
||||
config SEMIHOSTING
|
||||
bool
|
||||
|
||||
config ARM_COMPATIBLE_SEMIHOSTING
|
||||
bool
|
||||
select SEMIHOSTING
|
||||
|
File diff suppressed because it is too large
Load Diff
39
hw/semihosting/common-semi.h
Normal file
39
hw/semihosting/common-semi.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Semihosting support for systems modeled on the Arm "Angel"
|
||||
* semihosting syscalls design. This includes Arm and RISC-V processors
|
||||
*
|
||||
* Copyright (c) 2005, 2007 CodeSourcery.
|
||||
* Copyright (c) 2019 Linaro
|
||||
* Written by Paul Brook.
|
||||
*
|
||||
* Copyright © 2020 by Keith Packard <keithp@keithp.com>
|
||||
* Adapted for systems other than ARM, including RISC-V, by Keith Packard
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* ARM Semihosting is documented in:
|
||||
* Semihosting for AArch32 and AArch64 Release 2.0
|
||||
* https://static.docs.arm.com/100863/0200/semihosting.pdf
|
||||
*
|
||||
* RISC-V Semihosting is documented in:
|
||||
* RISC-V Semihosting
|
||||
* https://github.com/riscv/riscv-semihosting-spec/blob/main/riscv-semihosting-spec.adoc
|
||||
*/
|
||||
|
||||
#ifndef COMMON_SEMI_H
|
||||
#define COMMON_SEMI_H
|
||||
|
||||
target_ulong do_common_semihosting(CPUState *cs);
|
||||
|
||||
#endif /* COMMON_SEMI_H */
|
@ -2,3 +2,6 @@ specific_ss.add(when: 'CONFIG_SEMIHOSTING', if_true: files(
|
||||
'config.c',
|
||||
'console.c',
|
||||
))
|
||||
|
||||
specific_ss.add(when: ['CONFIG_ARM_COMPATIBLE_SEMIHOSTING'],
|
||||
if_true: files('arm-compat-semi.c'))
|
||||
|
@ -46,7 +46,17 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...);
|
||||
void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va);
|
||||
int use_gdb_syscalls(void);
|
||||
void gdb_set_stop_cpu(CPUState *cpu);
|
||||
void gdb_exit(CPUArchState *, int);
|
||||
|
||||
/**
|
||||
* gdb_exit: exit gdb session, reporting inferior status
|
||||
* @code: exit code reported
|
||||
*
|
||||
* This closes the session and sends a final packet to GDB reporting
|
||||
* the exit status of the program. It also cleans up any connections
|
||||
* detritus before returning.
|
||||
*/
|
||||
void gdb_exit(int code);
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
/**
|
||||
* gdb_handlesig: yield control to gdb
|
||||
@ -187,8 +197,6 @@ static inline uint8_t * gdb_get_reg_ptr(GByteArray *buf, int len)
|
||||
*/
|
||||
int gdbserver_start(const char *port_or_device);
|
||||
|
||||
void gdbserver_cleanup(void);
|
||||
|
||||
/**
|
||||
* gdb_has_xml:
|
||||
* This is an ugly hack to cope with both new and old gdb.
|
||||
|
@ -808,6 +808,8 @@ static inline int64_t get_clock_realtime(void)
|
||||
return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000);
|
||||
}
|
||||
|
||||
extern int64_t clock_start;
|
||||
|
||||
/* Warning: don't insert tracepoints into these functions, they are
|
||||
also used by simpletrace backend and tracepoints would cause
|
||||
an infinite recursion! */
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "qemu.h"
|
||||
#include "cpu_loop-common.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "hw/semihosting/common-semi.h"
|
||||
|
||||
#define get_user_code_u32(x, gaddr, env) \
|
||||
({ abi_long __r = get_user_u32((x), (gaddr)); \
|
||||
@ -129,7 +130,7 @@ void cpu_loop(CPUARMState *env)
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
break;
|
||||
case EXCP_SEMIHOST:
|
||||
env->xregs[0] = do_arm_semihosting(env);
|
||||
env->xregs[0] = do_common_semihosting(cs);
|
||||
env->pc += 4;
|
||||
break;
|
||||
case EXCP_YIELD:
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "qemu.h"
|
||||
#include "elf.h"
|
||||
#include "cpu_loop-common.h"
|
||||
#include "hw/semihosting/common-semi.h"
|
||||
|
||||
#define get_user_code_u32(x, gaddr, env) \
|
||||
({ abi_long __r = get_user_u32((x), (gaddr)); \
|
||||
@ -421,7 +422,7 @@ void cpu_loop(CPUARMState *env)
|
||||
}
|
||||
break;
|
||||
case EXCP_SEMIHOST:
|
||||
env->regs[0] = do_arm_semihosting(env);
|
||||
env->regs[0] = do_common_semihosting(cs);
|
||||
env->regs[15] += env->thumb ? 2 : 4;
|
||||
break;
|
||||
case EXCP_INTERRUPT:
|
||||
|
@ -1,6 +1,3 @@
|
||||
linux_user_ss.add(when: 'TARGET_AARCH64', if_true: files('semihost.c'))
|
||||
linux_user_ss.add(when: 'TARGET_ARM', if_true: files('semihost.c'))
|
||||
|
||||
subdir('nwfpe')
|
||||
|
||||
syscall_nr_generators += {
|
||||
|
@ -34,6 +34,6 @@ void preexit_cleanup(CPUArchState *env, int code)
|
||||
#ifdef CONFIG_GCOV
|
||||
__gcov_dump();
|
||||
#endif
|
||||
gdb_exit(env, code);
|
||||
gdb_exit(code);
|
||||
qemu_plugin_atexit_cb();
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ linux_user_ss.add(rt)
|
||||
|
||||
linux_user_ss.add(when: 'TARGET_HAS_BFLT', if_true: files('flatload.c'))
|
||||
linux_user_ss.add(when: 'TARGET_I386', if_true: files('vm86.c'))
|
||||
linux_user_ss.add(when: 'CONFIG_ARM_COMPATIBLE_SEMIHOSTING', if_true: files('semihost.c'))
|
||||
|
||||
|
||||
syscall_nr_generators = {}
|
||||
|
@ -109,6 +109,8 @@ typedef struct TaskState {
|
||||
/* FPA state */
|
||||
FPA11 fpa;
|
||||
# endif
|
||||
#endif
|
||||
#if defined(TARGET_ARM) || defined(TARGET_RISCV)
|
||||
int swi_errno;
|
||||
#endif
|
||||
#if defined(TARGET_I386) && !defined(TARGET_X86_64)
|
||||
@ -122,7 +124,7 @@ typedef struct TaskState {
|
||||
#ifdef TARGET_M68K
|
||||
abi_ulong tp_value;
|
||||
#endif
|
||||
#if defined(TARGET_ARM) || defined(TARGET_M68K)
|
||||
#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_RISCV)
|
||||
/* Extra fields for semihosted binaries. */
|
||||
abi_ulong heap_base;
|
||||
abi_ulong heap_limit;
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "qemu.h"
|
||||
#include "cpu_loop-common.h"
|
||||
#include "elf.h"
|
||||
#include "hw/semihosting/common-semi.h"
|
||||
|
||||
void cpu_loop(CPURISCVState *env)
|
||||
{
|
||||
@ -91,6 +92,10 @@ void cpu_loop(CPURISCVState *env)
|
||||
sigcode = TARGET_SEGV_MAPERR;
|
||||
sigaddr = env->badaddr;
|
||||
break;
|
||||
case RISCV_EXCP_SEMIHOST:
|
||||
env->gpr[xA0] = do_common_semihosting(cs);
|
||||
env->pc += 4;
|
||||
break;
|
||||
case EXCP_DEBUG:
|
||||
gdbstep:
|
||||
signum = TARGET_SIGTRAP;
|
||||
|
@ -1,11 +1,11 @@
|
||||
/*
|
||||
* ARM Semihosting Console Support
|
||||
* ARM Compatible Semihosting Console Support.
|
||||
*
|
||||
* Copyright (c) 2019 Linaro Ltd
|
||||
*
|
||||
* Currently ARM is unique in having support for semihosting support
|
||||
* in linux-user. So for now we implement the common console API but
|
||||
* just for arm linux-user.
|
||||
* Currently ARM and RISC-V are unique in having support for
|
||||
* semihosting support in linux-user. So for now we implement the
|
||||
* common console API but just for arm and risc-v linux-user.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
@ -4207,10 +4207,10 @@ ERST
|
||||
DEF("semihosting", 0, QEMU_OPTION_semihosting,
|
||||
"-semihosting semihosting mode\n",
|
||||
QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32 |
|
||||
QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2)
|
||||
QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV)
|
||||
SRST
|
||||
``-semihosting``
|
||||
Enable semihosting mode (ARM, M68K, Xtensa, MIPS, Nios II only).
|
||||
Enable semihosting mode (ARM, M68K, Xtensa, MIPS, Nios II, RISC-V only).
|
||||
|
||||
Note that this allows guest direct access to the host filesystem, so
|
||||
should only be used with a trusted guest OS.
|
||||
@ -4222,10 +4222,10 @@ DEF("semihosting-config", HAS_ARG, QEMU_OPTION_semihosting_config,
|
||||
"-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,arg=str[,...]]\n" \
|
||||
" semihosting configuration\n",
|
||||
QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32 |
|
||||
QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2)
|
||||
QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV)
|
||||
SRST
|
||||
``-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,arg=str[,...]]``
|
||||
Enable and configure semihosting (ARM, M68K, Xtensa, MIPS, Nios II
|
||||
Enable and configure semihosting (ARM, M68K, Xtensa, MIPS, Nios II, RISC-V
|
||||
only).
|
||||
|
||||
Note that this allows guest direct access to the host filesystem, so
|
||||
@ -4240,6 +4240,8 @@ SRST
|
||||
open/read/write/seek/select. Tensilica baremetal libc for ISS and
|
||||
linux platform "sim" use this interface.
|
||||
|
||||
On RISC-V this implements the standard semihosting API, version 0.2.
|
||||
|
||||
``target=native|gdb|auto``
|
||||
Defines where the semihosting calls will be addressed, to QEMU
|
||||
(``native``) or to GDB (``gdb``). The default is ``auto``, which
|
||||
|
@ -399,7 +399,7 @@ if ($chk_branch) {
|
||||
my $num_patches = @patches;
|
||||
for my $hash (@patches) {
|
||||
my $FILE;
|
||||
open($FILE, '-|', "git", "show", $hash) ||
|
||||
open($FILE, '-|', "git", "show", "--patch-with-stat", $hash) ||
|
||||
die "$P: git show $hash - $!\n";
|
||||
while (<$FILE>) {
|
||||
chomp;
|
||||
|
@ -775,7 +775,7 @@ void qemu_init_subsystems(void)
|
||||
|
||||
void qemu_cleanup(void)
|
||||
{
|
||||
gdbserver_cleanup();
|
||||
gdb_exit(0);
|
||||
|
||||
/*
|
||||
* cleaning up the migration object cancels any existing migration
|
||||
|
@ -47,6 +47,7 @@ stub_ss.add(files('vm-stop.c'))
|
||||
stub_ss.add(files('win32-kbd-hook.c'))
|
||||
stub_ss.add(files('cpu-synchronize-state.c'))
|
||||
if have_block
|
||||
stub_ss.add(files('yank.c'))
|
||||
stub_ss.add(files('replay-tools.c'))
|
||||
endif
|
||||
if have_system
|
||||
|
29
stubs/yank.c
Normal file
29
stubs/yank.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/yank.h"
|
||||
|
||||
bool yank_register_instance(const YankInstance *instance, Error **errp)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void yank_unregister_instance(const YankInstance *instance)
|
||||
{
|
||||
}
|
||||
|
||||
void yank_register_function(const YankInstance *instance,
|
||||
YankFn *func,
|
||||
void *opaque)
|
||||
{
|
||||
}
|
||||
|
||||
void yank_unregister_function(const YankInstance *instance,
|
||||
YankFn *func,
|
||||
void *opaque)
|
||||
{
|
||||
}
|
||||
|
||||
void yank_generic_iochannel(void *opaque)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1068,14 +1068,6 @@ static inline void aarch64_sve_change_el(CPUARMState *env, int o,
|
||||
static inline void aarch64_add_sve_properties(Object *obj) { }
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_TCG)
|
||||
static inline target_ulong do_arm_semihosting(CPUARMState *env)
|
||||
{
|
||||
g_assert_not_reached();
|
||||
}
|
||||
#else
|
||||
target_ulong do_arm_semihosting(CPUARMState *env);
|
||||
#endif
|
||||
void aarch64_sync_32_to_64(CPUARMState *env);
|
||||
void aarch64_sync_64_to_32(CPUARMState *env);
|
||||
|
||||
|
@ -195,22 +195,17 @@ static const struct TypeSize vec_lanes[] = {
|
||||
{ "uint128", 128, 'q', 'u' },
|
||||
{ "int128", 128, 'q', 's' },
|
||||
/* 64 bit */
|
||||
{ "ieee_double", 64, 'd', 'f' },
|
||||
{ "uint64", 64, 'd', 'u' },
|
||||
{ "int64", 64, 'd', 's' },
|
||||
{ "ieee_double", 64, 'd', 'f' },
|
||||
/* 32 bit */
|
||||
{ "ieee_single", 32, 's', 'f' },
|
||||
{ "uint32", 32, 's', 'u' },
|
||||
{ "int32", 32, 's', 's' },
|
||||
{ "ieee_single", 32, 's', 'f' },
|
||||
/* 16 bit */
|
||||
{ "ieee_half", 16, 'h', 'f' },
|
||||
{ "uint16", 16, 'h', 'u' },
|
||||
{ "int16", 16, 'h', 's' },
|
||||
/*
|
||||
* TODO: currently there is no reliable way of telling
|
||||
* if the remote gdb actually understands ieee_half so
|
||||
* we don't expose it in the target description for now.
|
||||
* { "ieee_half", 16, 'h', 'f' },
|
||||
*/
|
||||
/* bytes */
|
||||
{ "uint8", 8, 'b', 'u' },
|
||||
{ "int8", 8, 'b', 's' },
|
||||
@ -223,17 +218,16 @@ int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg)
|
||||
GString *s = g_string_new(NULL);
|
||||
DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml;
|
||||
g_autoptr(GString) ts = g_string_new("");
|
||||
int i, bits, reg_width = (cpu->sve_max_vq * 128);
|
||||
int i, j, bits, reg_width = (cpu->sve_max_vq * 128);
|
||||
info->num = 0;
|
||||
g_string_printf(s, "<?xml version=\"1.0\"?>");
|
||||
g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
|
||||
g_string_append_printf(s, "<feature name=\"org.qemu.gdb.aarch64.sve\">");
|
||||
g_string_append_printf(s, "<feature name=\"org.gnu.gdb.aarch64.sve\">");
|
||||
|
||||
/* First define types and totals in a whole VL */
|
||||
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
|
||||
int count = reg_width / vec_lanes[i].size;
|
||||
g_string_printf(ts, "vq%d%c%c", count,
|
||||
vec_lanes[i].sz, vec_lanes[i].suffix);
|
||||
g_string_printf(ts, "svev%c%c", vec_lanes[i].sz, vec_lanes[i].suffix);
|
||||
g_string_append_printf(s,
|
||||
"<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
|
||||
ts->str, vec_lanes[i].gdb_type, count);
|
||||
@ -243,39 +237,37 @@ int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg)
|
||||
* signed and potentially float versions of each size from 128 to
|
||||
* 8 bits.
|
||||
*/
|
||||
for (bits = 128; bits >= 8; bits /= 2) {
|
||||
int count = reg_width / bits;
|
||||
g_string_append_printf(s, "<union id=\"vq%dn\">", count);
|
||||
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
|
||||
if (vec_lanes[i].size == bits) {
|
||||
g_string_append_printf(s, "<field name=\"%c\" type=\"vq%d%c%c\"/>",
|
||||
vec_lanes[i].suffix,
|
||||
count,
|
||||
vec_lanes[i].sz, vec_lanes[i].suffix);
|
||||
for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
|
||||
const char suf[] = { 'q', 'd', 's', 'h', 'b' };
|
||||
g_string_append_printf(s, "<union id=\"svevn%c\">", suf[i]);
|
||||
for (j = 0; j < ARRAY_SIZE(vec_lanes); j++) {
|
||||
if (vec_lanes[j].size == bits) {
|
||||
g_string_append_printf(s, "<field name=\"%c\" type=\"svev%c%c\"/>",
|
||||
vec_lanes[j].suffix,
|
||||
vec_lanes[j].sz, vec_lanes[j].suffix);
|
||||
}
|
||||
}
|
||||
g_string_append(s, "</union>");
|
||||
}
|
||||
/* And now the final union of unions */
|
||||
g_string_append(s, "<union id=\"vq\">");
|
||||
for (bits = 128; bits >= 8; bits /= 2) {
|
||||
int count = reg_width / bits;
|
||||
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
|
||||
if (vec_lanes[i].size == bits) {
|
||||
g_string_append_printf(s, "<field name=\"%c\" type=\"vq%dn\"/>",
|
||||
vec_lanes[i].sz, count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_string_append(s, "<union id=\"svev\">");
|
||||
for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
|
||||
const char suf[] = { 'q', 'd', 's', 'h', 'b' };
|
||||
g_string_append_printf(s, "<field name=\"%c\" type=\"svevn%c\"/>",
|
||||
suf[i], suf[i]);
|
||||
}
|
||||
g_string_append(s, "</union>");
|
||||
|
||||
/* Finally the sve prefix type */
|
||||
g_string_append_printf(s,
|
||||
"<vector id=\"svep\" type=\"uint8\" count=\"%d\"/>",
|
||||
reg_width / 8);
|
||||
|
||||
/* Then define each register in parts for each vq */
|
||||
for (i = 0; i < 32; i++) {
|
||||
g_string_append_printf(s,
|
||||
"<reg name=\"z%d\" bitsize=\"%d\""
|
||||
" regnum=\"%d\" group=\"vector\""
|
||||
" type=\"vq\"/>",
|
||||
" regnum=\"%d\" type=\"svev\"/>",
|
||||
i, reg_width, base_reg++);
|
||||
info->num++;
|
||||
}
|
||||
@ -287,31 +279,22 @@ int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg)
|
||||
" regnum=\"%d\" group=\"float\""
|
||||
" type=\"int\"/>", base_reg++);
|
||||
info->num += 2;
|
||||
/*
|
||||
* Predicate registers aren't so big they are worth splitting up
|
||||
* but we do need to define a type to hold the array of quad
|
||||
* references.
|
||||
*/
|
||||
g_string_append_printf(s,
|
||||
"<vector id=\"vqp\" type=\"uint16\" count=\"%d\"/>",
|
||||
cpu->sve_max_vq);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
g_string_append_printf(s,
|
||||
"<reg name=\"p%d\" bitsize=\"%d\""
|
||||
" regnum=\"%d\" group=\"vector\""
|
||||
" type=\"vqp\"/>",
|
||||
" regnum=\"%d\" type=\"svep\"/>",
|
||||
i, cpu->sve_max_vq * 16, base_reg++);
|
||||
info->num++;
|
||||
}
|
||||
g_string_append_printf(s,
|
||||
"<reg name=\"ffr\" bitsize=\"%d\""
|
||||
" regnum=\"%d\" group=\"vector\""
|
||||
" type=\"vqp\"/>",
|
||||
" type=\"svep\"/>",
|
||||
cpu->sve_max_vq * 16, base_reg++);
|
||||
g_string_append_printf(s,
|
||||
"<reg name=\"vg\" bitsize=\"64\""
|
||||
" regnum=\"%d\" group=\"vector\""
|
||||
" type=\"uint32\"/>",
|
||||
" regnum=\"%d\" type=\"int\"/>",
|
||||
base_reg++);
|
||||
info->num += 2;
|
||||
g_string_append_printf(s, "</feature>");
|
||||
|
@ -34,6 +34,7 @@
|
||||
#ifdef CONFIG_TCG
|
||||
#include "arm_ldst.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "hw/semihosting/common-semi.h"
|
||||
#endif
|
||||
|
||||
#define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
|
||||
@ -276,7 +277,7 @@ static int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, int reg)
|
||||
* while the ZCR works in Vector Quads (VQ) which is 128bit chunks.
|
||||
*/
|
||||
int vq = sve_zcr_len_for_el(env, arm_current_el(env)) + 1;
|
||||
return gdb_get_reg32(buf, vq * 2);
|
||||
return gdb_get_reg64(buf, vq * 2);
|
||||
}
|
||||
default:
|
||||
/* gdbstub asked for something out our range */
|
||||
@ -9875,13 +9876,13 @@ static void handle_semihosting(CPUState *cs)
|
||||
qemu_log_mask(CPU_LOG_INT,
|
||||
"...handling as semihosting call 0x%" PRIx64 "\n",
|
||||
env->xregs[0]);
|
||||
env->xregs[0] = do_arm_semihosting(env);
|
||||
env->xregs[0] = do_common_semihosting(cs);
|
||||
env->pc += 4;
|
||||
} else {
|
||||
qemu_log_mask(CPU_LOG_INT,
|
||||
"...handling as semihosting call 0x%x\n",
|
||||
env->regs[0]);
|
||||
env->regs[0] = do_arm_semihosting(env);
|
||||
env->regs[0] = do_common_semihosting(cs);
|
||||
env->regs[15] += env->thumb ? 2 : 4;
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
#ifdef CONFIG_TCG
|
||||
#include "arm_ldst.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "hw/semihosting/common-semi.h"
|
||||
#endif
|
||||
|
||||
static void v7m_msr_xpsr(CPUARMState *env, uint32_t mask,
|
||||
@ -2306,7 +2307,11 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
|
||||
qemu_log_mask(CPU_LOG_INT,
|
||||
"...handling as semihosting call 0x%x\n",
|
||||
env->regs[0]);
|
||||
env->regs[0] = do_arm_semihosting(env);
|
||||
#ifdef CONFIG_TCG
|
||||
env->regs[0] = do_common_semihosting(cs);
|
||||
#else
|
||||
g_assert_not_reached();
|
||||
#endif
|
||||
env->regs[15] += env->thumb ? 2 : 4;
|
||||
return;
|
||||
case EXCP_BKPT:
|
||||
|
@ -32,8 +32,6 @@ arm_ss.add(files(
|
||||
))
|
||||
arm_ss.add(zlib)
|
||||
|
||||
arm_ss.add(when: 'CONFIG_TCG', if_true: files('arm-semi.c'))
|
||||
|
||||
arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c'))
|
||||
|
||||
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
|
||||
|
@ -195,7 +195,7 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
|
||||
args = env->dregs[1];
|
||||
switch (nr) {
|
||||
case HOSTED_EXIT:
|
||||
gdb_exit(env, env->dregs[0]);
|
||||
gdb_exit(env->dregs[0]);
|
||||
exit(env->dregs[0]);
|
||||
case HOSTED_OPEN:
|
||||
GET_ARG(0);
|
||||
|
@ -215,7 +215,7 @@ void do_nios2_semihosting(CPUNios2State *env)
|
||||
args = env->regs[R_ARG1];
|
||||
switch (nr) {
|
||||
case HOSTED_EXIT:
|
||||
gdb_exit(env, env->regs[R_ARG0]);
|
||||
gdb_exit(env->regs[R_ARG0]);
|
||||
exit(env->regs[R_ARG0]);
|
||||
case HOSTED_OPEN:
|
||||
GET_ARG(0);
|
||||
|
@ -542,6 +542,7 @@
|
||||
#define RISCV_EXCP_INST_PAGE_FAULT 0xc /* since: priv-1.10.0 */
|
||||
#define RISCV_EXCP_LOAD_PAGE_FAULT 0xd /* since: priv-1.10.0 */
|
||||
#define RISCV_EXCP_STORE_PAGE_FAULT 0xf /* since: priv-1.10.0 */
|
||||
#define RISCV_EXCP_SEMIHOST 0x10
|
||||
#define RISCV_EXCP_INST_GUEST_PAGE_FAULT 0x14
|
||||
#define RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT 0x15
|
||||
#define RISCV_EXCP_VIRT_INSTRUCTION_FAULT 0x16
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "exec/exec-all.h"
|
||||
#include "tcg/tcg-op.h"
|
||||
#include "trace.h"
|
||||
#include "hw/semihosting/common-semi.h"
|
||||
|
||||
int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
|
||||
{
|
||||
@ -847,6 +848,15 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
||||
target_ulong htval = 0;
|
||||
target_ulong mtval2 = 0;
|
||||
|
||||
if (cause == RISCV_EXCP_SEMIHOST) {
|
||||
if (env->priv >= PRV_S) {
|
||||
env->gpr[xA0] = do_common_semihosting(cs);
|
||||
env->pc += 4;
|
||||
return;
|
||||
}
|
||||
cause = RISCV_EXCP_BREAKPOINT;
|
||||
}
|
||||
|
||||
if (!async) {
|
||||
/* set tval to badaddr for traps with address information */
|
||||
switch (cause) {
|
||||
|
@ -29,7 +29,42 @@ static bool trans_ecall(DisasContext *ctx, arg_ecall *a)
|
||||
|
||||
static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a)
|
||||
{
|
||||
generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
|
||||
target_ulong ebreak_addr = ctx->base.pc_next;
|
||||
target_ulong pre_addr = ebreak_addr - 4;
|
||||
target_ulong post_addr = ebreak_addr + 4;
|
||||
uint32_t pre = 0;
|
||||
uint32_t ebreak = 0;
|
||||
uint32_t post = 0;
|
||||
|
||||
/*
|
||||
* The RISC-V semihosting spec specifies the following
|
||||
* three-instruction sequence to flag a semihosting call:
|
||||
*
|
||||
* slli zero, zero, 0x1f 0x01f01013
|
||||
* ebreak 0x00100073
|
||||
* srai zero, zero, 0x7 0x40705013
|
||||
*
|
||||
* The two shift operations on the zero register are no-ops, used
|
||||
* here to signify a semihosting exception, rather than a breakpoint.
|
||||
*
|
||||
* Uncompressed instructions are required so that the sequence is easy
|
||||
* to validate.
|
||||
*
|
||||
* The three instructions are required to lie in the same page so
|
||||
* that no exception will be raised when fetching them.
|
||||
*/
|
||||
|
||||
if ((pre_addr & TARGET_PAGE_MASK) == (post_addr & TARGET_PAGE_MASK)) {
|
||||
pre = opcode_at(&ctx->base, pre_addr);
|
||||
ebreak = opcode_at(&ctx->base, ebreak_addr);
|
||||
post = opcode_at(&ctx->base, post_addr);
|
||||
}
|
||||
|
||||
if (pre == 0x01f01013 && ebreak == 0x00100073 && post == 0x40705013) {
|
||||
generate_exception(ctx, RISCV_EXCP_SEMIHOST);
|
||||
} else {
|
||||
generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
|
||||
}
|
||||
exit_tb(ctx); /* no chaining */
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
return true;
|
||||
|
@ -64,6 +64,7 @@ typedef struct DisasContext {
|
||||
uint16_t vlen;
|
||||
uint16_t mlen;
|
||||
bool vl_eq_vlmax;
|
||||
CPUState *cs;
|
||||
} DisasContext;
|
||||
|
||||
#ifdef TARGET_RISCV64
|
||||
@ -747,6 +748,15 @@ static bool gen_shift(DisasContext *ctx, arg_r *a,
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
|
||||
{
|
||||
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
||||
CPUState *cpu = ctx->cs;
|
||||
CPURISCVState *env = cpu->env_ptr;
|
||||
|
||||
return cpu_ldl_code(env, pc);
|
||||
}
|
||||
|
||||
/* Include insn module translation function */
|
||||
#include "insn_trans/trans_rvi.c.inc"
|
||||
#include "insn_trans/trans_rvm.c.inc"
|
||||
@ -814,6 +824,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|
||||
ctx->lmul = FIELD_EX32(tb_flags, TB_FLAGS, LMUL);
|
||||
ctx->mlen = 1 << (ctx->sew + 3 - ctx->lmul);
|
||||
ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
|
||||
ctx->cs = cs;
|
||||
}
|
||||
|
||||
static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)
|
||||
|
@ -108,7 +108,6 @@ ifneq ($(HOST_ARCH),x86_64)
|
||||
DOCKER_PARTIAL_IMAGES += debian-mips-cross debian-mipsel-cross debian-mips64el-cross
|
||||
DOCKER_PARTIAL_IMAGES += debian-ppc64el-cross
|
||||
DOCKER_PARTIAL_IMAGES += debian-s390x-cross
|
||||
DOCKER_PARTIAL_IMAGES += debian-win32-cross debian-win64-cross
|
||||
DOCKER_PARTIAL_IMAGES += fedora travis
|
||||
endif
|
||||
|
||||
|
@ -332,9 +332,9 @@ class Docker(object):
|
||||
(uname, uid, uname))
|
||||
|
||||
tmp_df.write("\n")
|
||||
tmp_df.write("LABEL com.qemu.dockerfile-checksum=%s" % (checksum))
|
||||
tmp_df.write("LABEL com.qemu.dockerfile-checksum=%s\n" % (checksum))
|
||||
for f, c in extra_files_cksum:
|
||||
tmp_df.write("LABEL com.qemu.%s-checksum=%s" % (f, c))
|
||||
tmp_df.write("LABEL com.qemu.%s-checksum=%s\n" % (f, c))
|
||||
|
||||
tmp_df.flush()
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Docker x86_64 target
|
||||
#
|
||||
# This docker target builds on the debian Stretch base image. Further
|
||||
# This docker target builds on the Debian Buster base image. Further
|
||||
# libraries which are not widely available are installed by hand.
|
||||
#
|
||||
FROM qemu/debian10
|
||||
@ -14,7 +14,10 @@ RUN apt update && \
|
||||
RUN apt update && \
|
||||
DEBIAN_FRONTEND=noninteractive eatmydata \
|
||||
apt install -y --no-install-recommends \
|
||||
cscope \
|
||||
genisoimage \
|
||||
exuberant-ctags \
|
||||
global \
|
||||
libbz2-dev \
|
||||
liblzo2-dev \
|
||||
libgcrypt20-dev \
|
||||
|
@ -16,6 +16,7 @@ import subprocess
|
||||
import shutil
|
||||
import shlex
|
||||
import os
|
||||
from time import sleep
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
def get_args():
|
||||
@ -27,10 +28,21 @@ def get_args():
|
||||
required=True)
|
||||
parser.add_argument("--test", help="GDB test script",
|
||||
required=True)
|
||||
parser.add_argument("--gdb", help="The gdb binary to use", default=None)
|
||||
parser.add_argument("--gdb", help="The gdb binary to use",
|
||||
default=None)
|
||||
parser.add_argument("--output", help="A file to redirect output to")
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def log(output, msg):
|
||||
if output:
|
||||
output.write(msg + "\n")
|
||||
output.flush()
|
||||
else:
|
||||
print(msg)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = get_args()
|
||||
|
||||
@ -42,17 +54,25 @@ if __name__ == '__main__':
|
||||
if not args.gdb:
|
||||
print("We need gdb to run the test")
|
||||
exit(-1)
|
||||
if args.output:
|
||||
output = open(args.output, "w")
|
||||
else:
|
||||
output = None
|
||||
|
||||
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)
|
||||
cmd = "%s %s %s -gdb unix:path=%s,server" % (args.qemu,
|
||||
args.qargs,
|
||||
args.binary,
|
||||
socket_name)
|
||||
else:
|
||||
cmd = "%s %s -g %s %s" % (args.qemu, args.qargs, socket_name,
|
||||
args.binary)
|
||||
|
||||
log(output, "QEMU CMD: %s" % (cmd))
|
||||
inferior = subprocess.Popen(shlex.split(cmd))
|
||||
|
||||
# Now launch gdb with our test and collect the result
|
||||
@ -62,16 +82,15 @@ if __name__ == '__main__':
|
||||
# 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)
|
||||
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);
|
||||
sleep(1)
|
||||
log(output, "GDB CMD: %s" % (gdb_cmd))
|
||||
|
||||
result = subprocess.call(gdb_cmd, shell=True, stdout=output)
|
||||
|
||||
# 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
|
||||
|
@ -15,6 +15,7 @@ CRT_PATH=$(AARCH64_SYSTEM_SRC)
|
||||
LINK_SCRIPT=$(AARCH64_SYSTEM_SRC)/kernel.ld
|
||||
LDFLAGS=-Wl,-T$(LINK_SCRIPT)
|
||||
TESTS+=$(AARCH64_TESTS) $(MULTIARCH_TESTS)
|
||||
EXTRA_RUNS+=$(MULTIARCH_RUNS)
|
||||
CFLAGS+=-nostdlib -ggdb -O0 $(MINILIB_INC)
|
||||
LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
|
||||
|
||||
|
@ -40,6 +40,17 @@ class TestBreakpoint(gdb.Breakpoint):
|
||||
except gdb.error:
|
||||
report(False, "checking zregs (out of range)")
|
||||
|
||||
# Check the aliased V registers are set and GDB has correctly
|
||||
# created them for us having recognised and handled SVE.
|
||||
try:
|
||||
for i in range(0, 16):
|
||||
val_z = gdb.parse_and_eval("$z0.b.u[%d]" % i)
|
||||
val_v = gdb.parse_and_eval("$v0.b.u[%d]" % i)
|
||||
report(int(val_z) == int(val_v),
|
||||
"v0.b.u[%d] == z0.b.u[%d]" % (i, i))
|
||||
except gdb.error:
|
||||
report(False, "checking vregs (out of range)")
|
||||
|
||||
|
||||
def run_test():
|
||||
"Run through the tests one by one"
|
||||
|
@ -197,6 +197,7 @@ __start:
|
||||
bl main
|
||||
|
||||
/* pass return value to sys exit */
|
||||
_exit:
|
||||
mov x1, x0
|
||||
ldr x0, =0x20026 /* ADP_Stopped_ApplicationExit */
|
||||
stp x0, x1, [sp, #-16]!
|
||||
|
@ -19,6 +19,7 @@ CFLAGS+=-nostdlib -ggdb -O0 $(MINILIB_INC)
|
||||
LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
|
||||
|
||||
TESTS+=$(MULTIARCH_TESTS)
|
||||
EXTRA_RUNS+=$(MULTIARCH_RUNS)
|
||||
|
||||
# building head blobs
|
||||
.PRECIOUS: $(CRT_OBJS)
|
||||
|
@ -76,7 +76,7 @@ _start:
|
||||
*/
|
||||
call main
|
||||
|
||||
/* output any non-zero result in eax to isa-debug-exit device */
|
||||
_exit: /* output any non-zero result in eax to isa-debug-exit device */
|
||||
test %al, %al
|
||||
jz 1f
|
||||
out %ax, $0xf4
|
||||
|
@ -54,9 +54,16 @@ run-gdbstub-sha1: sha1
|
||||
--bin $< --test $(MULTIARCH_SRC)/gdbstub/sha1.py, \
|
||||
"basic gdbstub support")
|
||||
|
||||
# Disable this for now -- it provokes a gdb internal-error on
|
||||
# Ubuntu gdb 8.1.1-0ubuntu1.
|
||||
# EXTRA_RUNS += run-gdbstub-sha1
|
||||
EXTRA_RUNS += run-gdbstub-sha1
|
||||
|
||||
run-gdbstub-qxfer-auxv-read: sha1
|
||||
$(call run-test, $@, $(GDB_SCRIPT) \
|
||||
--gdb $(HAVE_GDB_BIN) \
|
||||
--qemu $(QEMU) --qargs "$(QEMU_OPTS)" \
|
||||
--bin $< --test $(MULTIARCH_SRC)/gdbstub/test-qxfer-auxv-read.py, \
|
||||
"basic gdbstub qXfer:auxv:read support")
|
||||
|
||||
EXTRA_RUNS += run-gdbstub-sha1 run-gdbstub-qxfer-auxv-read
|
||||
endif
|
||||
|
||||
|
||||
|
130
tests/tcg/multiarch/gdbstub/memory.py
Normal file
130
tests/tcg/multiarch/gdbstub/memory.py
Normal file
@ -0,0 +1,130 @@
|
||||
from __future__ import print_function
|
||||
#
|
||||
# Test some of the softmmu debug features with the multiarch memory
|
||||
# test. It is a port of the original vmlinux focused test case but
|
||||
# using the "memory" test instead.
|
||||
#
|
||||
# This is launched via tests/guest-debug/run-test.py
|
||||
#
|
||||
|
||||
import gdb
|
||||
import sys
|
||||
|
||||
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_step():
|
||||
"Step an instruction, check it moved."
|
||||
start_pc = gdb.parse_and_eval('$pc')
|
||||
gdb.execute("si")
|
||||
end_pc = gdb.parse_and_eval('$pc')
|
||||
|
||||
return not (start_pc == end_pc)
|
||||
|
||||
|
||||
#
|
||||
# Currently it's hard to create a hbreak with the pure python API and
|
||||
# manually matching PC to symbol address is a bit flaky thanks to
|
||||
# function prologues. However internally QEMU's gdbstub treats them
|
||||
# the same as normal breakpoints so it will do for now.
|
||||
#
|
||||
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.BP_BREAKPOINT)
|
||||
|
||||
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 do_one_watch(sym, wtype, text):
|
||||
|
||||
wp = gdb.Breakpoint(sym, gdb.BP_WATCHPOINT, wtype)
|
||||
gdb.execute("c")
|
||||
report_str = "%s for %s" % (text, sym)
|
||||
|
||||
if wp.hit_count > 0:
|
||||
report(True, report_str)
|
||||
wp.delete()
|
||||
else:
|
||||
report(False, report_str)
|
||||
|
||||
|
||||
def check_watches(sym_name):
|
||||
"Watch a symbol for any access."
|
||||
|
||||
# Should hit for any read
|
||||
do_one_watch(sym_name, gdb.WP_ACCESS, "awatch")
|
||||
|
||||
# Again should hit for reads
|
||||
do_one_watch(sym_name, gdb.WP_READ, "rwatch")
|
||||
|
||||
# Finally when it is written
|
||||
do_one_watch(sym_name, gdb.WP_WRITE, "watch")
|
||||
|
||||
|
||||
def run_test():
|
||||
"Run through the tests one by one"
|
||||
|
||||
print("Checking we can step the first few instructions")
|
||||
step_ok = 0
|
||||
for i in range(3):
|
||||
if check_step():
|
||||
step_ok += 1
|
||||
|
||||
report(step_ok == 3, "single step in boot code")
|
||||
|
||||
# If we get here we have missed some of the other breakpoints.
|
||||
print("Setup catch-all for _exit")
|
||||
cbp = gdb.Breakpoint("_exit", gdb.BP_BREAKPOINT)
|
||||
|
||||
check_break("main")
|
||||
check_watches("test_data[128]")
|
||||
|
||||
report(cbp.hit_count == 0, "didn't reach backstop")
|
||||
|
||||
#
|
||||
# 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)
|
||||
|
||||
if gdb.parse_and_eval('$pc') == 0:
|
||||
print("SKIP: PC not set")
|
||||
exit(0)
|
||||
|
||||
try:
|
||||
# These are not very useful in scripts
|
||||
gdb.execute("set pagination off")
|
||||
|
||||
# Run the actual tests
|
||||
run_test()
|
||||
except (gdb.error):
|
||||
print("GDB Exception: %s" % (sys.exc_info()[0]))
|
||||
failcount += 1
|
||||
pass
|
||||
|
||||
# Finally kill the inferior and exit gdb with a count of failures
|
||||
gdb.execute("kill")
|
||||
exit(failcount)
|
57
tests/tcg/multiarch/gdbstub/test-qxfer-auxv-read.py
Normal file
57
tests/tcg/multiarch/gdbstub/test-qxfer-auxv-read.py
Normal file
@ -0,0 +1,57 @@
|
||||
from __future__ import print_function
|
||||
#
|
||||
# Test auxiliary vector is loaded via gdbstub
|
||||
#
|
||||
# This is launched via tests/guest-debug/run-test.py
|
||||
#
|
||||
|
||||
import gdb
|
||||
import sys
|
||||
|
||||
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 run_test():
|
||||
"Run through the tests one by one"
|
||||
|
||||
auxv = gdb.execute("info auxv", False, True)
|
||||
report(isinstance(auxv, str), "Fetched auxv from inferior")
|
||||
report(auxv.find("sha1"), "Found test binary name in auxv")
|
||||
|
||||
#
|
||||
# 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)
|
||||
|
||||
if gdb.parse_and_eval('$pc') == 0:
|
||||
print("SKIP: PC not set")
|
||||
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)
|
@ -7,8 +7,25 @@
|
||||
# complications of building.
|
||||
#
|
||||
|
||||
MULTIARCH_SYSTEM_SRC=$(SRC_PATH)/tests/tcg/multiarch/system
|
||||
MULTIARCH_SRC=$(SRC_PATH)/tests/tcg/multiarch
|
||||
MULTIARCH_SYSTEM_SRC=$(MULTIARCH_SRC)/system
|
||||
VPATH+=$(MULTIARCH_SYSTEM_SRC)
|
||||
|
||||
MULTIARCH_TEST_SRCS=$(wildcard $(MULTIARCH_SYSTEM_SRC)/*.c)
|
||||
MULTIARCH_TESTS = $(patsubst $(MULTIARCH_SYSTEM_SRC)/%.c, %, $(MULTIARCH_TEST_SRCS))
|
||||
|
||||
ifneq ($(HAVE_GDB_BIN),)
|
||||
GDB_SCRIPT=$(SRC_PATH)/tests/guest-debug/run-test.py
|
||||
|
||||
run-gdbstub-memory: memory
|
||||
$(call run-test, $@, $(GDB_SCRIPT) \
|
||||
--gdb $(HAVE_GDB_BIN) \
|
||||
--qemu $(QEMU) \
|
||||
--output $<.gdb.out \
|
||||
--qargs \
|
||||
"-monitor none -display none -chardev file$(COMMA)path=$<.out$(COMMA)id=output $(QEMU_OPTS)" \
|
||||
--bin $< --test $(MULTIARCH_SRC)/gdbstub/memory.py, \
|
||||
"softmmu gdbstub support")
|
||||
|
||||
MULTIARCH_RUNS += run-gdbstub-memory
|
||||
endif
|
||||
|
@ -19,6 +19,7 @@ CFLAGS+=-nostdlib -ggdb -O0 $(MINILIB_INC)
|
||||
LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
|
||||
|
||||
TESTS+=$(MULTIARCH_TESTS)
|
||||
EXTRA_RUNS+=$(MULTIARCH_RUNS)
|
||||
|
||||
# building head blobs
|
||||
.PRECIOUS: $(CRT_OBJS)
|
||||
|
@ -124,7 +124,7 @@ _start:
|
||||
/* don't worry about stack frame, assume everthing is garbage when we return */
|
||||
call main
|
||||
|
||||
/* output any non-zero result in eax to isa-debug-exit device */
|
||||
_exit: /* output any non-zero result in eax to isa-debug-exit device */
|
||||
test %al, %al
|
||||
jz 1f
|
||||
out %ax, $0xf4
|
||||
|
@ -27,6 +27,8 @@
|
||||
/***********************************************************/
|
||||
/* real time host monotonic timer */
|
||||
|
||||
int64_t clock_start;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
int64_t clock_freq;
|
||||
@ -41,6 +43,7 @@ static void __attribute__((constructor)) init_get_clock(void)
|
||||
exit(1);
|
||||
}
|
||||
clock_freq = freq.QuadPart;
|
||||
clock_start = get_clock();
|
||||
}
|
||||
|
||||
#else
|
||||
@ -55,5 +58,6 @@ static void __attribute__((constructor)) init_get_clock(void)
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
|
||||
use_rt_clock = 1;
|
||||
}
|
||||
clock_start = get_clock();
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user