New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement gdb-stub
on 3rd UART
#360
Conversation
This syscall is the opposite of ClaimInterrupt. Signed-off-by: Sean Cross <sean@xobs.io>
This function never failed. Make it infallible so that it matches the same calling convention as `enable_irq()` Signed-off-by: Sean Cross <sean@xobs.io>
Previously, `disable_irq()` would unconditionally mask an interrupt in the `sim` register. However, when interrupts are disabled this register is zero, and we really should be updating `SIM_BACKING`. Consult the state of the interrupt handler and update the appropriate field as necessary. Signed-off-by: Sean Cross <sean@xobs.io>
Add an initial reimplementation of the gdb-stub using the gdbstub backing crate. This supports process enumeration and basic thread investigation. Processes will pause when the debugger is inspecting them. Memory and registers can be investigated. Threads can be listed and selected. It does not yet support breakpoints. Signed-off-by: Sean Cross <sean@xobs.io>
This adds a basic gdb server. Currently, it is possible to list processes and inspect memory and threads. It is not yet possible to actually interact with code (e.g. no breakpoints and no single stepping). Signed-off-by: Sean Cross <sean@xobs.io>
These calls should be possible to make during interrupts. Signed-off-by: Sean Cross <sean@xobs.io>
Disable IRQs during destruction, but only if constructed with `GdbUart::new()`. This allows characters to buffer when the GDB bridge is destroyed while avoiding the double-free error we were getting from creating a new UART in the IRQ handler. Signed-off-by: Sean Cross <sean@xobs.io>
When debugging an invalid process (e.g. not yet run, terminated, etc.) return an error rather than silently continuing. Signed-off-by: Sean Cross <sean@xobs.io>
Implement the basics required to get "extended mode" working. This is waiting on upstream to fix issues, but should allow us to attach to processes once it works. Signed-off-by: Sean Cross <sean@xobs.io>
Since gdbstub is able to do this, break individual features into their own files. Signed-off-by: Sean Cross <sean@xobs.io>
Many of the devicse have changed from `uint` to `ulong`, so forward-port the peripherals to work with the new format. Signed-off-by: Sean Cross <sean@xobs.io>
Debug handling was not correct, and didn't work at all. Additionally, interrupt masking didn't work. Fix these problems. Signed-off-by: Sean Cross <sean@xobs.io>
The gdb server runs on an additional serial port and provides process-level debugging to the kernel. Signed-off-by: Sean Cross <sean@xobs.io>
The riscv target requires stepi to be implemented, which we now do. Signed-off-by: Sean Cross <sean@xobs.io>
I rebased onto |
Resume the debugged process when the debugger disconnects. Signed-off-by: Sean Cross <sean@xobs.io>
We should probably put the documentation on "building" and "usage" somewhere more permanent than in this issue... |
Agreed -- I just wanted to have it tested on real hardware first. I think there should be an |
i've added a It'll take a while to re-image the disk, and then I'll be able to test this. |
You ought to be able to use |
yah the problem isn't the distro. it's that the card has hit its write life limit and is hanging as i extract it. |
There's a delightful Python program from stack overflow to hook a serial port up to a TCP socket, so you can use your build machine: #!/usr/bin/python
import socket
import sys
import serial
#open serial port
ser = serial.Serial('/dev/ttyAMA0', 115200, timeout=0)
#create socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
#bond to the port. Don't use localhost to accept external connections
server_address = ('', 2105)
print('starting up on {} port {}'.format(*server_address))
sock.bind(server_address)
#listen
sock.listen(1)
#loop
while True:
#waits for a new connection
print('waiting for a connection')
connection, client_address = sock.accept()
try:
print('connection from', client_address)
#continously send from serial port to tcp and viceversa
connection.settimeout(0.1)
while True:
try:
data = connection.recv(16)
if data == '': break
ser.write(data)
except KeyboardInterrupt:
connection.close()
sys.exit()
except Exception as e:
pass
received_data = ser.read(ser.inWaiting())
connection.sendall(received_data)
except Exception as e:
print e
finally:
#clean up connection
connection.close() |
that's a neat trick, maybe it should be documented somewhere where it can be discovered by others? |
woo more yak shaving. the card is now renewed to a new one, but my libc is too old for the xpack toolchain....it'll be another few hours while the dist-upgrade runs. |
Alright, got things upgraded and tried running it. It sort of works, but the connection seems unstable. This is what I get on a "good" run:
Of course in the above trial I had the path of the executable wrong, but at least it did something. More typically, I get something like this:
I wonder if there are flow control issues possibly? I guess there are no RTS/CTS pins on this interface, but basically if the kernel is held up you're going to lose data. The FIFO is only 16 bytes deep on the Tx/Rx queues on the UARTs, so if you write more than that and the kernel is busy with something else, you'll end up dropping bytes. |
That looks like you might be connecting to the kernel debug port? Isn't there a command to switch the serial port to be the |
This patchset implements a
gdb-stub
server that runs on the 3rd UART (app_uart
). With this patch, enabling thegdb-stub
feature will yield a server that allows for application level debugging.Building
To build, add
gdb-stub
to the list of features:Then load the kernel into an image onto the target device.
Usage
To use, attach gdb to the serial port. For example, to debug the ticktimer, you might run:
This will load the
xous-ticktimer
ELF file, then attach to the GDB server running on the serial port connected to COM43, then attach to process ID 2.You will then be able to use normal GDB commands to inspect memory, single-step, add breakpoints, and switch threads.
Useful commands
The
info thr
command will list current threads. You may then switch threads with e.g.thr 4
to switch to thread 4.The
x
command can be used to examine arbitrary memory.b
is used to insert breakpoints. Note that breakpoints are accomplished by replacing instructions in memory withc.ebreak
instructions, so debugging does not work with XIP processes.c
will continue execution, andControl-C
will pause execution.stepi
will single-step assembly execution.You may switch processes with
attach [PID]
Debugging and servers
When a process is under debug, messages will queue up. Interrupts are masked, and the process is paused.
When you
continue
a process under debug, it is unpaused, interrupts are re-enabled, and messages are delivered.Renode fixes
When running this under Renode, a very recent copy (from April 2023 or later) is required. This also requires adjustments to the simulation models, which are included in this patchset.