genode/ports/run/gdb_monitor.run
Christian Prochaska 93faa9a36f Config option for GDB monitor RAM preservation
This patch allows to configure the amount of RAM that GDB monitor should
preserve for itself. The configuration syntax looks as follows:

<start name="gdb_monitor">
    <resource name="RAM" quantum="1G"/>
    <config>
        <target name="noux">
        <preserve name="RAM" quantum="2M"/>
        ...
    </config>
</start>

Fixes #190.
2012-04-23 15:32:22 +02:00

240 lines
5.5 KiB
Tcl

#
# \brief Test for using the GDB monitor
# \author Christian Prochaska
# \author Norman Feske
# \date 2011-05-24
#
#
# Only Genode/Fiasco.OC supports all the tested features at this time
#
assert_spec foc
#
# Build
#
build {
core init
drivers/timer drivers/uart
app/gdb_monitor
test/gdb_monitor
}
create_boot_directory
#
# Generate config
#
set config {
<config verbose="yes">
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="CAP"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
<service name="SIGNAL"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<start name="timer">
<resource name="RAM" quantum="512K"/>
<provides> <service name="Timer"/> </provides>
</start>
<start name="uart_drv">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Terminal"/> </provides>
<config>
<policy label="gdb_monitor" uart="1"/>
</config>
</start>
<start name="gdb_monitor">
<resource name="RAM" quantum="4M"/>
<config>
<target name="test-gdb_monitor"/>
<preserve name="RAM" quantum="2M"/>
</config>
</start>
</config>
}
install_config $config
#
# Boot modules
#
# generic modules
set boot_modules {
core init timer
ld.lib.so libc.lib.so libc_log.lib.so libc_lock_pipe.lib.so libc_terminal.lib.so
uart_drv
gdb_monitor test-gdb_monitor
}
build_boot_image $boot_modules
#
# Execute test case
#
#
set local_port 5555
# qemu config
append qemu_args " -m 128 -nographic "
# connect comport 0 to stdio
append qemu_args " -serial mon: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 "
run_genode_until {.*Remote debugging using /dev/terminal.*} 30
puts "GDB monitor is up, starting GDB"
# sequence of GDB commands to execute at startup
set gdb_cmds ""
append gdb_cmds {-ex "target remote localhost:$local_port" }
#
# The test breaks into the 'main()' function of the dynamically linked test
# application by using the following gdb command sequence. It's important that
# the 'main()' breakpoint gets set before the 'sharedlibrary' command is
# executed. Otherwise the breakpoint would get set in ld.lib.so's main()
# function.
#
# don't ask for y/n when loading a new symbol file
append gdb_cmds {-ex "set interactive-mode off" }
# load the symbols of ld.lib.so
append gdb_cmds {-ex "symbol-file bin/ld.lib.so" }
# set a breakpoint in the 'call_main()' function
append gdb_cmds {-ex "b call_main" }
# continue execution until the breakpoint triggers
append gdb_cmds {-ex "c" }
# delete the 'call_main()' breakpoint
append gdb_cmds {-ex "delete 1" }
# load the symbols of the test application
append gdb_cmds {-ex "symbol-file bin/test-gdb_monitor" }
# set a breakpoint in the application's 'main()' function
append gdb_cmds {-ex "b main" }
# load the symbols of loaded shared libraries
append gdb_cmds {-ex "sharedlibrary" }
# continue execution until the breakpoint triggers
append gdb_cmds {-ex "c" }
# delete the 'main()' breakpoint
append gdb_cmds {-ex "delete 2" }
#
# Test commands
#
# test: breakpoint in shared library
append gdb_cmds {-ex "b puts" }
append gdb_cmds {-ex "c" }
# test: stack trace when not in syscall
append gdb_cmds {-ex "bt" }
# test: thread info
append gdb_cmds {-ex "b Test_thread::entry()" }
append gdb_cmds {-ex "c" }
append gdb_cmds {-ex "info threads" }
# test: single stepping
append gdb_cmds {-ex "step" }
# test: catch segmentation fault
append gdb_cmds {-ex "c" }
# test: stack trace when in syscall
append gdb_cmds {-ex "thread 1" }
append gdb_cmds {-ex "bt" }
# quit
append gdb_cmds {-ex "q" }
# run GDB and redirect stderr to stdio to get the relevant output into the expect buffer
eval spawn [gdb] bin/test-gdb_monitor -batch $gdb_cmds 2&>1
set timeout 60
expect {
timeout { puts stderr "Error: Test execution timed out"; exit -2 }
}
set gdb_output $expect_out(buffer)
#
# Evaluate the test results
#
if {![regexp {Breakpoint 2, main ()} $gdb_output]} {
puts stderr "Error: Breakpoint in main() did not trigger"
exit -1
}
if {![regexp {Breakpoint 3, puts ()} $gdb_output]} {
puts "Error: Breakpoint in shared library did not trigger"
exit -1
}
if {![regexp {#0 puts} $gdb_output] ||
![regexp {in func2 ()} $gdb_output] ||
![regexp {in func1 ()} $gdb_output] ||
![regexp {in main ()} $gdb_output]} {
puts stderr "Error: Stack trace when not in syscall is not as expected"
exit -1
}
if {![regexp {Breakpoint 4, Test_thread::entry()} $gdb_output]} {
puts stderr "Error: Breakpoint in test thread did not trigger"
exit -1
}
if {![regexp {\* 2 Thread 2 Test_thread::entry} $gdb_output] ||
![regexp { 1 Thread 1} $gdb_output]} {
puts stderr "Error: Thread info is not as expected"
exit -1
}
if {![regexp {40 func()} $gdb_output]} {
puts stderr "Error: Single stepping didn't result in the expected output"
exit -1
}
if {![regexp {Program received signal SIGSEGV, Segmentation fault.} $gdb_output]} {
puts stderr "Error: Segmentation fault exception was not catched"
exit -1
}
if {![regexp {Genode::Ipc_istream::_wait} $gdb_output] ||
![regexp {Genode::Ipc_server::_wait} $gdb_output] ||
![regexp {Genode::sleep_forever ()} $gdb_output]} {
puts stderr "Error: Stack trace when in syscall is not as expected"
exit -1
}
puts "Test succeeded"
# vi: set ft=tcl :