Previous: Example Configuration File, Up: Example
In one window, change to the example directory and start rsp-proxy with the example configuration file or1k.cfg on port 51000 with tracing enabled.
rsp-proxy or1k.cfg 51000 trace
rsp-proxy reports it is listening:
Listening for RSP on port 51000
In a second window, change to the example directory and start OpenRISC 1000 GDB. Load the symbols from the hello executable
or32-uclinux-gdb Building automata... done, num uncovered: 0/216. Parsing operands data... done. GNU gdb 6.8 Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=i686-pc-linux-gnu --target=or32-uclinux". (gdb) file hello Reading symbols from rsp-proxy/example/hello...done. (gdb)
Now connect to rsp-proxy using the GDB target remote command.
(gdb) target remote :51000 Remote debugging using :51000 simputc (c=72) at utils.c:61 61 __asm__ __volatile__ ( "\tl.nop\t%0" : : "K"( NOP_PUTC )); (gdb)
In the window running rsp-proxy, a trace of the RSP packets exchanged is shown, since rsp-proxy was started with the trace option:
RSP trace: getPkt: RSP packet: 10 chars, "qSupported" RSP trace: putPkt: RSP packet: 14 chars, "PacketSize=119" RSP trace: getPkt: RSP packet: 1 chars, "?" RSP trace: putPkt: RSP packet: 3 chars, "S05" RSP trace: getPkt: RSP packet: 4 chars, "Hc-1" RSP trace: putPkt: RSP packet: 2 chars, "OK" RSP trace: getPkt: RSP packet: 2 chars, "qC" RSP trace: putPkt: RSP packet: 3 chars, "QC1" RSP trace: getPkt: RSP packet: 8 chars, "qOffsets" RSP trace: putPkt: RSP packet: 19 chars, "Text=0;Data=0;Bss=0" RSP trace: getPkt: RSP packet: 3 chars, "Hg1" RSP trace: putPkt: RSP packet: 2 chars, "OK" RSP trace: getPkt: RSP packet: 1 chars, "g" RSP trace: putPkt: RSP packet: 280 chars, "0000000000007eb400007ebc000000000000 000000000000000000000000000000000000000012b000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000102c000010300 0000000" RSP trace: getPkt: RSP packet: 7 chars, "m1020,4" RSP trace: putPkt: RSP packet: 8 chars, "9c21fff8" RSP trace: getPkt: RSP packet: 7 chars, "m1024,4" RSP trace: putPkt: RSP packet: 8 chars, "d4011000" RSP trace: getPkt: RSP packet: 7 chars, "m1028,4" RSP trace: putPkt: RSP packet: 8 chars, "9c410008" RSP trace: getPkt: RSP packet: 7 chars, "m102c,4" RSP trace: putPkt: RSP packet: 8 chars, "d7e21ffc" RSP trace: getPkt: RSP packet: 7 chars, "m102c,4" RSP trace: putPkt: RSP packet: 8 chars, "d7e21ffc" RSP trace: getPkt: RSP packet: 7 chars, "m7eb8,4" RSP trace: putPkt: RSP packet: 8 chars, "00000048" RSP trace: getPkt: RSP packet: 9 chars, "qSymbol::" RSP trace: putPkt: RSP packet: 2 chars, "OK"
There is an initial exchange of packets to establish the characteristics of the target. rsp-proxy mimics a bare metal target, so there is only ever one thread. For simplicity no shifting of code sections is permitted.
A g
packets is a request for register values, which are returned
according to the values specified in the configuration file.
Lastly is a group of m
packets to read memory, as the GDB server
analyzes the function prologue of the code at its stopped location and
obtains data from the stack frame. The values returned are taken from
the initial values set in the configuration file.
At this point, any GDB command which relies only on reading or writing
memory or registers may be used. For example the argument to
simputs
, c
may be printed as a character:
(gdb) print (char)c $2 = 72 'H' (gdb)
The rsp-proxy window will show a m
packed used to read the
value from the stack
RSP trace: getPkt: RSP packet: 7 chars, "m7eb8,4" RSP trace: putPkt: RSP packet: 8 chars, "00000048"
The values used to initialize the stack correspond to a valid stack frame.
(gdb) backtrace #0 simputc (c=72) at utils.c:61 #1 0x000012b0 in simputs (str=0x13a0 "Hello World!\n") at utils.c:109 #2 0x00001358 in main () at hello.c:44 #3 0x00000118 in _start () (gdb)
The registers have their expected values
(gdb) info registers gpr1 gpr2 gpr9 ppc npc gpr1 0x7eb4 0x7eb4 gpr2 0x7ebc 0x7ebc gpr9 0x12b0 4784 ppc 0x102c 0x102c <simputc+12> npc 0x1030 0x1030 <simputc+16> (gdb)
The code can be disassembled, to check that the image specified in the configuration is as expected.
(gdb) disas simputc Dump of assembler code for function simputc: 0x00001020 <simputc+0>: l.addi r1,r1,-8 0x00001024 <simputc+4>: l.sw 0(r1),r2 0x00001028 <simputc+8>: l.addi r2,r1,8 0x0000102c <simputc+12>: l.sw -4(r2),r3 0x00001030 <simputc+16>: l.nop 4 0x00001034 <simputc+20>: l.lwz r2,0(r1) 0x00001038 <simputc+24>: l.jr r9 0x0000103c <simputc+28>: l.addi r1,r1,8 End of assembler dump. (gdb)
All register and memory locations are writable. For example we could
set the argument to simputc
, c
, held at offset -4 on the
current frame, to a different value.
(gdb) set *((int *)$fp - 1) = 'X' (gdb) backtrace #0 simputc (c=88) at utils.c:61 #1 0x000012b0 in simputs (str=0x13a0 "Hello World!\n") at utils.c:109 #2 0x00001358 in main () at hello.c:44 #3 0x00000118 in _start () (gdb) print (char)c $2 = 88 'X' (gdb)