Why is gdb automatically doing a read after my requested write? - debugging

I'm using gdb to communicate with a LEON2-based ASIC through a home made gdb server (not sure though that "gdb server" is the correct phrase here). It works like this: the gdb client uses the ordinary gdb protocol to talk to the gdb server, which then translates the gdb requests to reads and writes from/to the HW and sends back the result to the client, if any. My gdb client is sparc-rtems-gdb 6.6 in RTEMS 4.8.0 on a Windows 7 PC.
When I start the gdb client I run the following command to attach to the gdb server:
target extended-remote localhost:5000
Then I want to change a word in RAM so I run this gdb command:
set *((unsigned int*) 0x40000000)=2
While debugging the gdb server I can see that it receives the following line, which is expected and correct according to the gdb protocol, i.e. writing 4 bytes, value 2 to address 0x40000000:
M40000000,4:00000002
Now the confusion: After the write request above, another request comes from the gdb client, read 4 bytes from address 0xABD37787:
mabd37787,4
Why is the gdb client trying to read from that address? As far as I know, I haven't done anything to request this read, I only wanted to perform the write. If gdb would have read back the address 0x40000000, for example to verify the write, it would be OK. But the out-of-nowhere-address 0xABD37787 does not exist on my HW, which causes problems for me.
Is there any way that I can debug the gdb client to determine exactly what (and why) it is sending and receiving? Or is there a setting in gdb that can explain this behaviour?
Best regards
Henrik

While debugging the gdb server I can see that it receives the following line
You don't need to be debugging the gdbserver. You can simply turn on set debug remote 1 in GDB, and have GDB print all sent and received packets.
Why is the gdb client trying to read from that address?
There are several possibilities:
GDB believes that program counter is currently at 0xABD37787
GDB believes that it needs to set a breakpoint there
GDB believes that there is some data that it needs to read
One possible way to figure out why GDB is trying to read that location is to set debug infrun 1. This will print a lot of info about what GDB itself is trying to do.
Another way is to debug GDB itself. Put a breakpoint on putpkt, and when the packet of interest is being sent, examine the stacktrace to see why it is being sent.

Related

Debugging a custom OS with QEMU

I am trying to write a simple OS, I already wrote a bootloader but now I want to debug it, so I switched from using VirtualBox to QEMU because I saw it had better debugging.
The problem is that after I added the -s parameter to QEMU command and successfully connected via GDB, it says that the symbol table isn't loaded and that I should use the "file" command.
The only difference from what I did to what I saw people on the Internet do, is that they started GDB with gdb vmlinux, but I can't do that because I am not debugging a Linux kernel... so I figured that the issue is that I didn't start GDB with an executable, but using the "file" command on my OS image, and the compiled and linked .out file, tells me it's a "DOS/MBR boot sector", so I can't start GDB with either of them (I tried to do that anyways, but GDB failed).
Help would be appreciated.
EDIT: also, I did assemble the bootloader with the -g and --gstabs+ options.
gdb would like a file so that it can give you symbolic debugging information. For that you will need to give it a file in a format with debug info which corresponds to where your OS ends up in RAM. The "DOS/MBR boot sector" file is a disk image (the BIOS will load part of this into RAM for you, and it will then presumably finish loading code itself).
But gdb will also entirely happily let you do assembly-level debugging; you can just ignore the warning about not having a symbol table, and use the single step instruction, disassemble-from-pc and similar commands:
"disas $pc,+32" disassembles 32 bytes from the current PC
the display command prints after execution stops, so "disp /3i $pc" will print the next 3 instructions every time gdb gets control
"stepi" and "nexti" do single-instruction step/next ("step" and "next" are source-line stepping and require debug info)

Debug embedded software (coredump)

I'm currently working on an embedded CPU (ARM cortex-M0) on board. I'm experiencing crashes (HardFault) and thus, I'm trying to debug them.
Currently I can get a dump of the memory (I send everything in hex over the printf console, my only access to the memory).
My idea is to load that dump as coredump to gdb and thus being able to debug the program.
How is it possible to create a "real" coredump file from the raw memory dump, so that I can give it directly to gdb ?
I also tried to run my program in the gdb simulator to use the restore command with my raw memory but I don't understand how to run it. Do you have an idea ?
The main question here is in fact: How to create a coredump file that is compatible with gdb based on the program elf and the raw memory content ?
There are a pair of libraries that will do this: CrashCatcher and CrashDebug. This first prints a dump (which you are already doing but this prints in a specific format) and the second interfaces into gdb to allow loading the dump. For some reason CrashDebug doesn't create a core file but rather interfaces into gdb using gdb's target remote command. Same effect though. It supports Cortex-M0, M3, and M4.

Toggling between remote KGDB and local DDB within a debugging session

