mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 23:42:32 +00:00
0de54cddaa
This patch is a workaround for the missing implementation of 'Pd_session::transfer_quota' interface by the GDB monitor's PD service. The missing implementation becomes problematic with the changes of #3750 that enabled the cap-quota accounting for core's CPU service. In regular scenarios without the GDB monitor, the client of 'Cpu_session::create_thread' deals with Out_of_caps or Out_of_ram by upgrading the CPU session's cap and RAM quotas. This, in turn, results in a sequence of 'transfer_quota' operations at the parent. Since GDB monitor implements a custom PD service, these 'transfer_quota' calls try to transfer quota between sessions provided by core and those provided by the GDB monitor. This does of course not work. To fix this issue, the GDB monitor needs a major overhaul. This patch side-steps the problem by handing Out_of_caps and Out_of_ram from the debuging target.
309 lines
6.7 KiB
Tcl
309 lines
6.7 KiB
Tcl
#
|
|
# \brief Test for using the GDB monitor
|
|
# \author Christian Prochaska
|
|
# \author Norman Feske
|
|
# \date 2011-05-24
|
|
#
|
|
|
|
#
|
|
# Only the NOVA platform supports most of the tested features at this time.
|
|
#
|
|
|
|
if {![have_include "power_on/qemu"] ||
|
|
!([have_spec nova])} {
|
|
puts "Run script is only supported for NOVA in Qemu"; exit 0
|
|
}
|
|
|
|
#
|
|
# Build
|
|
#
|
|
|
|
set build_components {
|
|
core init timer
|
|
drivers/uart
|
|
app/gdb_monitor
|
|
test/gdb_monitor
|
|
}
|
|
|
|
lappend build_components "lib/gdbserver_platform-$::env(KERNEL)"
|
|
|
|
build $build_components
|
|
|
|
create_boot_directory
|
|
|
|
#
|
|
# Generate config
|
|
#
|
|
|
|
set config {
|
|
<config verbose="yes">
|
|
<parent-provides>
|
|
<service name="ROM"/>
|
|
<service name="IRQ"/>
|
|
<service name="IO_MEM"/>
|
|
<service name="IO_PORT"/>
|
|
<service name="PD"/>
|
|
<service name="RM"/>
|
|
<service name="CPU"/>
|
|
<service name="LOG"/>
|
|
</parent-provides>
|
|
<default-route>
|
|
<any-service> <parent/> <any-child/> </any-service>
|
|
</default-route>
|
|
<default caps="100"/>
|
|
<start name="timer">
|
|
<resource name="RAM" quantum="2M"/>
|
|
<provides> <service name="Timer"/> </provides>
|
|
</start>
|
|
<start name="pc_uart_drv">
|
|
<resource name="RAM" quantum="2M"/>
|
|
<provides>
|
|
<service name="Terminal"/>
|
|
<service name="Uart"/>
|
|
</provides>
|
|
<config>
|
|
<policy label_prefix="gdb_monitor" uart="1"/>
|
|
</config>
|
|
</start>
|
|
<start name="gdb_monitor" caps="200">
|
|
<resource name="RAM" quantum="9M"/>
|
|
<config>
|
|
<target name="test-gdb_monitor">
|
|
<config>
|
|
<vfs> <dir name="dev"> <log/> </dir> </vfs>
|
|
<libc stdout="/dev/log" stderr="/dev/log"/>
|
|
</config>
|
|
</target>
|
|
<preserve name="RAM" quantum="5M"/>
|
|
<vfs> <dir name="dev"> <log/> <terminal/> </dir> </vfs>
|
|
<libc stdout="/dev/log" stderr="/dev/log"/>
|
|
</config>
|
|
</start>
|
|
</config>
|
|
}
|
|
|
|
install_config $config
|
|
|
|
#
|
|
# Boot modules
|
|
#
|
|
|
|
# evaluated by the run tool
|
|
proc binary_name_gdbserver_platform_lib_so { } {
|
|
return "gdbserver_platform-$::env(KERNEL).lib.so"
|
|
}
|
|
|
|
# generic modules
|
|
set boot_modules {
|
|
core init timer
|
|
ld.lib.so libc.lib.so vfs.lib.so libm.lib.so libc_pipe.lib.so
|
|
pc_uart_drv posix.lib.so stdcxx.lib.so
|
|
gdb_monitor gdbserver_platform.lib.so test-gdb_monitor
|
|
}
|
|
|
|
build_boot_image $boot_modules
|
|
|
|
#
|
|
# Execute test case
|
|
#
|
|
#
|
|
set local_port 5555
|
|
|
|
# qemu config
|
|
append qemu_args " -display none "
|
|
|
|
# connect comport 0 to stdio
|
|
append qemu_args " -serial stdio "
|
|
|
|
# connect comport 1 with TCP port $local_port
|
|
append qemu_args " -serial chardev:uart "
|
|
append qemu_args " -chardev socket,id=uart,port=$local_port,host=localhost,server,nowait,ipv4 "
|
|
|
|
run_genode_until {.*\[init -> gdb_monitor\] Remote debugging using /dev/terminal.*} 30
|
|
set genode_id [output_spawn_id]
|
|
|
|
puts "GDB monitor is up, starting GDB"
|
|
|
|
source ${genode_dir}/repos/ports/run/gdb_monitor.inc
|
|
|
|
# GDB loads symbols from 'debug/ld.lib.so'
|
|
if { [have_spec nova] } {
|
|
exec ln -sf ld-nova.lib.so debug/ld.lib.so
|
|
}
|
|
|
|
set gdb_target_binary "test-gdb_monitor"
|
|
|
|
# sequence of GDB commands to execute at startup
|
|
set gdb_cmds ""
|
|
append gdb_cmds {-ex "target remote localhost:$local_port" }
|
|
append gdb_cmds [gdb_initial_breakpoint_cmds $gdb_target_binary]
|
|
|
|
# run GDB
|
|
eval spawn [gdb] debug/ld.lib.so -n $gdb_cmds
|
|
set gdb_id [list $spawn_id $genode_id]
|
|
|
|
puts ""
|
|
puts "----- test: breakpoint in 'main()' -----"
|
|
puts ""
|
|
|
|
run_genode_until {\(gdb\)} 60 $gdb_id
|
|
|
|
send "b main\n"
|
|
run_genode_until {\(gdb\)} 20 $gdb_id
|
|
send "c\n"
|
|
run_genode_until {\(gdb\)} 20 $gdb_id
|
|
|
|
if {![regexp {Breakpoint 2, main ()} $output]} {
|
|
puts stderr "*** Error: Breakpoint in main() did not trigger"
|
|
exit -1
|
|
}
|
|
|
|
send "delete 2\n"
|
|
run_genode_until {\(gdb\)} 20 $gdb_id
|
|
|
|
puts "\n"
|
|
puts "----- test: breakpoint in shared library -----"
|
|
puts ""
|
|
|
|
send "b puts\n"
|
|
run_genode_until {\(gdb\)} 20 $gdb_id
|
|
send "c\n"
|
|
run_genode_until {\(gdb\)} 20 $gdb_id
|
|
|
|
if {![regexp {Breakpoint 3, puts ()} $output]} {
|
|
puts "*** Error: Breakpoint in shared library did not trigger"
|
|
exit -1
|
|
}
|
|
|
|
puts "\n"
|
|
puts "----- test: stack trace when not in syscall -----"
|
|
puts ""
|
|
|
|
send "bt\n"
|
|
run_genode_until {\(gdb\)} 20 $gdb_id
|
|
|
|
if {![regexp {#0 puts} $output] ||
|
|
![regexp {in func2()} $output] ||
|
|
![regexp {in func1()} $output] ||
|
|
![regexp {in main ()} $output]} {
|
|
|
|
puts stderr "*** Error: Stack trace when not in syscall is not as expected"
|
|
exit -1
|
|
}
|
|
|
|
puts "\n"
|
|
puts "----- test: modification of a variable value -----"
|
|
puts ""
|
|
|
|
send "print test_var\n"
|
|
run_genode_until {\(gdb\)} 20 $gdb_id
|
|
|
|
if {![regexp {\$1 = 1} $output]} {
|
|
puts stderr "*** Error: first 'print test_var' command didn't result in the expected output"
|
|
exit -1
|
|
}
|
|
|
|
send "set var test_var=2\n"
|
|
run_genode_until {\(gdb\)} 20 $gdb_id
|
|
|
|
send "print test_var\n"
|
|
run_genode_until {\(gdb\)} 20 $gdb_id
|
|
|
|
if {![regexp {\$2 = 2} $output]} {
|
|
puts stderr "*** Error: second 'print test_var' command didn't result in the expected output"
|
|
exit -1
|
|
}
|
|
|
|
puts "\n"
|
|
puts "----- test: 'call' command -----"
|
|
puts ""
|
|
|
|
send "call test_var_func()\n"
|
|
run_genode_until {\(gdb\)} 60 $gdb_id
|
|
|
|
if {![regexp {\$3 = 3} $output]} {
|
|
puts stderr "*** Error: 'call' command didn't result in the expected output"
|
|
exit -1
|
|
}
|
|
|
|
puts "\n"
|
|
puts "----- test: thread info -----"
|
|
puts ""
|
|
|
|
send "b test_thread_start\n"
|
|
run_genode_until {\(gdb\)} 20 $gdb_id
|
|
|
|
send "c\n"
|
|
run_genode_until {\(gdb\)} 20 $gdb_id
|
|
|
|
if {![regexp {Breakpoint 4, test_thread_start} $output]} {
|
|
puts stderr "*** Error: Breakpoint in test thread did not trigger"
|
|
exit -1
|
|
}
|
|
|
|
send "info threads\n"
|
|
run_genode_until {\(gdb\)} 20 $gdb_id
|
|
|
|
if {![regexp {\* 4 Thread 4 test_thread_start} $output] ||
|
|
![regexp { 3 Thread 3} $output] ||
|
|
![regexp { 2 Thread 2} $output] ||
|
|
![regexp { 1 Thread 1} $output]} {
|
|
puts stderr "*** Error: Thread info is not as expected"
|
|
exit -1
|
|
}
|
|
|
|
puts "\n"
|
|
puts "----- test: step into function -----"
|
|
puts ""
|
|
|
|
send "step\n"
|
|
run_genode_until {\(gdb\)} 30 $gdb_id
|
|
|
|
send "thread 2\n"
|
|
run_genode_until {\(gdb\)} 20 $gdb_id
|
|
|
|
if {![regexp {test_thread_step} $output]} {
|
|
puts stderr "*** Error: Step into function didn't result in the expected output"
|
|
exit -1
|
|
}
|
|
|
|
puts "\n"
|
|
puts "----- test: catching a segmentation fault -----"
|
|
puts ""
|
|
|
|
send "c\n"
|
|
run_genode_until {\(gdb\)} 20 $gdb_id
|
|
|
|
if {![regexp {Thread 4 received signal SIGSEGV, Segmentation fault.} $output]} {
|
|
puts stderr "*** Error: Segmentation fault exception was not caught"
|
|
exit -1
|
|
}
|
|
|
|
# does not work well on ARM yet
|
|
if {![have_spec arm]} {
|
|
|
|
puts "\n"
|
|
puts "----- test: stack trace when in syscall -----"
|
|
puts ""
|
|
|
|
send "thread 2\n"
|
|
run_genode_until {\(gdb\)} 20 $gdb_id
|
|
|
|
send "bt\n"
|
|
run_genode_until {\(gdb\)} 20 $gdb_id
|
|
|
|
if {![regexp {Genode::Cancelable_lock::lock} $output] ||
|
|
![regexp {Genode::Signal_receiver::block_for_signal} $output] ||
|
|
![regexp {Genode::Entrypoint::_wait_and_dispatch_one_io_signal} $output] ||
|
|
![regexp {Libc::Kernel::run} $output] } {
|
|
|
|
puts stderr "*** Error: Stack trace when in syscall is not as expected"
|
|
exit -1
|
|
|
|
}
|
|
}
|
|
|
|
puts ""
|
|
|
|
# vi: set ft=tcl :
|