gdb: xtensa: fix truncated backtrace for nested noreturn functions

The problem appears when break in nested noreturn calls.
panic_abort() and esp_system_abort() are noreturn functions:

    #0  0x4008779f in panic_abort ()
    #1  0x40087a78 in esp_system_abort ()
    Backtrace stopped: previous frame identical to this frame (corrupt stack?)

Assembly listing:

    40081ad4 <panic_abort>:
    40081ad4:	004136        	entry	a1, 32
    40081aeb:	ffff06        	j	40081aeb <panic_abort+0x17>
    	...

    40085614 <esp_system_abort>:
    40085614:	004136        	entry	a1, 32
    40085619:	fc4ba5        	call8	40081ad4 <panic_abort>

    4008561c <__ubsan_include>:
    4008561c:	004136        	entry	a1, 32

PC register for frame esp_system_abort points to the next instruction after
instruction with address 40085619.
It is ENTRY instruction for __ubsan_include. This caused wrong unwinding
because we are not in __ubsan_include at this frame. In general for
noreturn functions there should be RET instruction. This is why it works
in all other cases.

PC register can point to entry instruction only for the innermost frame.
It is not possible otherwise.

The fix is making it not possible to go with not innermost frame into
the code block which collects frame cache for frames when PC is on entry
instruction.
This commit is contained in:
Alexey Lapshin
2022-08-05 18:18:09 +04:00
parent 9427a9f5ac
commit ba83bd16b7
3 changed files with 92 additions and 1 deletions

View File

@@ -0,0 +1,42 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2019-2022 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "../lib/attributes.h"
void __attribute__((noreturn)) ATTRIBUTE_NOCLONE
baz ()
{
while(1); /* Break here. */
}
void __attribute__((noreturn)) ATTRIBUTE_NOCLONE
bar ()
{
baz ();
}
void __attribute__((noinline)) ATTRIBUTE_NOCLONE
foo ()
{
bar ();
}
int
main ()
{
foo ();
}

View File

@@ -0,0 +1,48 @@
# Copyright 2019-2022 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# A place for miscellaneous tests related to backtrace.
standard_testfile
if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
return -1
}
if ![runto_main] then {
fail "can't run to main"
return 0
}
# Run to the breakpoint at return.
gdb_breakpoint [gdb_get_line_number "Break here."]
gdb_continue_to_breakpoint "Break here."
# Backtrace with the default options.
gdb_test "bt" \
[multi_line \
"#0\[ \t\]*baz \\(\\) at \[^\r\n\]+" \
"#1\[ \t\]*$hex in bar \\(\\) at \[^\r\n\]+" \
"#2\[ \t\]*$hex in foo \\(\\) at \[^\r\n\]+" \
"#3\[ \t\]*$hex in main \\(\\) at \[^\r\n\]+" ]
# Backtrace with 'set disassemble-next-line on'. This shouldn't make
# any difference to the backtrace.
gdb_test "with disassemble-next-line on -- bt" \
[multi_line \
"#0\[ \t\]*baz \\(\\) at \[^\r\n\]+" \
"#1\[ \t\]*$hex in bar \\(\\) at \[^\r\n\]+" \
"#2\[ \t\]*$hex in foo \\(\\) at \[^\r\n\]+" \
"#3\[ \t\]*$hex in main \\(\\) at \[^\r\n\]+" ]

View File

@@ -1264,7 +1264,8 @@ xtensa_frame_cache (const frame_info_ptr &this_frame, void **this_cache)
ws = get_frame_register_unsigned (this_frame,
tdep->ws_regnum);
if (safe_read_memory_integer (pc, 1, byte_order, &op1)
if (frame_relative_level (this_frame) == 0
&& safe_read_memory_integer (pc, 1, byte_order, &op1)
&& XTENSA_IS_ENTRY (gdbarch, op1))
{
int callinc = CALLINC (ps);