I am trying to debug code on an ARMv6-compatible processor rev 4.
I compiled the GDBserver with the --host=arm-openwrt-linux-gnueabi flag.
The gdb itself is compiled with
--host=x86_64-unknon-linux-gnu --target=arm-openwrt-linux-gnueabi --with-expat
If I now connect to the gdbserver in, my program is running in, I get the following error message:
(gdb) target remote 192.168.x.x:2345
Remote debugging using 192.168.x.x:2345
Cannot access memory at address 0x0
0xb6fdaec0 in ?? ()
(gdb) set sysroot /home/xxxxxx/Dokumente/lgn-sdk-v0.2/staging_dir/toolchain-arm_v6k_gcc-4.6-linaro_eglibc-2.15_eabi/
Reading symbols from /home/xxxxxx/Dokumente/lgn-sdk-v0.2/staging_dir/toolchain-arm_v6k_gcc-4.6-linaro_eglibc-2.15_eabi/lib/ld-linux.so.3...done.
Loaded symbols for /home/xxxxxxx/Dokumente/lgn-sdk-v0.2/staging_dir/toolchain-arm_v6k_gcc-4.6-linaro_eglibc-2.15_eabi/lib/ld-linux.so.3
(gdb) n
Single stepping until exit from function _start,
which has no line number information.
Program received signal SIGILL, Illegal instruction.
0xb6fe8d20 in _dl_debug_initialize () from /home/xxxxx/Dokumente/lgn-sdk-v0.2/staging_dir/toolchain-arm_v6k_gcc-4.6-linaro_eglibc-2.15_eabi/lib/ld-linux.so.3
(gdb)
Single stepping until exit from function _dl_debug_initialize,
which has no line number information.
Program terminated with signal SIGILL, Illegal instruction.
I don't have a complete answer, but I have a similar problem and work around it by:
connect via target remote
break main
continue
then, set sysroot
This lets me get past the crash. I'd certainly be interested in a better solution, though.
Related
I ported a gdbstub for an OS I'm working on which runs on x86_64. The host which is running gdb is connected to the target that has the stub and the OS over serial. I have an int3 instruction in the source code to force the OS to jump into the stub's code which it does. The problem is if I try to step to the next instruction using nexti the stub stops responding and the host keeps timing out.
Looking at the packets that the host is sending I see this:
Sending packet: $Me1dc20,1:cc#6c...Ack
Timed out.
Timed out.
Timed out.
Ignoring packet error, continuing...
which means that the host is telling the stub to write cc (which is the opcode for int3) to memory location 0xe1dc20. I looked into that memory location and found this:
(gdb) x/16i 0xe1dc20
0xe1dc20 <_Unwind_DebugHook>: retq
0xe1dc21: data16 nopw %cs:0x0(%rax,%rax,1)
0xe1dc2c: nopl 0x0(%rax)
This function is part of gcc's code here https://github.com/gcc-mirror/gcc/blob/master/libgcc/unwind-dw2.c but it is not used anywhere in the source file that I am debugging.
Now obviously it is causing me troubles so I disabled memory writing functionality in my stub so that it longer responds to memory writing commands $M and $X and when I did I was able to execute nexti and step in gdb without issues. The stub uses the RFLAGS.TF for flow control.
The question is why is gdb trying to set a breakpoint in a function that I am not using anywhere and how do I prevent it from doing so? I thought about adding an if statement in the stub to ignore writes to this memory location but is there a less intrusive way of doing it?
The _Unwind_DebugHook symbol exists as a place for GDB (or any other debugger) to place a breakpoint and so catch exceptions. GDB will look for this symbol (in the debug info), and it it exists, place a breakpoint there.
These breakpoints will always get inserted, even when doing something as simple as a stepi, just in case - you might be about to step to that address.
One problem I see with the remote trace is that GDB will be expecting an OK packet to indicate that the write succeeded, this is why you're seeing the timeout messages.
I am using GDB to log the executed assembly instruction.
Here is the GDB script I made:
log.gdb
set confirm off
tbreak start_trigger
r
set logging overwrite on
set logging on
set height 0
set style enabled off
while (1)
x/i $pc
stepi
end
quit
And I ran gdb using
$ gdb results-mte/aha-compress.elf -x script.gdb -batch
This works well and writes the gdb.txt but it is really slow. Is there any way to make it faster?
Is there any way to make it faster?
Yes: don't do that.
Think about how single-stepping works. On a processor which supports single-step in hardware, GDB has to
enable single-stepping
resume inferior
wait for OS to deliver SIGCHLD
query inferior for current registers ($pc mostly) via ptrace
decode and print current instruction
... repeat for each instruction. This is expected to be about 1000-10000 times slower than native execution.
Usual solutions are to use some tracing mechanism. E.g. using intel_pt trace would make this only slightly slower than full native speed.
I'm running this GDB inside a Fedora RiscV on QEMU.
Now you are emulating the GDB itself, adding another factor of 10 or more slowdown.
What you probably want to do is ask QEMU to record the instructions it executes.
Typing "qemu trace instructions" into Google produces this post (among others).
I am testing some simple code running in the ARM7TDMI, since I haven't found ARM7TDMI simulator on QEMU, I use Cortex-a8 instead (I am not sure if this will lead to bug, total newbie).
This is how I run QEMU:
qemu-system-arm -machine realview-pb-a8 -cpu cortex-a8 -nographic -monitor null -serial null -semihosting -kernel main.elf -gdb tcp::51234 -S
The code I want to test is quite simple, the function LoadContext() and SaveContext() is written in arm assembly for IAR IDE, and the IAR IDE is using ARM7TDMI as a core. I compiled this assembly file into an object file with IAR and link the code below with arm-none-eabi-gcc, will this cause unpredictable errors? (Just want to use gcc and QEMU instead of IAR...)
int main(void)
{
Running = &taskA;
Running->PC = task1;
Running->SP = &(Running->StackSeg[STACK_SIZE-1]);
LoadContext();
}
void task1(void)
{
register int reg_var = 1;
volatile int vol_var = 1;
SaveContext();
reg_var++;
vol_var++;
SaveContext();
reg_var++;
vol_var++;
LoadContext();
}
So, when I have set a breakpoint in the gdb, it is not working, it will just go into an endless loop I think. I checked the initialization process, it is:
(gdb)
0x000082f6 in __libc_init_array ()
(gdb)
0x000080e2 in _start ()
(gdb)
0x000080e4 in _start ()
(gdb)
0x000080e6 in _start ()
(gdb)
main () at src/context-demo.c:12
12 int main(void) {
(gdb)
0x000081ea 12 int main(void) {
(gdb)
0x00000008 in ?? ()
(gdb)
0x0000000c in ?? ()
(gdb)
0x00000010 in ?? ()
(gdb)
0x00000014 in ?? ()
(gdb) c
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x00000004 in ?? ()
(gdb) c
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x00000004 in ?? ()
(gdb)
Does anybody have any ideas about what happened here? Any help is appreciated, thanks!
You'll find this much easier to debug if you tell gdb to tell you about the assembly instructions it is executing ("display /3i $pc" will print the next 3 instructions every time gdb stops), and do single step of individual instructions ("stepi").
Something is causing you to end up at a low address 0x8 unexpectedly, and you need to find out what that is. Either you're really jumping to 0x8, or you've taken an exception. Looking at execution at a per-machine instruction level will tell you which it is.
Some plausible possibilities here:
executable built to assume it has RAM where the realview-pb-a8 does not have RAM -- this often manifests as "writing to the stack (or global variables) silently does nothing and reading from the stack/globals returns 0", so if you have a function pointer in a global or you try to push a return address to the stack and then pop it you'll end up at 0
executable built to assume it's running under an OS that provides an SVC API -- in this case the code will execute an SVC instruction and your code will crash because there's nothing to handle it at the SVC exception vector
executable built for the wrong CPU type and executes an instruction that UNDEFs (this should result in execution going to address 0x4, the undef vector, but I have a feeling there's a qemu bug in its gdbstub that may mean that a step that executes an UNDEF insn will not stop until after executing the first insn at the UNDEF vector)
executable built to assume that the FPU is always enabled. When QEMU is executing a "bare metal" binary like this, the CPU is started in the state that hardware starts, which has the FPU disabled. So any instructions using the FPU will UNDEF unless the executable's startup code has explicitly turned on the FPU.
I've listed those in rough order of probability for your case, but in any case single stepping by machine instruction should identify what's going on.
I am trying to debug a program using arm-none-eabi-gdb and step through it. There is an interrupt, USB0_Handler, which I do not want to step into while stepping the program. To achieve this, I tried to use skip, but it didn't work, even if I try to skip the function or skip the entire file (containing the interrupt). I am using openocd to achieve the remote debugging on the tm4c123gh6pm.
I have reached a point where I don't know if I should define myself a gdb function or I am missing a point. Here is the output of my terminal :
(gdb) info skip
Num Type Enb What
1 function y USB0_Handler
(gdb) c
Continuing.
Breakpoint 2, relayTask () at ./relay.c:191
191 nextTime = rtcGetTimeIn(DEFAULT_REFRESH_RATE);
(gdb) n
USB0_Handler () at ./UsbConfig.c:326
326 {
(gdb) n
332 ui32Status = MAP_USBIntStatusControl(USB0_BASE);
(gdb) n
337 USBDeviceIntHandlerInternal(0, ui32Status);
(gdb) n
338 }
(gdb) n #returning at the top of USB0_Handler
326 {
When an interrupt is triggered while stepping, GDB usually stops because the step ended in a place it didn't expect.
Interrupt handlers are generally hard to deal with from a debugger point of view because they are executed in a new context: the stack frames are changed and unless GDB recognizes a particular pattern in the frame it won't be able to compute a complete stack trace (i.e. the interrupt handler frames + your regular program stack trace before the interrupt.)
The simplest way to get you out of the interrupt handler is to plant a breakpoint on the last line of the function, resume and continue stepping. Someone suggested to use the finish command but it may fail depending on again the quality of the stack trace.
Thanks to GDB scriptability (in python for instance) it may be possible to automate that by checking the PC and if PC is on the isr address in irq vector, fetch the return address, plant a temporary breakpoint and resume.
I want to use rb_p() to aid in debugging a ruby C extension, but everytime i use it i get a SIGTRAP in gdb!
here's an example:
(gdb) p user_defaults
$3 = 137559900
(gdb) call rb_p(user_defaults)
{:fill=>true, :texture=>#}
(gdb) n
Program received signal SIGTRAP, Trace/breakpoint trap.
is_a_hash (try_hash=137560420) at utils.c:65
(gdb)
why does this happen? how can i stop it happening??
SIGTRAP is caused by a breakpoint exception, specifically by the int3 instruction on x86 (interrupt 3). Your code is probably executing an int3. Take a look where gdb is telling you -- at utils.c line 65 in the is_a_hash() function. If you don't have access to the source code, you can at least get the disassembly from gdb by typing
disas try_hash
at the gdb prompt.