I would like to know if there is indeed a way to toggle between gdb and ddb while debugging a remote kernel.
I am already at the gdb (or rather kgdb) prompt. From here how do I switch to local ddb on the debugged machine?
My kernel configuration file already contains options BREAK_TO_DEBUGGER and I have BOTH GDB and DDB configured aka:
options GDB
options DDB
As per the developer's handbook, "Every time you type gdb, the mode will be toggled between remote GDB and local DDB. In order to force a next trap immediately, simply type s (step). Your hosting GDB will now gain control over the target kernel:"
So, I did try typing 'gdb' at the gdb prompt (funny me:D) and as expected, it was an unrecognized command. Obviously, this command is supposed to be typed at the ddb prompt. But my question is, how do I drop to ddb from within a running machine whose serial ports (albeit virtual ones) are remotely attached to another machine's KGDB? When remote GDB is listening and I force a panic using sysctl debug.kdb.enter=1, it does drop into remote KGDB. However, when it is NOT listening, the system just freezes.
What I want, is to enter ddb on the local machine. Do some debugging using it; drop to remote KGDB for things that are best done using KGDB, then switch back to local DDB when I'm done.
Is there a way to do that?
KDB contains DDB & KDB backends, but there are a lot of conditions when they are available. To check if backend is available, check sysctl debug.kdb.available and debug.kdb.current (sys/kern/subr_kdb.c). If both backends are available, debug.kdb.available should contains "ddb gdb".
The possible way to toggle between backends (gdb / ddb) is to enter ddb at first, then call gdb and make debugging. Then exit gdb, and return to ddb (actually new trap will happen, seems Ctrl+C is required). It means that before panic, debug.kdb.current should be set to "ddb".
I hope it will help.

GDB does not break on a read access to an address caught by PIN

I've captured a read memory trace (i.e. addresses of all read accesses) of a program-run by Intel PIN, ASLR was off. I can capture it several times and the trace is still exactly the same.
Then I take an address from the trace (a specific address I am interested in), set a watchpoint in GDB by rwatch *0x7fffe309e643 but GDB does not notice the access. I'm doing this in the same terminal where the trace has been taken so it should access the same addresses; when I capture it then again, the trace is still very the same.
Do you have any ideas or hints why GDB does not catch it?
I have to note that the access very likely happens within a (C++) structure loaded from a Boost serialization and that the code has been compiled with -g3 -O1 flags (-O1 is really crucial for other reasons but a minimal example showed me that GDB breaks correctly even with -O1).
UPDATE:
As suggested, I tried PIN debugger (which actually utilizes GDB) but there is some problem with watchpoints. To present this problem, I made a minimal example.
int main()
{
unsigned char i = 4;
i++;
i = 3;
return 0;
}
I acquired a read memory trace with PIN and chose 0x7fffffffd89f (or similar) as the address of interest. Then I started PIN debugger and GDB in parallel terminals and connected GDB to PIN ((gdb) target remote :57946, as suggested by PIN). In GDB I set watchpoint (gdb) rwatch *0x7fffffffd89f and started execution but I get
Continuing.
Warning:
Could not insert hardware watchpoint 1.
Could not insert hardware breakpoints:
You may have requested too many hardware breakpoints/watchpoints.
even though I only inserted a single watchpoint. I also tried to explicitly disable hardware breakpoints by set can-use-hw-watchpoints 0 but then it ran for an hour with no result and no processor load so I killed it.
Is there any other way how to set a functional watchpoint at a specific address when GDB is connected to PIN debugger? Note that there is no such problem with standalone GDB.
I use GDB 7.7.1, PIN 2.14-71313 and GCC 4.4.7, running Ubuntu 14.04.
The original problem would be likely solved then.
From pin user guide:
The "pin" Executable (Launcher)
The kit's root directory contains a "pin" executable. This is a 32-bit
launcher, used for launching Pin in 32 and 64 bit modes. The launcher
sets up the environment to find the libraries supplied with the kit.
It is likely that the environment is different when running pinbin, and therefore stack addresses will also be different (0x7fffe309e643 looks like a possible stack address) even without ASLR.
Your best bet is probably to use Pin application debugging interface.

How to read GDTR and LDTR in kgdb?

This question deals with why you can't read the GDTR and LDTR in user-mode GDB. But I don't see why it shouldn't be possible when debugging a Linux kernel (with KGDB compiled in), using GDB on another machine with serial cable.
The kernel being debugged should be able to tell the debugger the values of the GDTR and LDTR, but it doesn't seem there is any GDB command to make it do so. Is there a good reason for this? Is it just something which nobody has implemented?
As you say, nobody implemented it.
gdb in particular doesn't consider those valid registers, so the kernel debug interface doesn't even try to send them.
Unless you are willing to change gdb, you must use a workaround to get that information. One such possibility I can think of is the ThreadExtraInfo command which should be able to send arbitrary string message that gets printed in gdb. So you could add that information in kernel/debug/gdbstub.c.

Resources