Re: GDB call and p func() on embedded target

Simon Marchi via Gdb <[email protected]>
Newsgroups gmane.comp.gdb.devel
Message-ID <[email protected]>

On 2021-08-14 11:54 a.m., Maximilian Schneider wrote:
> Hello,
> 
> Some more information:
> 
> I'm working on an stm32l475.
> 
> using openocd like so:
> openocd -v
> Open On-Chip Debugger 0.10.0+dev-g436782b (2019-03-05-19:20)
> 
> openocd -f interface/stlink-v2-1.cfg -f target/stm32l4x.cfg -d3
> And the executable I debug is compiled like this:
> arm-none-eabi-gcc -Wall -Werror -Tscript.ld -Wl,-n,-N -nostartfiles
> -ggdb -g -nostdlib -FPIC -FPIE -mcpu=cortex-m4 $(INCLUDES) $(DEFINES)
> src/loader.c -o loader.elf
> 
> I use a linker script to put the code section into RAM.
> 
> I should als mention the gdb version:
> arm-none-eabi-gdb -v
> GNU gdb (7.12-6+9+b2) 7.12.0.20161007-git
> 
> I will try compiling the latest gdb from source, and debug it a little
> later. In the mean time I can demonstrate gdb is creating stack frames.
> Maybe you can spot something wrong with them?
> 
> (gdb) set debug infrun 1
> (gdb) p Init()
> infrun: clear_proceed_status_thread (Remote target)
> infrun: proceed (addr=0x20000aac, signal=GDB_SIGNAL_0)
> infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [Remote target] at 0x20000aac
> infrun: infrun_async(1)
> infrun: prepare_to_wait
> infrun: target_wait (-1.0.0, status) =
> infrun:   -1.0.0 [Thread 0],
> infrun:   status->kind = ignore
> infrun: TARGET_WAITKIND_IGNORE
> infrun: prepare_to_wait
> 
> * just sits here *
> 
> I don't see any comments about creating a stack frame.
> But gdb definately creates one.
> I can inspect the stack frame after the call is made
> 
> eg:
> I place a breakpoint in Init. and use p Init() twice.
> (gdb) p Init()
> ...
> (gdb) p Init()
> ..
> (gdb) info frame
> Stack level 0, frame at 0x2000ffe0:
>  pc = 0x20000ab2 in Init (src/loader.c:718); saved pc = 0x0
>  called by frame at 0x2000ffe0
>  source language c.
>  Arglist at 0x2000ffd0, args: 
>  Locals at 0x2000ffd0, Previous frame's sp is 0x2000ffe0
>  Saved registers:
>   r7 at 0x2000ffd8, lr at 0x2000ffdc
> (gdb) info frame 1
> Stack frame at 0x2000ffe0:
>  pc = 0x0; saved pc = 0x20000ab2
>  called by frame at 0x2000fff8, caller of frame at 0x2000ffe0
>  Arglist at unknown address.
>  Locals at unknown address, Previous frame's sp is 0x2000ffe8
> (gdb) info symbol 0x20000ab2
> Init + 6 in section PrgCode
> 
> This is creating two stack frames as expected, and I can step the inner
> function.
> When I step through the return there is a pop instruction that restores
> the PC from the stack frame and execution resumes in the calee.
> 
> What is pc= vs saved pc=? Is it relevant that pc=0x0?

The execution out of the manual function call isn't expected to end
"just like that", with a return.  Normally, when the called function
returns, it should return to some code (the dummy stack frame) that
generates some exception, so that GDB gets back control.  How this is
done varies from arch to arch.  This is where it happens:

  https://gitlab.com/gnutools/binutils-gdb/-/blob/master/gdb/infcall.c#L956-1012

For ARM, it seems like gdbarch_call_dummy_location uses the default
AT_ENTRY_POINT, meaning that GDB puts a breakpoint at the address
returned by entry_point_address(), and sets up the stack frame created
to call Init to return there.  Maybe with your executable the entry
point returns 0, and that's why you see frame 1 having pc == 0?

Simon
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.