Make arm use the new gdbarch_pseudo_register_write. This fixes writing
pseudo registers to non-current frames for that architecture.
Change-Id: Icb2a649ab6394817844230e9e94c3d0564d2f765
Reviewed-By: John Baldwin <jhb@FreeBSD.org>
Approved-by: Luis Machado <luis.machado@arm.com>
Make arm use the "newer" gdbarch_pseudo_register_read_value. This fixes
reading pseudo registers in non-current frames on that architecture.
Change-Id: Ic4d3d5d96957a4addfa3443c7b567dc4a31794a9
Reviewed-By: John Baldwin <jhb@FreeBSD.org>
Approved-by: Luis Machado <luis.machado@arm.com>
The next patch introduces a new variant of gdbarch_pseudo_register_write
that takes a frame instead of a regcache for implementations to write
raw registers. Rename to old one to make it clear it's deprecated.
Change-Id: If8872c89c6f8a1edfcab983eb064248fd5ff3115
Reviewed-By: John Baldwin <jhb@FreeBSD.org>
Some functions related to the handling of registers in frames accept
"this frame", for which we want to read or write the register values,
while other functions accept "the next frame", which is the frame next
to that. The later is needed because we sometimes need to read register
values for a frame that does not exist yet (usually when trying to
unwind that frame-to-be).
value_of_register and value_of_register_lazy both take "this frame",
even if what they ultimately want internally is "the next frame". This
is annoying if you are in a spot that currently has "the next frame" and
need to call one of these functions (which happens later in this
series). You need to get the previous frame only for those functions to
get the next frame again. This is more manipulations, more chances of
mistake.
I propose to change these functions (and a few more functions in the
subsequent patches) to operate on "the next frame". Things become a bit
less awkward when all these functions agree on which frame they take.
So, in this patch, change value_of_register_lazy and value_of_register
to take "the next frame" instead of "this frame". This adds a lot of
get_next_frame_sentinel_okay, but if we convert the user registers API
to also use "the next frame" instead of "this frame", it will get simple
again.
Change-Id: Iaa24815e648fbe5ae3c214c738758890a91819cd
Reviewed-By: John Baldwin <jhb@FreeBSD.org>
Right now, gdbsupport/common-regcache.h contains two abstractons for a
regcache. An opaque type `regcache` (gdb and gdbserver both have their
own regcache that is the concrete version of this) and an abstract base
class `reg_buffer_common`, that is the base of regcaches on both sides.
These abstractions allow code to be written for both gdb and gdbserver,
for instance in the gdb/arch sub-directory.
However, having two
different abstractions is impractical. If some common code has a regcache,
and wants to use an operation defined on reg_buffer_common, it can't.
It would be better to have just one. Change all instances of `regcache
*` in gdbsupport/common-regcache.h to be `reg_buffer_common *`, then fix
fallouts.
Implementations in gdb and gdbserver now need to down-cast (using
gdb::checked_static_cast) from reg_buffer_common to their concrete
regcache type. Some of them could be avoided by changing free functions
(like regcache_register_size) to be virtual methods on
reg_buffer_common. I tried it, it seems to work, but I did not include
it in this series to avoid adding unnecessary changes.
Change-Id: Ia5503adb6b5509a0f4604bd2a68b4642cc5283fd
Reviewed-by: John Baldwin <jhb@FreeBSD.org>
This changes gdb to use the C++17 [[fallthrough]] attribute rather
than special comments.
This was mostly done by script, but I neglected a few spellings and so
also fixed it up by hand.
I suspect this fixes the bug mentioned below, by switching to a
standard approach that, presumably, clang supports.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23159
Approved-By: John Baldwin <jhb@FreeBSD.org>
Approved-By: Luis Machado <luis.machado@arm.com>
Approved-By: Pedro Alves <pedro@palves.net>
Since GDB now requires C++17, we don't need the internally maintained
gdb::optional implementation. This patch does the following replacing:
- gdb::optional -> std::optional
- gdb::in_place -> std::in_place
- #include "gdbsupport/gdb_optional.h" -> #include <optional>
This change has mostly been done automatically. One exception is
gdbsupport/thread-pool.* which did not use the gdb:: prefix as it
already lives in the gdb namespace.
Change-Id: I19a92fa03e89637bab136c72e34fd351524f65e9
Approved-By: Tom Tromey <tom@tromey.com>
Approved-By: Pedro Alves <pedro@palves.net>
When compiling gdb with -fsanitize=address on ARM, I get a crash in test
gdb.arch/arm-disp-step.exp, reproduced easily with:
$ ./gdb -nx -q --data-directory=data-directory testsuite/outputs/gdb.arch/arm-disp-step/arm-disp-step -ex "break *test_call_end"
Reading symbols from testsuite/outputs/gdb.arch/arm-disp-step/arm-disp-step...
=================================================================
==23295==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xb4a14fd1 at pc 0x01a48871 bp 0xbeab8490 sp 0xbeab8494
Since it doesn't require running the program, it can be reproduced locally on a
dev machine other than ARM, after acquiring the test binary.
The length of the allocate buffer `buf` is 1, and we try to extract an
integer of size 2 from it. The length of 1 comes from the subtraction
`bpaddr - boundary`. Normally, on ARM, all instructions are aligned on
a multiple of 2, so it's weird for this subtraction to result in 1. In
this case, boundary comes from the result of find_pc_partial_function
returning 0x549:
(gdb) p/x bpaddr
$2 = 0x54a
(gdb) p/x boundary
$3 = 0x549
(gdb) p/x bpaddr - boundary
$4 = 0x1
0x549 is the address of the test_call_subr label, 0x548, with the thumb
bit enabled. Before doing some math with the address, I think we need
to strip the thumb bit, like is done elsewhere (for instance for bpaddr
earlier in the same function).
I wonder if find_pc_partial_function should do that itself, in order to
return an address that is suitable for arithmetic. In any case, that
would be a change with a broad impact, so for now just fix the issue
locally.
After the patch:
$ ./gdb -nx -q --data-directory=data-directory testsuite/outputs/gdb.arch/arm-disp-step/arm-disp-step -ex "break *test_call_end"
Reading symbols from testsuite/outputs/gdb.arch/arm-disp-step/arm-disp-step...
Breakpoint 1 at 0x54a: file /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/arm-disp-step.S, line 103.
Change-Id: I74fc458dbea0d2c1e1f5eadd90755188df089288
Approved-By: Luis Machado <luis.machado@arm.com>
On a big-endian ARM machine, the "return" command resulted in the
wrong value being returned when the function had a fixed-point return
type. This patch fixes the problem by unpacking and repacking the
fixed-point type appropriately.
Approved-By: Luis Machado <luis.machado@arm.com>
On big-endian ARM, "return"ing from a function that returned a range
type did not work. This patch strips the range type to treat the
function as though it were returning the underlying type instead.
Approved-By: Luis Machado <luis.machado@arm.com>
On a big-endian ARM system, "finish" printed the wrong value when
finishing from a function that returned a vector type. Similarly,
calls to a function also resulted in the wrong value being passed. I
think both the read- and write-functions here should ignore the
endian-ness.
I tested this using the AdaCore internal test suite; the test case
that caught this is identical to gdb.base/gnu_vector.exp.
Approved-By: Luis Machado <luis.machado@arm.com>
On ARM (I tested big-endian but it may not matter), "finish" can
sometimes print the wrong result when the return type is a range type.
Range types should really be treated as their underlying type
(normally integer, but sometimes fixed-point). This patch implements
this.
Approved-By: Luis Machado <luis.machado@arm.com>
On big-endian ARM, an inferior call with a small integer will pass the
wrong value. This patch fixes the problem. Because the code here
works using scalar values, and not just bytes, left-shifting is
unnecessary.
Approved-By: Luis Machado <luis.machado@arm.com>
This function is just a wrapper around the current inferior's gdbarch.
I find that having that wrapper just obscures where the arch is coming
from, and that it's often used as "I don't know which arch to use so
I'll use this magical target_gdbarch function that gets me an arch" when
the arch should in fact come from something in the context (a thread,
objfile, symbol, etc). I think that removing it and inlining
`current_inferior ()->arch ()` everywhere will make it a bit clearer
where that arch comes from and will trigger people into reflecting
whether this is the right place to get the arch or not.
Change-Id: I79f14b4e4934c88f91ca3a3155f5fc3ea2fadf6b
Reviewed-By: John Baldwin <jhb@FreeBSD.org>
Approved-By: Andrew Burgess <aburgess@redhat.com>
The new_objfile observer is currently used to indicate both when a new
objfile is added to program space (when passed non-nullptr) and when all
objfiles of a program space were just removed (when passed nullptr).
I think this is confusing (and Andrew apparently thinks so too [1]).
Add a new "all_objfiles_removed" observer to remove the second role from
"new_objfile".
Some existing users of new_objfile do nothing if the passed objfile is
nullptr. For them, we can simply drop the nullptr check. For others,
add a new all_objfiles_removed callback, and refactor things a bit to
keep the existing behavior as much as possible.
Some callbacks relied on current_program_space, and following
the refactoring now use either objfile->pspace or the pspace passed to
all_objfiles_removed. I think this should be relatively safe, and in
general a step in the right direction.
On the notify side, I found only one call site to change from
new_objfile to all_objfiles_removed, in clear_symtab_users. It is not
entirely clear to me that this is entirely correct. clear_symtab_users
appears to be called in spots that don't remove all objfiles
(functions finish_new_objfile, remove_symbol_file_command, reread_symbols,
do_module_cleanups). But I think that this patch at least makes the
current code clearer.
[1] a0a031bce0
Change-Id: Icb648f72862e056267f30f44dd439bd4ec766f13
Approved-By: Tom Tromey <tom@tromey.com>
I noticed a comment by an include and remembered that I think these
don't really provide much value -- sometimes they are just editorial,
and sometimes they are obsolete. I think it's better to just remove
them. Tested by rebuilding.
Approved-By: Andrew Burgess <aburgess@redhat.com>
As noted by Tom Tromey, there are some formatting issues with the ternary
operator in the aarch64/arm codebase. This patch fixes those.
Reviewed-By: Tom Tromey <tom@tromey.com>
The gdb.dwarf2/dw2-prologue-end-2.exp test was failing for both AArch64 and
Arm.
As Tom pointed out here (https://inbox.sourceware.org/gdb-patches/6663707c-4297-c2f2-a0bd-f3e84fc62aad@suse.de/),
there are issues with both the prologue skipper for AArch64 and Arm and an
incorrect assumption by the testcase.
This patch fixes both of AArch64's and Arm's prologue skippers to not skip past
the end of a function. It also incorporates a fix to the testcase so it
doesn't assume the prologue skipper will stop at the first instruction of the
functions/labels.
Regression-tested on aarch64-linux/arm-linux Ubuntu 20.04/22.04 and
x86_64-linux Ubuntu 20.04.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30506
Co-Authored-By: Tom de Vries <tdevries@suse.de>
Co-Authored-By: Luis Machado <luis.machado@arm.com>
This changes field_is_static to be a method on struct field, and
updates all the callers. Most of this patch was written by script.
Regression tested on x86-64 Fedora 36.
This commit aims to address a problem that exists with the current
approach to displaced stepping, and was identified in PR gdb/22921.
Displaced stepping is currently supported on AArch64, ARM, amd64,
i386, rs6000 (ppc), and s390. Of these, I believe there is a problem
with the current approach which will impact amd64 and ARM, and can
lead to random register corruption when the inferior makes use of
asynchronous signals and GDB is using displaced stepping.
The problem can be found in displaced_step_buffers::finish in
displaced-stepping.c, and is this; after GDB tries to perform a
displaced step, and the inferior stops, GDB classifies the stop into
one of two states, either the displaced step succeeded, or the
displaced step failed.
If the displaced step succeeded then gdbarch_displaced_step_fixup is
called, which has the job of fixing up the state of the current
inferior as if the step had not been performed in a displaced manner.
This all seems just fine.
However, if the displaced step is considered to have not completed
then GDB doesn't call gdbarch_displaced_step_fixup, instead GDB
remains in displaced_step_buffers::finish and just performs a minimal
fixup which involves adjusting the program counter back to its
original value.
The problem here is that for amd64 and ARM setting up for a displaced
step can involve changing the values in some temporary registers. If
the displaced step succeeds then this is fine; after the step the
temporary registers are restored to their original values in the
architecture specific code.
But if the displaced step does not succeed then the temporary
registers are never restored, and they retain their modified values.
In this context a temporary register is simply any register that is
not otherwise used by the instruction being stepped that the
architecture specific code considers safe to borrow for the lifetime
of the instruction being stepped.
In the bug PR gdb/22921, the amd64 instruction being stepped is
an rip-relative instruction like this:
jmp *0x2fe2(%rip)
When we displaced step this instruction we borrow a register, and
modify the instruction to something like:
jmp *0x2fe2(%rcx)
with %rcx having its value adjusted to contain the original %rip
value.
Now if the displaced step does not succeed, then %rcx will be left
with a corrupted value. Obviously corrupting any register is bad; in
the bug report this problem was spotted because %rcx is used as a
function argument register.
And finally, why might a displaced step not succeed? Asynchronous
signals provides one reason. GDB sets up for the displaced step and,
at that precise moment, the OS delivers a signal (SIGALRM in the bug
report), the signal stops the inferior at the address of the displaced
instruction. GDB cancels the displaced instruction, handles the
signal, and then tries again with the displaced step. But it is that
first cancellation of the displaced step that causes the problem; in
that case GDB (correctly) sees the displaced step as having not
completed, and so does not perform the architecture specific fixup,
leaving the register corrupted.
The reason why I think AArch64, rs600, i386, and s390 are not effected
by this problem is that I don't believe these architectures make use
of any temporary registers, so when a displaced step is not completed
successfully, the minimal fix up is sufficient.
On amd64 we use at most one temporary register.
On ARM, looking at arm_displaced_step_copy_insn_closure, we could
modify up to 16 temporary registers, and the instruction being
displaced stepped could be expanded to multiple replacement
instructions, which increases the chances of this bug triggering.
This commit only aims to address the issue on amd64 for now, though I
believe that the approach I'm proposing here might be applicable for
ARM too.
What I propose is that we always call gdbarch_displaced_step_fixup.
We will now pass an extra argument to gdbarch_displaced_step_fixup,
this a boolean that indicates whether GDB thinks the displaced step
completed successfully or not.
When this flag is false this indicates that the displaced step halted
for some "other" reason. On ARM GDB can potentially read the
inferior's program counter in order figure out how far through the
sequence of replacement instructions we got, and from that GDB can
figure out what fixup needs to be performed.
On targets like amd64 the problem is slightly easier as displaced
stepping only uses a single replacement instruction. If the displaced
step didn't complete the GDB knows that the single instruction didn't
execute.
The point is that by always calling gdbarch_displaced_step_fixup, each
architecture can now ensure that the inferior state is fixed up
correctly in all cases, not just the success case.
On amd64 this ensures that we always restore the temporary register
value, and so bug PR gdb/22921 is resolved.
In order to move all architectures to this new API, I have moved the
minimal roll-back version of the code inside the architecture specific
fixup functions for AArch64, rs600, s390, and ARM. For all of these
except ARM I think this is good enough, as no temporaries are used all
that's needed is the program counter restore anyway.
For ARM the minimal code is no worse than what we had before, though I
do consider this architecture's displaced-stepping broken.
I've updated the gdb.arch/amd64-disp-step.exp test to cover the
'jmpq*' instruction that was causing problems in the original bug, and
also added support for testing the displaced step in the presence of
asynchronous signal delivery.
I've also added two new tests (for amd64 and i386) that check that GDB
can correctly handle displaced stepping over a single instruction that
branches to itself. I added these tests after a first version of this
patch relied too much on checking the program-counter value in order
to see if the displaced instruction had executed. This works fine in
almost all cases, but when an instruction branches to itself a pure
program counter check is not sufficient. The new tests expose this
problem.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=22921
Approved-By: Pedro Alves <pedro@palves.net>
GDB expected PC should point right after the SVC instruction when the
syscall is active. But some active syscalls keep PC pointing to the SVC
instruction itself.
This leads to a broken backtrace like:
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
#0 0xb6f8681c in pthread_cond_timedwait@@GLIBC_2.4 () from /lib/arm-linux-gnueabihf/libpthread.so.0
#1 0xb6e21f80 in ?? ()
The reason is that .ARM.exidx unwinder gives up if PC does not point
right after the SVC (syscall) instruction. I did not investigate why but
some syscalls will point PC to the SVC instruction itself. This happens
for the "futex" syscall used by pthread_cond_timedwait.
That normally does not matter as ARM prologue unwinder gets called
instead of the .ARM.exidx one. Unfortunately some glibc calls have more
complicated prologue where the GDB unwinder fails to properly determine
the return address (that is in fact an orthogonal GDB bug). I expect it
is due to the "vpush" there in this case but I did not investigate it more:
Dump of assembler code for function pthread_cond_timedwait@@GLIBC_2.4:
0xb6f8757c <+0>: push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
0xb6f87580 <+4>: mov r10, r2
0xb6f87584 <+8>: vpush {d8}
Regression tested on armv7l kernel 5.15.32-v7l+ (Raspbian 11).
Approved-By: Luis Machado <luis.machado@arm.com>
The gdbarch::max_insn_length field is used mostly to support displaced
stepping; it controls the size of the buffers allocated for the
displaced-step instruction, and is also used when first copying the
instruction, and later, when fixing up the instruction, in order to
read in and parse the instruction being stepped.
However, it has started to be used in other places in GDB, for
example, it's used in the Python disassembler API, and it is used on
amd64 as part of branch-tracing instruction classification.
The problem is that the value assigned to max_insn_length is not
always the maximum instruction length, but sometimes is a multiple of
that length, as required to support displaced stepping, see rs600,
ARM, and AArch64 for examples of this.
It seems to me that we are overloading the meaning of the
max_insn_length field, and I think that could potentially lead to
confusion.
I propose that we add a new gdbarch field,
gdbarch::displaced_step_buffer_length, this new field will do
exactly what it says on the tin; represent the required displaced step
buffer size. The max_insn_length field can then do exactly what it
claims to do; represent the maximum length of a single instruction.
As some architectures (e.g. i386, and amd64) only require their
displaced step buffers to be a single instruction in size, I propose
that the default for displaced_step_buffer_length will be the
value of max_insn_length. Architectures than need more buffer space
can then override this default as needed.
I've updated all architectures to setup the new field if appropriate,
and I've audited all calls to gdbarch_max_insn_length and switched to
gdbarch_displaced_step_buffer_length where appropriate.
There should be no user visible changes after this commit.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
This turns the remaining value_contents functions -- value_contents,
value_contents_all, value_contents_for_printing, and
value_contents_for_printing_const -- into methods of value. It also
converts the static functions require_not_optimized_out and
require_available to be private methods.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
This turns value_contents_raw, value_contents_writeable, and
value_contents_all_raw into methods on value. The remaining functions
will be changed later in the series; they were a bit trickier and so I
didn't include them in this patch.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
This patch resolves the performance issue reported in pr/29738 by
caching the values for the stack pointers for the inner frame. By
doing so, the impact can be reduced to checking the state and
returning the appropriate value.
Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
Signed-off-by: Yvan Roux <yvan.roux@foss.st.com>
This helps resolve some cyclic include problem later in the series.
The only language-related thing frame.h needs is enum language, and that
is in defs.h.
Doing so reveals that a bunch of files were relying on frame.h to
include language.h, so fix the fallouts here and there.
Change-Id: I178a7efec1953c2d088adb58483bade1f349b705
Reviewed-By: Bruno Larsen <blarsen@redhat.com>
It's currently not clear how the ownership of gdbarch_tdep objects
works. In fact, nothing ever takes ownership of it. This is mostly
fine because we never free gdbarch objects, and thus we never free
gdbarch_tdep objects. There is an exception to that however: when
initialization fails, we do free the gdbarch object that is not going to
be used, and we free the tdep too. Currently, i386 and s390 do it.
To make things clearer, change gdbarch_alloc so that it takes ownership
of the tdep. The tdep is thus automatically freed if the gdbarch is
freed.
Change all gdbarch initialization functions to pass a new gdbarch_tdep
object to gdbarch_alloc and then retrieve a non-owning reference from
the gdbarch object.
Before this patch, the xtensa architecture had a single global instance
of xtensa_gdbarch_tdep. Since we need to pass a dynamically allocated
gdbarch_tdep_base instance to gdbarch_alloc, remove this global
instance, and dynamically allocate one as needed, like we do for all
other architectures. Make the `rmap` array externally visible and
rename it to the less collision-prone `xtensa_rmap` name.
Change-Id: Id3d70493ef80ce4bdff701c57636f4c79ed8aea2
Approved-By: Andrew Burgess <aburgess@redhat.com>
This converts a few selected architectures to use
gdbarch_return_value_as_value rather than gdbarch_return_value. The
architectures are just the ones that I am able to test. This patch
should not introduce any behavior changes.
This commit is the result of running the gdb/copyright.py script,
which automated the update of the copyright year range for all
source files managed by the GDB project to be updated to include
year 2023.
These headers define the register numbers for each port to implement
the sim_fetch_register & sim_store_register interfaces. While gdb
uses these, the APIs are part of the sim, not gdb. Move the headers
out of the gdb/ include namespace and into sim/ instead.
For v8m, the EXC_RETURN pattern, without security extension, consists of
FType, Mode and SPSEL. These are the same bits that are used in v7m.
This patch extends the list of patterns to include also the FType bit
and not just Mode and SPSEL bits for v8m targets without security
extension.
Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
As part of the rebase of the patch, I managed to loose the local
changes I had for the comments from Tomas in
https://sourceware.org/pipermail/gdb-patches/2022-November/193413.html
This patch corrects the obvious two typos.
Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
For targets with secext, msp and psp can be seen as an alias for one
of msp_s, msp_ns, psp_s or psp_ns.
Without this patch, sp might be secure, but msp or psp is non-secure
(this state can not happen in the hardware).
Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
For targets with secext, msp and psp can be seen as an alias for one
of msp_s, msp_ns, psp_s or psp_ns. When switching active sp, the
corresponding msp/psp needs to be switched too.
Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
Arm v8-M Architecture Reference Manual,
D1.2.95 EXC_RETURN, Exception Return Payload
describes ES bit:
"ES, bit [0]
Exception Secure. The security domain the exception was taken to.
The possible values of this bit are:
0 Non-secure.
1 Secure"
arm-tdep.c:3443, arm_m_exception_cache () function tests this bit:
exception_domain_is_secure = (bit (lr, 0) == 0);
The test is negated!
Later on line 3553, the condition evaluates if an additional state
context is stacked:
/* With the Security extension, the hardware saves R4..R11 too. */
if (tdep->have_sec_ext && secure_stack_used
&& (!default_callee_register_stacking || exception_domain_is_secure))
RM, B3.19 Exception entry, context stacking
reads:
RPLHM "In a PE with the Security Extension, on taking an exception,
the PE hardware:
...
2. If exception entry requires a transition from Secure state to
Non-secure state, the PE hardware extends the stack frame and also
saves additional state context."
So we should test for !exception_domain_is_secure instead of non-negated
value!
These two bugs compensate each other so unstacking works correctly.
But another test of exception_domain_is_secure (negated due to the
first bug) prevents arm_unwind_secure_frames to work as expected:
/* Unwinding from non-secure to secure can trip security
measures. In order to avoid the debugger being
intrusive, rely on the user to configure the requested
mode. */
if (secure_stack_used && !exception_domain_is_secure
&& !arm_unwind_secure_frames)
Test with GNU gdb (GDB) 13.0.50.20221016-git.
Stopped in a non-secure handler:
(gdb) set arm unwind-secure-frames 0
(gdb) bt
#0 HAL_SYSTICK_Callback () at C:/dvl/stm32l5trustzone/GPIO_IOToggle_TrustZone/NonSecure/Src/nsmain.c:490
#1 0x0804081c in SysTick_Handler ()
at C:/dvl/stm32l5trustzone/GPIO_IOToggle_TrustZone/NonSecure/Src/nsstm32l5xx_it.c:134
#2 <signal handler called>
#3 HAL_GPIO_ReadPin (GPIOx=0x52020800, GPIO_Pin=8192)
at C:/dvl/stm32l5trustzone/GPIO_IOToggle_TrustZone/Drivers/STM32L5xx_HAL_Driver/Src/stm32l5xx_hal_gpio.c:386
#4 0x0c000338 in SECURE_Mode () at C:/dvl/stm32l5trustzone/GPIO_IOToggle_TrustZone/Secure/Src/main.c:86
#5 0x080403f2 in main () at C:/dvl/stm32l5trustzone/GPIO_IOToggle_TrustZone/NonSecure/Src/nsmain.c:278
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
The frames #3 and #4 are secure. backtrace should stop before #3.
Stopped in a secure handler:
(gdb) bt
#0 HAL_SYSTICK_Callback () at C:/dvl/stm32l5trustzone/GPIO_IOToggle_TrustZone/Secure/Src/main.c:425
#1 0x0c000b6a in SysTick_Handler ()
at C:/dvl/stm32l5trustzone/GPIO_IOToggle_TrustZone/Secure/Src/stm32l5xx_it.c:234
warning: Non-secure to secure stack unwinding disabled.
#2 <signal handler called>
The exception from secure to secure erroneously stops unwinding. It should
continue as far as the security unlimited backtrace:
(gdb) set arm unwind-secure-frames 1
(gdb) si <-- used to rebuild frame cache after change of unwind-secure-frames
0x0c0008e6 425 if (SecureTimingDelay != 0U)
(gdb) bt
#0 0x0c0008e6 in HAL_SYSTICK_Callback () at C:/dvl/stm32l5trustzone/GPIO_IOToggle_TrustZone/Secure/Src/main.c:425
#1 0x0c000b6a in SysTick_Handler ()
at C:/dvl/stm32l5trustzone/GPIO_IOToggle_TrustZone/Secure/Src/stm32l5xx_it.c:234
#2 <signal handler called>
#3 0x0c000328 in SECURE_Mode () at C:/dvl/stm32l5trustzone/GPIO_IOToggle_TrustZone/Secure/Src/main.c:88
#4 0x080403f2 in main () at C:/dvl/stm32l5trustzone/GPIO_IOToggle_TrustZone/NonSecure/Src/nsmain.c:278
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
Set exception_domain_is_secure to the value expected by its name.
Fix exception_domain_is_secure usage in the additional state context
stacking condition.
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Arm v8-M Architecture Reference Manual,
D1.2.141 IPSR, Interrupt Program Status Register reads
"Exception, bits [8:0]"
9 bits, not 8! It is uncommon but true!
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
In the lockup state the PC value of the the outer frame is irreversibly
lost. The other registers are intact so LR likely contains
PC of some frame next to the outer one, but we cannot analyze
the nearest outer frame without knowing its PC
therefore we do not know SP fixup for this frame.
The frame unwinder possibly gets mad due to the wrong SP value.
To prevent problems terminate unwinding if PC contains the magic
value of the lockup state.
Example session wihtout this change,
Cortex-M33 CPU in lockup, gdb 13.0.50.20221016-git:
----------------
(gdb) c
Continuing.
Program received signal SIGINT, Interrupt.
0xeffffffe in ?? ()
(gdb) bt
#0 0xeffffffe in ?? ()
#1 0x0c000a9c in HardFault_Handler ()
at C:/dvl/stm32l5trustzone/GPIO_IOToggle_TrustZone/Secure/Src/stm32l5xx_it.c:99
#2 0x2002ffd8 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb)
----------------
The frame #1 is at correct PC taken from LR, #2 is a total nonsense.
With the change:
----------------
(gdb) c
Continuing.
Program received signal SIGINT, Interrupt.
warning: ARM M in lockup state, stack unwinding terminated.
<signal handler called>
(gdb) bt
#0 <signal handler called>
(gdb)
----------------
There is a visible drawback of emitting a warning in a cache buildnig routine
as introduced in Torbjörn SVENSSON's
[PATCH v4] gdb/arm: Stop unwinding on error, but do not assert
The warning is printed just once and not repeated on each backtrace command.
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Currently, every internal_error call must be passed __FILE__/__LINE__
explicitly, like:
internal_error (__FILE__, __LINE__, "foo %d", var);
The need to pass in explicit __FILE__/__LINE__ is there probably
because the function predates widespread and portable variadic macros
availability. We can use variadic macros nowadays, and in fact, we
already use them in several places, including the related
gdb_assert_not_reached.
So this patch renames the internal_error function to something else,
and then reimplements internal_error as a variadic macro that expands
__FILE__/__LINE__ itself.
The result is that we now should call internal_error like so:
internal_error ("foo %d", var);
Likewise for internal_warning.
The patch adjusts all calls sites. 99% of the adjustments were done
with a perl/sed script.
The non-mechanical changes are in gdbsupport/errors.h,
gdbsupport/gdb_assert.h, and gdb/gdbarch.py.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
Change-Id: Ia6f372c11550ca876829e8fd85048f4502bdcf06
Setting SP of the next frame to the same address as the current frame
is an ugly way to stop the unwinding. A cleaner way is to rely on
the frame_unwind_stop_reason function to return UNWIND_OUTERMOST.
Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
When it's impossible to read the FPCCR and XPSR, the unwinding is
unpredictable as the it's not possible to determine the correct
frame size or padding.
The only sane thing to do in this condition is to stop the unwinding.
Example session without this patch:
(gdb) bt
#0 SVC_Handler () at .../GPIO/GPIO_EXTI/Src/stm32f4xx_it.c:112
.../gdb/arm-tdep.c:3594: internal-error: arm_m_exception_cache: Assertion `safe_read_memory_unsigned_integer (FPCCR, ARM_INT_REGISTER_SIZE, byte_order, &fpccr)' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
----- Backtrace -----
0x5583bfb2a157 gdb_internal_backtrace_1
...
---------------------
This is a bug, please report it. For instructions, see:
<https://www.gnu.org/software/gdb/bugs/>.
Aborted (core dumped)
Example session with this patch:
(gdb) bt
#0 SVC_Handler () at .../GPIO/GPIO_EXTI/Src/stm32f4xx_it.c:112
warning: Could not fetch required FPCCR content. Further unwind is impossible.
#1 <signal handler called>
(gdb)
Reviewed-by: Pedro Alves <pedro@palves.net>
Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
This changes GDB to use frame_info_ptr instead of frame_info *
The substitution was done with multiple sequential `sed` commands:
sed 's/^struct frame_info;/class frame_info_ptr;/'
sed 's/struct frame_info \*/frame_info_ptr /g' - which left some
issues in a few files, that were manually fixed.
sed 's/\<frame_info \*/frame_info_ptr /g'
sed 's/frame_info_ptr $/frame_info_ptr/g' - used to remove whitespace
problems.
The changed files were then manually checked and some 'sed' changes
undone, some constructors and some gets were added, according to what
made sense, and what Tromey originally did
Co-Authored-By: Bruno Larsen <blarsen@redhat.com>
Approved-by: Tom Tomey <tom@tromey.com>