diff options
author | Rob Savoye <rob@senecass.com> | 2020-07-06 13:52:34 -0600 |
---|---|---|
committer | Rob Savoye <rob@senecass.com> | 2020-07-06 13:52:34 -0600 |
commit | 60e555675a9990270be8c4d63d3b4b8f484f3f51 (patch) | |
tree | 4e98eff0088454f9b67a8a77201de86d753cc924 | |
parent | 155ad7ac7f606f43613bb457ea36cc466d113613 (diff) |
Add board support file for QEMU for bare metal testing.
-rw-r--r-- | baseboards/qemu.exp | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/baseboards/qemu.exp b/baseboards/qemu.exp new file mode 100644 index 0000000..b699805 --- /dev/null +++ b/baseboards/qemu.exp @@ -0,0 +1,274 @@ +# +# Copyright (C) 2020 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# DejaGnu 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 DejaGnu; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + +# Load the generic configuration for this board. This will define a basic +# set of routines used to communicate with the board. +# load_generic_config "sim" +load_generic_config "gdbserver" +#load_lib gdbserver-support.exp + + +set qemu "" +set spec "" + +proc gdb_start {} { + puts "TRACE: gdb_start" + default_gdb_start + + return 0 +} + +# No multilib flags needed by default. +process_multilib_options "" + +set_board_info compiler [find_gcc] + +# When testing GCC in tree, the libgloss linker scripts files aren't +# usually in a known location, so we have to find them in the sysroot. +# FIXME: this may change in the near future, but for now it works. +set compiler "[find_gcc]" +set ret [local_exec "$compiler --print-sysroot" "" "" $timeout] +if { [lindex $ret 0] == 0 } { + set sysroot "[lindex $ret 1]" + # Strip the CR or LF off the end of the line as returned by GCC + regsub -all "\[\n\r\]+" $sysroot "" sysroot +} +# set library path environment variable for qemu +set env(QEMU_LD_PREFIX) $sysroot + +# In the beginning, only linker scripts were used to produce a fully +# linked executable. Then a better solution of having GCC spec file +# "patches" worked much better. None of the ARM/AARCH64 target +# use linker scripts, some targets support both, some just the +# linker script. +set ldscripts [ glob -nocomplain $sysroot/usr/lib/*.ld ] +if { [string length $ldscripts] == 0 } { + warning "No linker scripts found." +} +set specfiles [ glob -nocomplain $sysroot/usr/lib/*.specs ] +if { [string length $specfiles] == 0 } { + warning "No spec files found." +} else { + # FIXME: For now, both ldscripts and specfiles are ignored, and a + # single value is used tor testing. + foreach spec $specfiles { + verbose "Found spec file $spec" + } +} + +# The basic set of flags needed to build "hello world" for this +# board. This board uses libgloss and newlib. +case "$target_triplet" in { + { "armeb-*-eabi*" } { + set qemu "qemu-armeb" + set spec "elf-rdimon.specs" + } + { "arm-pi3-*" } { + set qemu "qemu-arm" + set spec="-static" + set target_list pi + } + { "arm*-*-eabi*" } { + set qemu "qemu-arm" + set spec "elf-rdimon.specs" + } + { "aarch64be-*-elf" } { + set qemu "qemu-aarch64_be" + set spec "rdimon.specs" + } + { "aarch64*-*elf*" } { + # There's multiple spec files, but rdimon is the + # one usually used for testing. + set qemu "qemu-aarch64" + set spec "rdimon.specs" + set target_list qemu + } + # FIXME: These following qemu variants are just what QEMU + # support, the pattern to match for the target needs to be + # researched. + { "cris*" } { + set qemu "qemu-cris" + } + { "microblaze-*" } { + set qemu "qemu-microblaze" + set spec "elf-gloss-linux.specs" + } + { "microblazeel-*" } { + set qemu "qemu-microblazeel" + set spec "elf-gloss-linux.specs" + } + { "mips" } { + set qemu "qemu-mips" + } + { "mips64-*" } { + set qemu "qemu-mips64" + } + { "mips64el-*" } { + set qemu "qemu-mips64el" + } + { "mipsel-*" } { + set qemu "qemu-mipsel" + } + { "mipsn32-*" } { + set qemu "qemu-mipsn32" + } + { "mipsn32el-*" } { + set qemu "qemu-mipsn32el" + } + { "ppc-*" } { + set qemu "qemu-ppc" + } + { "ppc64-*" } { + set qemu "qemu-ppc64" + } + { "ppc64abi32-*" } { + set qemu "qemu-ppc64abi32" + } + { "ppc64le-*" } { + set qemu "qemu-ppc64le" + } + { "riscv32-elf" } { + set qemu "qemu-riscv32" + } + { "riscv64-elf" } { + set qemu "qemu-riscv64" + set spec "nano.spec" + } + { "sh4-*" } { + set qemu "qemu-sh4" + } + { "sh4eb-*" } { + set qemu "qemu-sh4eb" + } + { "sparc=*" } { + set qemu "qemu-sparc" + } + { "sparc32plus-*" } { + set qemu "qemu-sparc32plus" + } + { "sparc64-*" } { + set qemu "qemu-sparc64" + } + default { + puts "No target hardware for $target_triplet" + } +} + +set port "2345" +# QEMU uses the standard renmote debugging protocol as used by gdbserver. +set_board_info gdb_protocol "remote" +# localhost is the default host used for the remote debugging protocol +set_board_info gdb,sockethost "localhost" +# 2345 is the default port used for the remote debugging protocol +set_board_info gdb,socketport $port +set_board_info target_sim_options "-g $port" +set_board_info gdb_server_prog $qemu +set_board_info specfile $spec +set_board_info needs_status_wrapper 1 +set_board_info protocol standard +push_config target qemu + +# This gdbserver can only run a process once per session. +set_board_info gdb,do_reload_on_run 1 +set_board_info exit_is_reliable 1 + +# Set this if the board does not support passing arguments to the +# inferior process. +set_board_info noargs 0 + +set_board_info cflags "[libgloss_include_flags]" +set_board_info ldflags "[libgloss_link_flags] [newlib_link_flags] -specs=$spec -static" + +proc qemu_load { dest prog args } { + global qemu + global timeout + set ret [local_exec "$qemu $prog" "" "" $timeout] + + if { [array size ret] == 0 } { + return "pass" + } else { + return "fail" + } +} + +# +# Start QEMU with the executable +# +proc qemu_download { dest prog args } { + global qemu + global timeout + puts "TRACE: qemu_download $dest $prog $args" + # qemu is already running with our executable. +} + +proc qemu_exec { dest prog args } { + global qemu + global timeout + puts "TRACE: qemu_exec $dest $prog $args" + + # gdb_target_cmd "remote" "" + +} + +# +# Load executable into GDB +# +proc gdb_load { args } { + global gdb_prompt + global verbose + global GDB + global user_spawn_id + global qemu + puts "TRACE: gdb_load $args" + + # qemu implements the gdbserver protocol. + spawn -nottyinit -noecho $qemu -g 2345 $args + # disconnect + + if { $args != "" } { + if [gdb_file_cmd $args] then { return -1 } + } + + # Only the remote protocol is used with the QEMU's gdbserver support + set ret [gdb_target_cmd "remote" ":2345"] + # set ret [gdb_target_cmd $protocol ""] + puts $ret + + send_gdb "load\n" + gdb_expect 2400 { + -re ".*$gdb_prompt $" { + if $verbose>1 then { + send_user "Loaded $args into $GDB\n" + } + close $spawn_id + return 0 + } + -re "$gdb_prompt $" { + if $verbose>1 then { + perror "GDB couldn't load." + } + } + timeout { + if $verbose>1 then { + perror "Timed out trying to load $args." + } + } + } + + close $spawn_id + return -1 +} |