This is the mail archive of the
gdb@sourceware.org
mailing list for the GDB project.
Debugging big-endian ARM target from little-endian host
- From: Jeff Wandling <JWandling at blueorigin dot com>
- To: "gdb at sourceware dot org" <gdb at sourceware dot org>
- Date: Wed, 27 Feb 2019 19:50:08 +0000
- Subject: Debugging big-endian ARM target from little-endian host
I have a question about the method to configure gdb(1) to debug big-endian target firmware.
Question and comments, ping me directly. I'll summarize as warranted based on responses. Thanks in advance.
The symptom/problem:
When the target firmware is compiled for big-endian, and when JLinkGDBServer is running such that the target is big-endian, then when debugging with gdb the capability to break and step fails.
The question(s) are:
If the remote target is big-endian, and the host is little-endian, is there something _more_ needed to be done in gdb(1) configuration to conduct a debug session whereas the endianness of the data and registers is interpreted as expected?
Is there a setting in gdb that enforces a behavior to step INTO assembly functions rather than OVER them even when "si" is used?
Setup:
Target device TMS570LC4357 (Hercules, TMS 570) ARM Cortex-R5
Target firmware, C/ASM code compiled as "big endian" (-mbig-endian, -EB, etc..)
All compilations made with:
$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (15:4.9.3+svn231177-1) 4.9.3 20150529 (prerelease)
$ arm-none-eabi-as --version
GNU assembler (2.26-4ubuntu1+8) 2.26
$ arm-none-eabi-ar --version
GNU ar (2.26-4ubuntu1+8) 2.26
$ arm-none-eabi-ld --version
GNU ld (2.26-4ubuntu1+8) 2.26
Host:
Little-endian Xeon with Ubuntu
Host runs JLinkGDBServer.exe ( version V642-f)
Host runs gdb(1) version 8.2
GDB was configured as follows:
configure --host=x86_64-linux-gnu --target=arm-none-eabi
--with-auto-load-dir=:/auto-load
--with-auto-load-safe-path=:/auto-load
--with-expat
--with-gdb-datadir=/usr/lib/arm-none-eabi/share/gdb
--with-jit-reader-dir=/usr/lib/lib/gdb
--without-libunwind-ia64
--without-lzma
--without-babeltrace
--without-intel-pt
--disable-libmcheck
--without-mpfr
--without-guile
--with-separate-debug-dir=/usr/lib/lib/debug
--with-system-gdbinit=/usr/lib/arm-none-eabi/lib/gdbinit
Data and explanation:
Suppose the firmware has a function at physical address 0x0000003C (somewhere in the first block of flash)
Suppose the breakpoint set in gdb is at this address.
If the breakpoint is set, and then the firmware is run, the gdb traps on the breakpoint:
GNU gdb (GDB) 8.2
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
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=x86_64-linux-gnu --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
.
Find the GDB manual and other documentation resources online at:
.
For help, type "help".
Type "apropos word" to search for commands related to "word".
Reading symbols from image.elf...done.
Remote debugging using localhost:2331
0x00000000 in ?? ()
The target endianness is set automatically (currently big endian)
(gdb) load
Loading section .text, size 0x4758 lma 0x20
Loading section .rodata, size 0x200 lma 0x4778
Start address 0x3c, load size 18776
Transfer rate: 6111 KB/sec, 6258 bytes/write.
(gdb) br _c_int00
Breakpoint 1 at 0x3c: file source/HL_sys_startup.c, line 88.
(gdb) c
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
0x3c000000 in ?? ()
(gdb) list
1
2
3 int main()
4 {
5 return 0;
6 }
(gdb) step
Cannot find bounds of current function
Attempts to step fail
"Cannot find bounds of current function"
I presume this is because the big-endian interpretation of the PC is an address where the function is not located.. The function is at physical address 0x3C.
(gdb) monitor regs
PC = 3C000000, CPSR = 000003D3 (SVC mode, ARM FIQ dis. IRQ dis.)
R0 = 00173180, R1 = FFFFFF48, R2 = 00000000, R3 = D3D3E1AB
R4 = 00000000, R5 = 08000B60, R6 = 00000000, R7 = 0800013F
USR: R8 =52894D31, R9 =084C44C1, R10=8D206C51, R11 =58311700, R12 =AC0C7CD7
R13=08000BA0, R14=08000137
FIQ: R8 =180A8884, R9 =00200200, R10=97D50C37, R11 =081E1C10, R12 =18A40002
R13=00008000, R14=9167F273, SPSR=2E0008E8
SVC: R13=04A9A810, R14=00000040, SPSR=2E0018E8
ABT: R13=2E6FA985, R14=3C000004, SPSR=00000393
IRQ: R13=2067F940, R14=0D044C2C, SPSR=2E0018E9
UND: R13=01004080, R14=00000008, SPSR=0000039B
OK, so to diagnose, I retried the test, but this time recompiling for little-endian and setup JLinkGDBServer for little endian:
Results are a little better. I can step next, but cannot step into:
GNU gdb (GDB) 8.2
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
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=x86_64-linux-gnu --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
.
Find the GDB manual and other documentation resources online at:
.
For help, type "help".
Type "apropos word" to search for commands related to "word".
Reading symbols from image.elf...done.
Remote debugging using localhost:2331
0x00000000 in ?? ()
(gdb) file image.elf
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Load new symbol table from "image.elf"? (y or n) y
Reading symbols from image.elf...done.
Resetting target
(gdb) load
Loading section .text, size 0x4760 lma 0x20
Loading section .rodata, size 0x200 lma 0x4780
Start address 0x3c, load size 18784
Transfer rate: 6114 KB/sec, 6261 bytes/write.
(gdb) b _c_int00
Breakpoint 1 at 0x3c: file source/HL_sys_startup.c, line 88.
(gdb) c
Continuing.
Breakpoint 1, _c_int00 () at source/HL_sys_startup.c:88
88 _coreInitRegisters_();
(gdb) disassemble _coreInitRegisters_
Dump of assembler code for function _coreInitRegisters_:
0x00004058 : mov r0, lr
0x0000405c : mov r1, #0
0x00004060 : mov r2, #0
0x00004064 : mov r3, #0
0x00004068 : mov r4, #0
0x0000406c : mov r5, #0
0x00004070 : mov r6, #0
0x00004074 : mov r7, #0
0x00004078 : mov r8, #0
0x0000407c : mov r9, #0
0x00004080 : mov r10, #0
0x00004084 : mov r11, #0
0x00004088 : mov r12, #0
0x0000408c : mov sp, #0
0x00004090 : mrs r1, CPSR
0x00004094 : msr SPSR_fsxc, r1
0x00004098 : cps #17
0x0000409c : mov lr, r0
0x000040a0 : mov r8, #0
0x000040a4 : mov r9, #0
0x000040a8 : mov r10, #0
0x000040ac : mov r11, #0
0x000040b0 : mov r12, #0
0x000040b4 : mrs r1, CPSR
0x000040b8 : msr SPSR_fsxc, r1
0x000040bc : cps #18
0x000040c0 : mov lr, r0
0x000040c4 : mrs r1, CPSR
0x000040c8 : msr SPSR_fsxc, r1
0x000040cc : cps #23
0x000040d0 : mov lr, r0
0x000040d4 : mrs r1, CPSR
0x000040d8 : msr SPSR_fsxc, r1
0x000040dc : cps #27
0x000040e0 : mov lr, r0
0x000040e4 : mrs r1, CPSR
0x000040e8 : msr SPSR_fsxc, r1
0x000040ec : cps #31
0x000040f0 : mov lr, r0
0x000040f4 : mrs r1, CPSR
0x000040f8 : msr SPSR_fsxc, r1
0x000040fc : mrc 15, 0, r2, cr1, cr0, {2}
0x00004100 : orr r2, r2, #15728640 ; 0xf00000
0x00004104 : mcr 15, 0, r2, cr1, cr0, {2}
0x00004108 : mov r2, #1073741824 ; 0x40000000
0x0000410c : vmsr fpexc, r2
--Type for more, q to quit, c to continue without paging--q
Quit
(gdb) b *0x4058
Breakpoint 2 at 0x4058: file source/HL_sys_core.s, line 50.
(gdb) n
// I would have expected the breakpoint at 0x4058 to be hit since it's after 0x4164, where the 'next' progressed to.
91 _coreInitStackPointer_();
(gdb) disassemble _coreInitStackPointer_
Dump of assembler code for function _coreInitStackPointer_:
0x00004164 : cps #17
0x00004168 : ldr sp, [pc, #48] ; 0x41a0
0x0000416c : cps #18
0x00004170 : ldr sp, [pc, #44] ; 0x41a4
0x00004174 : cps #19
0x00004178 : ldr sp, [pc, #28] ; 0x419c
0x0000417c : cps #23
0x00004180 : ldr sp, [pc, #32] ; 0x41a8
0x00004184 : cps #27
0x00004188 : ldr sp, [pc, #28] ; 0x41ac
0x0000418c : cps #31
0x00004190 : ldr sp, [pc] ; 0x4198
0x00004194 : bx lr
End of assembler dump.
(gdb) si
96 rstSrc = getResetSource();
// I would have expected it step into _coreInitStackPointer_, rather it stepped over it.
(gdb) list
91 _coreInitStackPointer_();
92
93 /* Reset handler: the following instructions read from the system exception status register
94 * to identify the cause of the CPU reset.
95 */
96 rstSrc = getResetSource();
97 switch(rstSrc)
98 {
99 case POWERON_RESET:
100 /* Initialize L2RAM to avoid ECC errors right after power on */
(gdb)