[PING] gdb/arm: Fix backtrace for pthread_cond_timedwait

Message ID Y8V2/BPT840ojNDq@host1.jankratochvil.net
State New
Headers
Series [PING] gdb/arm: Fix backtrace for pthread_cond_timedwait |

Commit Message

Jan Kratochvil Jan. 16, 2023, 4:10 p.m. UTC
  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).
---
 gdb/arm-tdep.c                                |  42 ++++---
 .../gdb.arch/arm-pthread_cond_timedwait-bt.c  |  62 +++++++++++
 .../arm-pthread_cond_timedwait-bt.exp         | 105 ++++++++++++++++++
 3 files changed, 192 insertions(+), 17 deletions(-)
 create mode 100644 gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c
 create mode 100644 gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.exp
  

Comments

Luis Machado Jan. 17, 2023, 11:14 a.m. UTC | #1
Hi Jan,

Sorry, I didn't spot the patch on the list.

On 1/16/23 16:10, Jan Kratochvil wrote:
> 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).
> ---
>   gdb/arm-tdep.c                                |  42 ++++---
>   .../gdb.arch/arm-pthread_cond_timedwait-bt.c  |  62 +++++++++++
>   .../arm-pthread_cond_timedwait-bt.exp         | 105 ++++++++++++++++++
>   3 files changed, 192 insertions(+), 17 deletions(-)
>   create mode 100644 gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c
>   create mode 100644 gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.exp
> 
> diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
> index 78a2fe2ade5..328eb17f419 100644
> --- a/gdb/arm-tdep.c
> +++ b/gdb/arm-tdep.c
> @@ -3116,26 +3116,34 @@ arm_exidx_unwind_sniffer (const struct frame_unwind *self,
>   	  && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME)
>   	exc_valid = 1;
>   
> -      /* We also assume exception information is valid if we're currently
> -	 blocked in a system call.  The system library is supposed to
> -	 ensure this, so that e.g. pthread cancellation works.  */
> -      if (arm_frame_is_thumb (this_frame))
> +      /* Some syscalls keep PC pointing to the SVC instruction itself.  */
> +      for (int shift = 0; shift <= 1 && !exc_valid; ++shift)
>   	{
> -	  ULONGEST insn;
> +	  /* We also assume exception information is valid if we're currently
> +	     blocked in a system call.  The system library is supposed to
> +	     ensure this, so that e.g. pthread cancellation works.  */
> +	  if (arm_frame_is_thumb (this_frame))
> +	    {
> +	      ULONGEST insn;
>   
> -	  if (safe_read_memory_unsigned_integer (get_frame_pc (this_frame) - 2,
> -						 2, byte_order_for_code, &insn)
> -	      && (insn & 0xff00) == 0xdf00 /* svc */)
> -	    exc_valid = 1;
> -	}
> -      else
> -	{
> -	  ULONGEST insn;
> +	      if (safe_read_memory_unsigned_integer ((get_frame_pc (this_frame)
> +						      - (shift ? 2 : 0)),
> +						     2, byte_order_for_code,
> +						     &insn)
> +		  && (insn & 0xff00) == 0xdf00 /* svc */)
> +		exc_valid = 1;
> +	    }
> +	  else
> +	    {
> +	      ULONGEST insn;
>   
> -	  if (safe_read_memory_unsigned_integer (get_frame_pc (this_frame) - 4,
> -						 4, byte_order_for_code, &insn)
> -	      && (insn & 0x0f000000) == 0x0f000000 /* svc */)
> -	    exc_valid = 1;
> +	      if (safe_read_memory_unsigned_integer ((get_frame_pc (this_frame)
> +						      - (shift ? 4 : 0)),
> +						     4, byte_order_for_code,
> +						     &insn)
> +		  && (insn & 0x0f000000) == 0x0f000000 /* svc */)
> +		exc_valid = 1;
> +	    }
>   	}

The changes and reasoning sound good to me, though the test doesn't seem to be doing much on my setup.

I see the same results with a patched and unpatched gdb:

PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: successfully compiled posix threads test case
PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: advance to break-line
PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: thread 2 for svc check
UNTESTED: gdb.arch/arm-pthread_cond_timedwait-bt.exp: pc points to svc

Do you see something different?

>   	
>         /* Bail out if we don't know that exception information is valid.  */
> diff --git a/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c b/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c
> new file mode 100644
> index 00000000000..c382a100afd
> --- /dev/null
> +++ b/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c
> @@ -0,0 +1,62 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 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 <pthread.h>
> +#include <sys/time.h>
> +#include <unistd.h>
> +#include <assert.h>
> +
> +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
> +static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
> +
> +static void *fun(void *arg)
> +{
> +  struct timeval now;
> +  struct timespec until;
> +  int err;
> +
> +  err = gettimeofday(&now, NULL);
> +  assert(!err);
> +
> +  until.tv_sec = now.tv_sec + 60;
> +  until.tv_nsec = now.tv_usec * 1000UL;
> +
> +  pthread_cond_timedwait(&cond, &mutex, &until);
> +  assert(0);
> +  err = pthread_mutex_unlock(&mutex);
> +  assert(!err);
> +
> +  return arg;
> +}
> +
> +int main()
> +{
> +  pthread_t thread;
> +  void *ret;
> +  int err;
> +
> +  err = pthread_mutex_lock(&mutex);
> +  assert(!err);
> +  err = pthread_create(&thread, NULL, fun, NULL);
> +  assert(!err);
> +  err = pthread_mutex_lock(&mutex);
> +  assert(!err);
> +  err = pthread_join(thread, &ret); // break-line
> +  assert(0);
> +
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.exp b/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.exp
> new file mode 100644
> index 00000000000..d5e594c73d5
> --- /dev/null
> +++ b/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.exp
> @@ -0,0 +1,105 @@
> +# Copyright 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/>.
> +
> +# This serves as a template for writing new test cases.  Replace this with
> +# a description of what this test case tests.
> +
> +standard_testfile
> +
> +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
> +			  {debug pthreads}] } {
> +    return
> +}
> +
> +if { ![runto_main] } {
> +    return
> +}
> +
> +gdb_test "advance [gdb_get_line_number "break-line"]" "break-line.*" \
> +	 "advance to break-line"
> +
> +gdb_test "thread 2" "Switching to thread 2 .*" "thread 2 for svc check"
> +
> +# 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.
> +set test "pc points to svc"
> +gdb_test_multiple {x/i $pc} $test {
> +    -re ":\tsvc\t0x00000000\r\n$gdb_prompt $" {
> +	pass $test
> +    }
> +    -re "\r\n$gdb_prompt $" {
> +	untested $test
> +	return
> +    }
> +}
> +
> +gdb_test "thread 1" "Switching to thread 1 .*"
> +gdb_test_no_output "set debug frame 1"
> +
> +# PASS:
> +#  [frame] frame_unwind_try_unwinder: trying unwinder "arm exidx"
> +#  [frame] frame_unwind_register_value: enter
> +#...
> +#  [frame] frame_unwind_register_value: exit
> +#  [frame] frame_unwind_try_unwinder: yes
> +#...
> +#  [frame] get_prev_frame_always_1:   -> {level=0,type=NORMAL_FRAME,unwinder="arm exidx",pc=0xb6f8681c,id=<not computed>,func=<unknown>} // cached
> +
> +# FAIL:
> +#  [frame] frame_unwind_try_unwinder: trying unwinder "arm exidx"
> +#  [frame] frame_unwind_register_value: enter
> +#...
> +#  [frame] frame_unwind_register_value: exit
> +#  [frame] frame_unwind_try_unwinder: no
> +#  [frame] frame_unwind_try_unwinder: trying unwinder "arm epilogue"
> +#  [frame] frame_unwind_register_value: enter
> +#...
> +#  [frame] frame_unwind_register_value: exit
> +#  [frame] frame_unwind_try_unwinder: no
> +#  [frame] frame_unwind_try_unwinder: trying unwinder "arm prologue"
> +#  [frame] frame_unwind_try_unwinder: yes
> +#...
> +#  [frame] get_prev_frame_always_1:   -> {level=0,type=NORMAL_FRAME,unwinder="arm prologue",pc=0xb6f8681c,id=<not computed>,func=<unknown>} // cached
> +
> +set test "unwinder is arm exidx"
> +# Switch the threads to reset frame cache.
> +gdb_test_multiple {thread 2} $test {
> +    -re "\{level=0,type=NORMAL_FRAME,unwinder=\"arm exidx\",pc=.*\r\n$gdb_prompt $" {
> +	pass $test
> +    }
> +    -re "\{level=0,type=NORMAL_FRAME,unwinder=\"arm prologue\",pc=.*\r\n$gdb_prompt $" {
> +	fail $test
> +    }
> +    -re "\r\n$gdb_prompt $" {
> +	untested $test
> +	return
> +    }
> +}
> +
> +gdb_test "thread 2" "Switching to thread 2 .*" "thread 2 for debug frame check"
> +
> +gdb_test_no_output "set debug frame 0"
> +
> +# PASS:
> +# #0  0xb6f8681c in pthread_cond_timedwait@@GLIBC_2.4 () from /lib/arm-linux-gnueabihf/libpthread.so.0
> +# #1  0x00010648 in fun (arg=0x0) at .../gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c:38
> +# ...
> +
> +# FAIL:
> +# #0  0xb6f8681c in pthread_cond_timedwait@@GLIBC_2.4 () from /lib/arm-linux-gnueabihf/libpthread.so.0
> +# #1  0xb6e21f80 in ?? ()
> +# Backtrace stopped: previous frame identical to this frame (corrupt stack?)
> +
> +gdb_test "bt" { in fun \(arg=.*} "unwind of pthread_cond_timedwait"
  
Jan Kratochvil Jan. 18, 2023, 11:51 a.m. UTC | #2
Hi Luis,

On Tue, 17 Jan 2023 19:14:01 +0800, Luis Machado wrote:
> I see the same results with a patched and unpatched gdb:
> 
> PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: successfully compiled posix threads test case
> PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: advance to break-line
> PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: thread 2 for svc check
> UNTESTED: gdb.arch/arm-pthread_cond_timedwait-bt.exp: pc points to svc
> 
> Do you see something different?

Yes, on Raspbian 11 (bullseye), Linux version 5.15.32-v7l+, Raspberry 4.

What OS do you run?

There is the unfortunate dependency on system pthread_cond_timedwait()
implementation. The testcase could provide also its own .S implementation but
then it could be incompatible with the rest of system glibc.


Jan
Test run by jenkins on Wed Jan 18 12:34:28 2023
Native configuration is armv7l-unknown-linux-gnueabihf

		=== gdb tests ===

Schedule of variations:
    unix

Running target unix
Using /usr/share/dejagnu/baseboards/unix.exp as board description file for target.
Using /usr/share/dejagnu/config/unix.exp as generic interface file for target.
Using /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/config/unix.exp as tool-and-target-specific interface file.
Running /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.exp ...
Executing on host: gcc   -fdiagnostics-color=never -c -o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/temp/20819/ccopts20819.o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/temp/20819/ccopts20819.c    (timeout = 300)
builtin_spawn -ignore SIGHUP gcc -fdiagnostics-color=never -c -o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/temp/20819/ccopts20819.o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/temp/20819/ccopts20819.c
get_compiler_info: gcc-10-2-1
Executing on host: gcc  -fno-stack-protector  -fdiagnostics-color=never -c -g  -o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt0.o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c    (timeout = 300)
builtin_spawn -ignore SIGHUP gcc -fno-stack-protector -fdiagnostics-color=never -c -g -o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt0.o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c
Executing on host: gcc  -fno-stack-protector /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt0.o  -fdiagnostics-color=never -g  -lpthreads -lm   -o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt    (timeout = 300)
builtin_spawn -ignore SIGHUP gcc -fno-stack-protector /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt0.o -fdiagnostics-color=never -g -lpthreads -lm -o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt
/usr/bin/ld: cannot find -lpthreads
collect2: error: ld returned 1 exit status
compiler exited with status 1
output is:
/usr/bin/ld: cannot find -lpthreads
collect2: error: ld returned 1 exit status

Executing on host: gcc  -fno-stack-protector /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt0.o  -fdiagnostics-color=never -g  -lpthread -lm   -o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt    (timeout = 300)
builtin_spawn -ignore SIGHUP gcc -fno-stack-protector /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt0.o -fdiagnostics-color=never -g -lpthread -lm -o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt
PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: successfully compiled posix threads test case
builtin_spawn /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/../../gdb/gdb -nw -nx -iex set height 0 -iex set width 0 -data-directory /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/../data-directory
GNU gdb (GDB) 14.0.50.20230118-git
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
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 "armv7l-unknown-linux-gnueabihf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) set height 0
(gdb) set width 0
(gdb) dir
Reinitialize source path to empty? (y or n) y
Source directories searched: $cdir:$cwd
(gdb) dir /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch
Source directories searched: /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch:$cdir:$cwd
(gdb) kill
The program is not being run.
(gdb) file /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt
Reading symbols from /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt...
(gdb) delete breakpoints
(gdb) info breakpoints
No breakpoints or watchpoints.
(gdb) break -qualified main
Breakpoint 1 at 0x10680: file /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c, line 52.
(gdb) run 
Starting program: /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".

Breakpoint 1, main () at /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c:52
52	  err = pthread_mutex_lock(&mutex);
(gdb) advance 58
[New Thread 0xb6e22440 (LWP 20889)]
main () at /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c:58
58	  err = pthread_join(thread, &ret); // break-line
(gdb) PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: advance to break-line
thread 2
[Switching to thread 2 (Thread 0xb6e22440 (LWP 20889))]
#0  0xb6f8681c in pthread_cond_timedwait@@GLIBC_2.4 () from /lib/arm-linux-gnueabihf/libpthread.so.0
(gdb) PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: thread 2 for svc check
x/i $pc
=> 0xb6f8681c <pthread_cond_timedwait@@GLIBC_2.4+672>:	svc	0x00000000
(gdb) PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: pc points to svc
thread 1
[Switching to thread 1 (Thread 0xb6ffa280 (LWP 20884))]
#0  main () at /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c:58
58	  err = pthread_join(thread, &ret); // break-line
(gdb) PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: thread 1
set debug frame 1
(gdb) PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: set debug frame 1
thread 2
[frame] reinit_frame_cache: generation=141
[frame] reinit_frame_cache: generation=142
[Switching to thread 2 (Thread 0xb6e22440 (LWP 20889))]
[frame] create_sentinel_frame:   -> {level=-1,type=SENTINEL_FRAME,unwinder="sentinel",pc=<unknown>,id={stack=<sentinel>,!code,special=0x0000000000000000},func=<unknown>}
[frame] get_prev_frame_always_1: enter
  [frame] get_prev_frame_always_1: this_frame=-1
  [frame] frame_unwind_arch: next_frame=-1 -> armv6
  [frame] operator==: l={stack=<sentinel>,!code,special=0x0000000000000000}, r={stack=<outer>,!code,special=0x0000000000000000} -> 0
  [frame] get_prev_frame_raw:   -> {level=0,type=<unknown>,unwinder=<unknown>,pc=<unknown>,id=<not computed>,func=<unknown>}
[frame] get_prev_frame_always_1: exit
[frame] frame_unwind_register_value: enter
  [frame] frame_unwind_register_value: frame=-1, regnum=15(pc)
  [frame] frame_unwind_register_value:   -> register=15 bytes=[1c68f8b6]
[frame] frame_unwind_register_value: exit
[frame] frame_unwind_pc: this_frame=-1 -> 0xb6f8681c
[frame] frame_unwind_find_by_frame: enter
  [frame] frame_unwind_find_by_frame: this_frame=0
  [frame] frame_unwind_try_unwinder: trying unwinder "dummy"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "dwarf2 tailcall"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "inline"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "jit"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "python"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "arm stub"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "dwarf2"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "dwarf2 signal"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "arm exidx"
  [frame] frame_unwind_register_value: enter
    [frame] frame_unwind_register_value: frame=-1, regnum=25(cpsr)
    [frame] frame_unwind_register_value:   -> register=25 bytes=[10000080]
  [frame] frame_unwind_register_value: exit
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "arm epilogue"
  [frame] frame_unwind_register_value: enter
    [frame] frame_unwind_register_value: frame=-1, regnum=25(cpsr)
    [frame] frame_unwind_register_value:   -> register=25 bytes=[10000080]
  [frame] frame_unwind_register_value: exit
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "arm prologue"
  [frame] frame_unwind_try_unwinder: yes
[frame] frame_unwind_find_by_frame: exit
#0  0xb6f8681c in pthread_cond_timedwait@@GLIBC_2.4 ([frame] frame_id_p: l={!stack,!code,!special} -> 0
) from /lib/arm-linux-gnueabihf/libpthread.so.0
[frame] get_prev_frame_always_1: enter
  [frame] get_prev_frame_always_1: this_frame=-1
  [frame] get_prev_frame_always_1:   -> {level=0,type=NORMAL_FRAME,unwinder="arm prologue",pc=0xb6f8681c,id=<not computed>,func=<unknown>} // cached
[frame] get_prev_frame_always_1: exit
(gdb) FAIL: gdb.arch/arm-pthread_cond_timedwait-bt.exp: unwinder is arm exidx
thread 2
[frame] reinit_frame_cache: generation=143
[frame] reinit_frame_cache: generation=144
[Switching to thread 2 (Thread 0xb6e22440 (LWP 20889))]
[frame] create_sentinel_frame:   -> {level=-1,type=SENTINEL_FRAME,unwinder="sentinel",pc=<unknown>,id={stack=<sentinel>,!code,special=0x0000000000000000},func=<unknown>}
[frame] get_prev_frame_always_1: enter
  [frame] get_prev_frame_always_1: this_frame=-1
  [frame] frame_unwind_arch: next_frame=-1 -> armv6
  [frame] operator==: l={stack=<sentinel>,!code,special=0x0000000000000000}, r={stack=<outer>,!code,special=0x0000000000000000} -> 0
  [frame] get_prev_frame_raw:   -> {level=0,type=<unknown>,unwinder=<unknown>,pc=<unknown>,id=<not computed>,func=<unknown>}
[frame] get_prev_frame_always_1: exit
[frame] frame_unwind_register_value: enter
  [frame] frame_unwind_register_value: frame=-1, regnum=15(pc)
  [frame] frame_unwind_register_value:   -> register=15 bytes=[1c68f8b6]
[frame] frame_unwind_register_value: exit
[frame] frame_unwind_pc: this_frame=-1 -> 0xb6f8681c
[frame] frame_unwind_find_by_frame: enter
  [frame] frame_unwind_find_by_frame: this_frame=0
  [frame] frame_unwind_try_unwinder: trying unwinder "dummy"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "dwarf2 tailcall"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "inline"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "jit"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "python"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "arm stub"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "dwarf2"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "dwarf2 signal"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "arm exidx"
  [frame] frame_unwind_register_value: enter
    [frame] frame_unwind_register_value: frame=-1, regnum=25(cpsr)
    [frame] frame_unwind_register_value:   -> register=25 bytes=[10000080]
  [frame] frame_unwind_register_value: exit
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "arm epilogue"
  [frame] frame_unwind_register_value: enter
    [frame] frame_unwind_register_value: frame=-1, regnum=25(cpsr)
    [frame] frame_unwind_register_value:   -> register=25 bytes=[10000080]
  [frame] frame_unwind_register_value: exit
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "arm prologue"
  [frame] frame_unwind_try_unwinder: yes
[frame] frame_unwind_find_by_frame: exit
#0  0xb6f8681c in pthread_cond_timedwait@@GLIBC_2.4 ([frame] frame_id_p: l={!stack,!code,!special} -> 0
) from /lib/arm-linux-gnueabihf/libpthread.so.0
[frame] get_prev_frame_always_1: enter
  [frame] get_prev_frame_always_1: this_frame=-1
  [frame] get_prev_frame_always_1:   -> {level=0,type=NORMAL_FRAME,unwinder="arm prologue",pc=0xb6f8681c,id=<not computed>,func=<unknown>} // cached
[frame] get_prev_frame_always_1: exit
(gdb) PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: thread 2 for debug frame check
set debug frame 0
(gdb) PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: set debug frame 0
bt
#0  0xb6f8681c in pthread_cond_timedwait@@GLIBC_2.4 () from /lib/arm-linux-gnueabihf/libpthread.so.0
#1  0xb6e21f80 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) FAIL: gdb.arch/arm-pthread_cond_timedwait-bt.exp: unwind of pthread_cond_timedwait
testcase /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.exp completed in 1 seconds

		=== gdb Summary ===

# of expected passes		8
# of unexpected failures	2
Executing on host: /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/../../gdb/gdb -nw -nx -iex "set height 0" -iex "set width 0" -data-directory /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/../data-directory --version    (timeout = 300)
builtin_spawn -ignore SIGHUP /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/../../gdb/gdb -nw -nx -iex set height 0 -iex set width 0 -data-directory /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/../data-directory --version
GNU gdb (GDB) 14.0.50.20230118-git
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
/home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/gdb version  14.0.50.20230118-git -nw -nx -iex "set height 0" -iex "set width 0" -data-directory /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/../data-directory 

runtest completed at Wed Jan 18 12:34:30 2023
Test run by jenkins on Wed Jan 18 12:36:12 2023
Native configuration is armv7l-unknown-linux-gnueabihf

		=== gdb tests ===

Schedule of variations:
    unix

Running target unix
Using /usr/share/dejagnu/baseboards/unix.exp as board description file for target.
Using /usr/share/dejagnu/config/unix.exp as generic interface file for target.
Using /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/config/unix.exp as tool-and-target-specific interface file.
Running /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.exp ...
Executing on host: gcc   -fdiagnostics-color=never -c -o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/temp/21055/ccopts21055.o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/temp/21055/ccopts21055.c    (timeout = 300)
builtin_spawn -ignore SIGHUP gcc -fdiagnostics-color=never -c -o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/temp/21055/ccopts21055.o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/temp/21055/ccopts21055.c
get_compiler_info: gcc-10-2-1
Executing on host: gcc  -fno-stack-protector  -fdiagnostics-color=never -c -g  -o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt0.o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c    (timeout = 300)
builtin_spawn -ignore SIGHUP gcc -fno-stack-protector -fdiagnostics-color=never -c -g -o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt0.o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c
Executing on host: gcc  -fno-stack-protector /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt0.o  -fdiagnostics-color=never -g  -lpthreads -lm   -o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt    (timeout = 300)
builtin_spawn -ignore SIGHUP gcc -fno-stack-protector /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt0.o -fdiagnostics-color=never -g -lpthreads -lm -o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt
/usr/bin/ld: cannot find -lpthreads
collect2: error: ld returned 1 exit status
compiler exited with status 1
output is:
/usr/bin/ld: cannot find -lpthreads
collect2: error: ld returned 1 exit status

Executing on host: gcc  -fno-stack-protector /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt0.o  -fdiagnostics-color=never -g  -lpthread -lm   -o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt    (timeout = 300)
builtin_spawn -ignore SIGHUP gcc -fno-stack-protector /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt0.o -fdiagnostics-color=never -g -lpthread -lm -o /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt
PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: successfully compiled posix threads test case
builtin_spawn /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/../../gdb/gdb -nw -nx -iex set height 0 -iex set width 0 -data-directory /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/../data-directory
GNU gdb (GDB) 14.0.50.20230118-git
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
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 "armv7l-unknown-linux-gnueabihf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) set height 0
(gdb) set width 0
(gdb) dir
Reinitialize source path to empty? (y or n) y
Source directories searched: $cdir:$cwd
(gdb) dir /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch
Source directories searched: /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch:$cdir:$cwd
(gdb) kill
The program is not being run.
(gdb) file /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt
Reading symbols from /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt...
(gdb) delete breakpoints
(gdb) info breakpoints
No breakpoints or watchpoints.
(gdb) break -qualified main
Breakpoint 1 at 0x10680: file /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c, line 52.
(gdb) run 
Starting program: /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/outputs/gdb.arch/arm-pthread_cond_timedwait-bt/arm-pthread_cond_timedwait-bt 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".

Breakpoint 1, main () at /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c:52
52	  err = pthread_mutex_lock(&mutex);
(gdb) advance 58
[New Thread 0xb6e22440 (LWP 21125)]
main () at /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c:58
58	  err = pthread_join(thread, &ret); // break-line
(gdb) PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: advance to break-line
thread 2
[Switching to thread 2 (Thread 0xb6e22440 (LWP 21125))]
#0  0xb6f8681c in pthread_cond_timedwait@@GLIBC_2.4 () from /lib/arm-linux-gnueabihf/libpthread.so.0
(gdb) PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: thread 2 for svc check
x/i $pc
=> 0xb6f8681c <pthread_cond_timedwait@@GLIBC_2.4+672>:	svc	0x00000000
(gdb) PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: pc points to svc
thread 1
[Switching to thread 1 (Thread 0xb6ffa280 (LWP 21120))]
#0  main () at /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c:58
58	  err = pthread_join(thread, &ret); // break-line
(gdb) PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: thread 1
set debug frame 1
(gdb) PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: set debug frame 1
thread 2
[frame] reinit_frame_cache: generation=147
[frame] reinit_frame_cache: generation=148
[Switching to thread 2 (Thread 0xb6e22440 (LWP 21125))]
[frame] create_sentinel_frame:   -> {level=-1,type=SENTINEL_FRAME,unwinder="sentinel",pc=<unknown>,id={stack=<sentinel>,!code,special=0x0000000000000000},func=<unknown>}
[frame] get_prev_frame_always_1: enter
  [frame] get_prev_frame_always_1: this_frame=-1
  [frame] frame_unwind_arch: next_frame=-1 -> armv6
  [frame] operator==: l={stack=<sentinel>,!code,special=0x0000000000000000}, r={stack=<outer>,!code,special=0x0000000000000000} -> 0
  [frame] get_prev_frame_raw:   -> {level=0,type=<unknown>,unwinder=<unknown>,pc=<unknown>,id=<not computed>,func=<unknown>}
[frame] get_prev_frame_always_1: exit
[frame] frame_unwind_register_value: enter
  [frame] frame_unwind_register_value: frame=-1, regnum=15(pc)
  [frame] frame_unwind_register_value:   -> register=15 bytes=[1c68f8b6]
[frame] frame_unwind_register_value: exit
[frame] frame_unwind_pc: this_frame=-1 -> 0xb6f8681c
[frame] frame_unwind_find_by_frame: enter
  [frame] frame_unwind_find_by_frame: this_frame=0
  [frame] frame_unwind_try_unwinder: trying unwinder "dummy"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "dwarf2 tailcall"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "inline"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "jit"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "python"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "arm stub"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "dwarf2"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "dwarf2 signal"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "arm exidx"
  [frame] frame_unwind_register_value: enter
    [frame] frame_unwind_register_value: frame=-1, regnum=25(cpsr)
    [frame] frame_unwind_register_value:   -> register=25 bytes=[10000080]
  [frame] frame_unwind_register_value: exit
  [frame] frame_unwind_register_value: enter
    [frame] frame_unwind_register_value: frame=-1, regnum=13(sp)
    [frame] frame_unwind_register_value:   -> register=13 bytes=[901de2b6]
  [frame] frame_unwind_register_value: exit
  [frame] frame_unwind_register_value: enter
    [frame] frame_unwind_register_value: frame=-1, regnum=13(sp)
    [frame] frame_unwind_register_value:   -> register=13 bytes=[901de2b6]
  [frame] frame_unwind_register_value: exit
  [frame] frame_unwind_register_value: enter
    [frame] frame_unwind_register_value: frame=-1, regnum=13(sp)
    [frame] frame_unwind_register_value:   -> register=13 bytes=[901de2b6]
  [frame] frame_unwind_register_value: exit
  [frame] frame_unwind_register_value: enter
    [frame] frame_unwind_register_value: frame=-1, regnum=13(sp)
    [frame] frame_unwind_register_value:   -> register=13 bytes=[901de2b6]
  [frame] frame_unwind_register_value: exit
  [frame] frame_unwind_try_unwinder: yes
[frame] frame_unwind_find_by_frame: exit
#0  0xb6f8681c in pthread_cond_timedwait@@GLIBC_2.4 ([frame] frame_id_p: l={!stack,!code,!special} -> 0
) from /lib/arm-linux-gnueabihf/libpthread.so.0
[frame] get_prev_frame_always_1: enter
  [frame] get_prev_frame_always_1: this_frame=-1
  [frame] get_prev_frame_always_1:   -> {level=0,type=NORMAL_FRAME,unwinder="arm exidx",pc=0xb6f8681c,id=<not computed>,func=<unknown>} // cached
[frame] get_prev_frame_always_1: exit
(gdb) PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: unwinder is arm exidx
thread 2
[frame] reinit_frame_cache: generation=149
[frame] reinit_frame_cache: generation=150
[Switching to thread 2 (Thread 0xb6e22440 (LWP 21125))]
[frame] create_sentinel_frame:   -> {level=-1,type=SENTINEL_FRAME,unwinder="sentinel",pc=<unknown>,id={stack=<sentinel>,!code,special=0x0000000000000000},func=<unknown>}
[frame] get_prev_frame_always_1: enter
  [frame] get_prev_frame_always_1: this_frame=-1
  [frame] frame_unwind_arch: next_frame=-1 -> armv6
  [frame] operator==: l={stack=<sentinel>,!code,special=0x0000000000000000}, r={stack=<outer>,!code,special=0x0000000000000000} -> 0
  [frame] get_prev_frame_raw:   -> {level=0,type=<unknown>,unwinder=<unknown>,pc=<unknown>,id=<not computed>,func=<unknown>}
[frame] get_prev_frame_always_1: exit
[frame] frame_unwind_register_value: enter
  [frame] frame_unwind_register_value: frame=-1, regnum=15(pc)
  [frame] frame_unwind_register_value:   -> register=15 bytes=[1c68f8b6]
[frame] frame_unwind_register_value: exit
[frame] frame_unwind_pc: this_frame=-1 -> 0xb6f8681c
[frame] frame_unwind_find_by_frame: enter
  [frame] frame_unwind_find_by_frame: this_frame=0
  [frame] frame_unwind_try_unwinder: trying unwinder "dummy"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "dwarf2 tailcall"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "inline"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "jit"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "python"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "(null)"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "arm stub"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "dwarf2"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "dwarf2 signal"
  [frame] frame_unwind_try_unwinder: no
  [frame] frame_unwind_try_unwinder: trying unwinder "arm exidx"
  [frame] frame_unwind_register_value: enter
    [frame] frame_unwind_register_value: frame=-1, regnum=25(cpsr)
    [frame] frame_unwind_register_value:   -> register=25 bytes=[10000080]
  [frame] frame_unwind_register_value: exit
  [frame] frame_unwind_register_value: enter
    [frame] frame_unwind_register_value: frame=-1, regnum=13(sp)
    [frame] frame_unwind_register_value:   -> register=13 bytes=[901de2b6]
  [frame] frame_unwind_register_value: exit
  [frame] frame_unwind_register_value: enter
    [frame] frame_unwind_register_value: frame=-1, regnum=13(sp)
    [frame] frame_unwind_register_value:   -> register=13 bytes=[901de2b6]
  [frame] frame_unwind_register_value: exit
  [frame] frame_unwind_register_value: enter
    [frame] frame_unwind_register_value: frame=-1, regnum=13(sp)
    [frame] frame_unwind_register_value:   -> register=13 bytes=[901de2b6]
  [frame] frame_unwind_register_value: exit
  [frame] frame_unwind_register_value: enter
    [frame] frame_unwind_register_value: frame=-1, regnum=13(sp)
    [frame] frame_unwind_register_value:   -> register=13 bytes=[901de2b6]
  [frame] frame_unwind_register_value: exit
  [frame] frame_unwind_try_unwinder: yes
[frame] frame_unwind_find_by_frame: exit
#0  0xb6f8681c in pthread_cond_timedwait@@GLIBC_2.4 ([frame] frame_id_p: l={!stack,!code,!special} -> 0
) from /lib/arm-linux-gnueabihf/libpthread.so.0
[frame] get_prev_frame_always_1: enter
  [frame] get_prev_frame_always_1: this_frame=-1
  [frame] get_prev_frame_always_1:   -> {level=0,type=NORMAL_FRAME,unwinder="arm exidx",pc=0xb6f8681c,id=<not computed>,func=<unknown>} // cached
[frame] get_prev_frame_always_1: exit
(gdb) PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: thread 2 for debug frame check
set debug frame 0
(gdb) PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: set debug frame 0
bt
#0  0xb6f8681c in pthread_cond_timedwait@@GLIBC_2.4 () from /lib/arm-linux-gnueabihf/libpthread.so.0
#1  0x00010648 in fun (arg=0x0) at /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c:38
#2  0xb6f7e300 in start_thread () from /lib/arm-linux-gnueabihf/libpthread.so.0
#3  0xb6f02208 in ?? () from /lib/arm-linux-gnueabihf/libc.so.6
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: unwind of pthread_cond_timedwait
testcase /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.exp completed in 2 seconds

		=== gdb Summary ===

# of expected passes		10
Executing on host: /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/../../gdb/gdb -nw -nx -iex "set height 0" -iex "set width 0" -data-directory /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/../data-directory --version    (timeout = 300)
builtin_spawn -ignore SIGHUP /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/../../gdb/gdb -nw -nx -iex set height 0 -iex set width 0 -data-directory /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/../data-directory --version
GNU gdb (GDB) 14.0.50.20230118-git
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
/home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/gdb version  14.0.50.20230118-git -nw -nx -iex "set height 0" -iex "set width 0" -data-directory /home/ezulu/jenkins_workspaces/rpi4-05/jkratochvil/binutils-gdb/gdb/testsuite/../data-directory 

runtest completed at Wed Jan 18 12:36:14 2023
  
Luis Machado Jan. 18, 2023, 2:22 p.m. UTC | #3
Hi Jan,

On 1/18/23 11:51, Jan Kratochvil wrote:
> Hi Luis,
> 
> On Tue, 17 Jan 2023 19:14:01 +0800, Luis Machado wrote:
>> I see the same results with a patched and unpatched gdb:
>>
>> PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: successfully compiled posix threads test case
>> PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: advance to break-line
>> PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: thread 2 for svc check
>> UNTESTED: gdb.arch/arm-pthread_cond_timedwait-bt.exp: pc points to svc
>>
>> Do you see something different?
> 
> Yes, on Raspbian 11 (bullseye), Linux version 5.15.32-v7l+, Raspberry 4.
> 
> What OS do you run?

I'm on Ubuntu 22.04/20.04, but running 32-bit on a 64-bit system via Docker. There seems to be a divergence in the
expected pattern of the svc instruction.

I see the following:

x/i $pc
=> 0xf7eadb04 <__libc_do_syscall+4>:    svc     0

The test seems to be expecting a pattern of

x/i $pc
=> 0xf7eadb04 <__libc_do_syscall+4>:    svc     0x00000000

If I replaced the pattern to force a match, the test continues until the unwinder check. Then it runs into a
UNTESTED again because I see the dwarf2 unwinder being used.

That may be because I have debug info installed I suppose. I wonder if there is a way to force gdb not to use the
dwarf2 unwinder for libc, even if it is available on the system.

> 
> There is the unfortunate dependency on system pthread_cond_timedwait()
> implementation. The testcase could provide also its own .S implementation but
> then it could be incompatible with the rest of system glibc.
> 
> 
> Jan
  
Jan Kratochvil Jan. 19, 2023, 3:15 a.m. UTC | #4
On Wed, 18 Jan 2023 22:22:51 +0800, Luis Machado wrote:
> I'm on Ubuntu 22.04/20.04, but running 32-bit on a 64-bit system via Docker.

Ubuntu is the host OS. But I haven't found recent armv7 (32-bit) Ubuntu.
What is the Docker container you use?


> x/i $pc
> => 0xf7eadb04 <__libc_do_syscall+4>:    svc     0
> 
> The test seems to be expecting a pattern of
> 
> x/i $pc
> => 0xf7eadb04 <__libc_do_syscall+4>:    svc     0x00000000
> 
> If I replaced the pattern to force a match, the test continues until the unwinder check.

I forgot to update this pattern but it would not help the testcase anyway.
The purpose is to stop in the function pthread_cond_timedwait.
Here it stops in function __libc_do_syscall.
It would be helpful at least a backtrace but I would more like to reproduce
your environment.


> Then it runs into a
> UNTESTED again because I see the dwarf2 unwinder being used.
> 
> That may be because I have debug info installed I suppose. I wonder if there
> is a way to force gdb not to use the dwarf2 unwinder for libc, even if it is
> available on the system.

I have fixed that part:
	gdb_test_no_output "set debug-file-directory" ""


Thanks,
Jan
  
Luis Machado Jan. 20, 2023, 5:41 p.m. UTC | #5
On 1/19/23 03:15, Jan Kratochvil wrote:
> On Wed, 18 Jan 2023 22:22:51 +0800, Luis Machado wrote:
>> I'm on Ubuntu 22.04/20.04, but running 32-bit on a 64-bit system via Docker.
> 
> Ubuntu is the host OS. But I haven't found recent armv7 (32-bit) Ubuntu.
> What is the Docker container you use?

It is a custom one built with Ubuntu 22.04/20.04 images/packages.

> 
> 
>> x/i $pc
>> => 0xf7eadb04 <__libc_do_syscall+4>:    svc     0
>>
>> The test seems to be expecting a pattern of
>>
>> x/i $pc
>> => 0xf7eadb04 <__libc_do_syscall+4>:    svc     0x00000000
>>
>> If I replaced the pattern to force a match, the test continues until the unwinder check.
> 
> I forgot to update this pattern but it would not help the testcase anyway.
> The purpose is to stop in the function pthread_cond_timedwait.
> Here it stops in function __libc_do_syscall.
> It would be helpful at least a backtrace but I would more like to reproduce
> your environment.

I've attached a gdb.log file. Hopefully that will bring some light. Please note I used
"nosharedlibrary" to remove the symbols for my test.

> 
> 
>> Then it runs into a
>> UNTESTED again because I see the dwarf2 unwinder being used.
>>
>> That may be because I have debug info installed I suppose. I wonder if there
>> is a way to force gdb not to use the dwarf2 unwinder for libc, even if it is
>> available on the system.
> 
> I have fixed that part:
> 	gdb_test_no_output "set debug-file-directory" ""

For my case, it looks like gdb will still find the symbols. The command "nosharedlibrary" will
drop the symbols completely though. But then I see the prologue unwinders being used instead of the
exception frame.

> 
> 
> Thanks,
> Jan
  
Jan Kratochvil Feb. 24, 2023, 1:38 p.m. UTC | #6
On Sat, 21 Jan 2023 01:41:00 +0800, Luis Machado wrote:
> I've attached a gdb.log file. Hopefully that will bring some light. Please note I used
> "nosharedlibrary" to remove the symbols for my test.

I think that was the problem. With "nosharedlibrary" even the exidx section is
not read.

Could you test the v3 patch I have sent along?


Thanks,
Jan
  
Luis Machado Feb. 24, 2023, 4:56 p.m. UTC | #7
Hi,

On 2/24/23 13:38, Jan Kratochvil wrote:
> On Sat, 21 Jan 2023 01:41:00 +0800, Luis Machado wrote:
>> I've attached a gdb.log file. Hopefully that will bring some light. Please note I used
>> "nosharedlibrary" to remove the symbols for my test.
> 
> I think that was the problem. With "nosharedlibrary" even the exidx section is
> not read.
> 
> Could you test the v3 patch I have sent along?

I gave this a try across Ubuntu 22.04/20.04 and aarch64/arm. All of them run like so:

PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: advance breakhere
UNTESTED: gdb.arch/arm-pthread_cond_timedwait-bt.exp: pc points to svc
PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: successfully compiled posix threads test case
PASS: gdb.arch/arm-pthread_cond_timedwait-bt.exp: thread 2 for svc check

Is that what you were expecting to see?
  
Jan Kratochvil Feb. 25, 2023, 10:04 a.m. UTC | #8
Hi Luis,

On Sat, 25 Feb 2023 00:56:12 +0800, Luis Machado wrote:
> I gave this a try across Ubuntu 22.04/20.04 and aarch64/arm. All of them run like so:
> 
> UNTESTED: gdb.arch/arm-pthread_cond_timedwait-bt.exp: pc points to svc
> 
> Is that what you were expecting to see?

unfortunately not but could you give the v4 patch a try? A single host should
be enough. I am not sure why my machine disassembles as "svc 0x00000000" while
yours as "svc 0", I did not investigate it more.


Thanks,
Jan
  
Jan Kratochvil March 20, 2023, 12:51 p.m. UTC | #9
[PATCH v4] gdb/arm: Fix backtrace for pthread_cond_timedwait
https://sourceware.org/pipermail/gdb-patches/2023-February/197413.html

Hi Luis,

On Sat, 25 Feb 2023 00:56:12 +0800, Luis Machado wrote:
> I gave this a try across Ubuntu 22.04/20.04 and aarch64/arm. All of them run like so:
> 
> UNTESTED: gdb.arch/arm-pthread_cond_timedwait-bt.exp: pc points to svc
> 
> Is that what you were expecting to see?

unfortunately not but could you give the v4 patch a try? A single host should
be enough. I am not sure why my machine disassembles as "svc 0x00000000" while
yours as "svc 0", I did not investigate it more.


Thanks,
Jan
  
Luis Machado March 30, 2023, 2:30 p.m. UTC | #10
On 3/20/23 12:51, Jan Kratochvil wrote:
> [PATCH v4] gdb/arm: Fix backtrace for pthread_cond_timedwait
> https://sourceware.org/pipermail/gdb-patches/2023-February/197413.html
> 
> Hi Luis,
> 
> On Sat, 25 Feb 2023 00:56:12 +0800, Luis Machado wrote:
>> I gave this a try across Ubuntu 22.04/20.04 and aarch64/arm. All of them run like so:
>>
>> UNTESTED: gdb.arch/arm-pthread_cond_timedwait-bt.exp: pc points to svc
>>
>> Is that what you were expecting to see?
> 
> unfortunately not but could you give the v4 patch a try? A single host should
> be enough. I am not sure why my machine disassembles as "svc 0x00000000" while
> yours as "svc 0", I did not investigate it more.

Sure. I'll give it a try and we'll let you know.

> 
> 
> Thanks,
> Jan
  
Luis Machado March 30, 2023, 4:09 p.m. UTC | #11
On 3/30/23 15:30, Luis Machado wrote:
> On 3/20/23 12:51, Jan Kratochvil wrote:
>> [PATCH v4] gdb/arm: Fix backtrace for pthread_cond_timedwait
>> https://sourceware.org/pipermail/gdb-patches/2023-February/197413.html
>>
>> Hi Luis,
>>
>> On Sat, 25 Feb 2023 00:56:12 +0800, Luis Machado wrote:
>>> I gave this a try across Ubuntu 22.04/20.04 and aarch64/arm. All of them run like so:
>>>
>>> UNTESTED: gdb.arch/arm-pthread_cond_timedwait-bt.exp: pc points to svc
>>>
>>> Is that what you were expecting to see?
>>
>> unfortunately not but could you give the v4 patch a try? A single host should
>> be enough. I am not sure why my machine disassembles as "svc 0x00000000" while
>> yours as "svc 0", I did not investigate it more.
> 
> Sure. I'll give it a try and we'll let you know.
> 
>>
>>
>> Thanks,
>> Jan
> 

I gave this a try and I get full PASSes now (10 of them). For aarch64 we bail out eventually
and report an untested case.

This looks good to me, but you'll need to adjust the copyright years and remove the template section
in the testcase:

+# This serves as a template for writing new test cases.  Replace this with
+# a description of what this test case tests.

Sorry for the late reply.

Thanks,
Luis
  
Jan Kratochvil April 1, 2023, 1:49 p.m. UTC | #12
On Fri, 31 Mar 2023 00:09:59 +0800, Luis Machado wrote:
> This looks good to me, but you'll need to adjust the copyright years and
> remove the template section in the testcase:

Checked-in, updated:
	https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=3026cdbdde0e1937f811b52ba18fe3fbb1419ef9


Thanks,
Jan
  

Patch

diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 78a2fe2ade5..328eb17f419 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -3116,26 +3116,34 @@  arm_exidx_unwind_sniffer (const struct frame_unwind *self,
 	  && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME)
 	exc_valid = 1;
 
-      /* We also assume exception information is valid if we're currently
-	 blocked in a system call.  The system library is supposed to
-	 ensure this, so that e.g. pthread cancellation works.  */
-      if (arm_frame_is_thumb (this_frame))
+      /* Some syscalls keep PC pointing to the SVC instruction itself.  */
+      for (int shift = 0; shift <= 1 && !exc_valid; ++shift)
 	{
-	  ULONGEST insn;
+	  /* We also assume exception information is valid if we're currently
+	     blocked in a system call.  The system library is supposed to
+	     ensure this, so that e.g. pthread cancellation works.  */
+	  if (arm_frame_is_thumb (this_frame))
+	    {
+	      ULONGEST insn;
 
-	  if (safe_read_memory_unsigned_integer (get_frame_pc (this_frame) - 2,
-						 2, byte_order_for_code, &insn)
-	      && (insn & 0xff00) == 0xdf00 /* svc */)
-	    exc_valid = 1;
-	}
-      else
-	{
-	  ULONGEST insn;
+	      if (safe_read_memory_unsigned_integer ((get_frame_pc (this_frame)
+						      - (shift ? 2 : 0)),
+						     2, byte_order_for_code,
+						     &insn)
+		  && (insn & 0xff00) == 0xdf00 /* svc */)
+		exc_valid = 1;
+	    }
+	  else
+	    {
+	      ULONGEST insn;
 
-	  if (safe_read_memory_unsigned_integer (get_frame_pc (this_frame) - 4,
-						 4, byte_order_for_code, &insn)
-	      && (insn & 0x0f000000) == 0x0f000000 /* svc */)
-	    exc_valid = 1;
+	      if (safe_read_memory_unsigned_integer ((get_frame_pc (this_frame)
+						      - (shift ? 4 : 0)),
+						     4, byte_order_for_code,
+						     &insn)
+		  && (insn & 0x0f000000) == 0x0f000000 /* svc */)
+		exc_valid = 1;
+	    }
 	}
 	
       /* Bail out if we don't know that exception information is valid.  */
diff --git a/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c b/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c
new file mode 100644
index 00000000000..c382a100afd
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c
@@ -0,0 +1,62 @@ 
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 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 <pthread.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <assert.h>
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+static void *fun(void *arg)
+{
+  struct timeval now;
+  struct timespec until;
+  int err;
+
+  err = gettimeofday(&now, NULL);
+  assert(!err);
+
+  until.tv_sec = now.tv_sec + 60;
+  until.tv_nsec = now.tv_usec * 1000UL;
+
+  pthread_cond_timedwait(&cond, &mutex, &until);
+  assert(0);
+  err = pthread_mutex_unlock(&mutex);
+  assert(!err);
+
+  return arg;
+}
+
+int main()
+{
+  pthread_t thread;
+  void *ret;
+  int err;
+
+  err = pthread_mutex_lock(&mutex);
+  assert(!err);
+  err = pthread_create(&thread, NULL, fun, NULL);
+  assert(!err);
+  err = pthread_mutex_lock(&mutex);
+  assert(!err);
+  err = pthread_join(thread, &ret); // break-line
+  assert(0);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.exp b/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.exp
new file mode 100644
index 00000000000..d5e594c73d5
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.exp
@@ -0,0 +1,105 @@ 
+# Copyright 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/>.
+
+# This serves as a template for writing new test cases.  Replace this with
+# a description of what this test case tests.
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
+			  {debug pthreads}] } {
+    return
+}
+
+if { ![runto_main] } {
+    return
+}
+
+gdb_test "advance [gdb_get_line_number "break-line"]" "break-line.*" \
+	 "advance to break-line"
+
+gdb_test "thread 2" "Switching to thread 2 .*" "thread 2 for svc check"
+
+# 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.
+set test "pc points to svc"
+gdb_test_multiple {x/i $pc} $test {
+    -re ":\tsvc\t0x00000000\r\n$gdb_prompt $" {
+	pass $test
+    }
+    -re "\r\n$gdb_prompt $" {
+	untested $test
+	return
+    }
+}
+
+gdb_test "thread 1" "Switching to thread 1 .*"
+gdb_test_no_output "set debug frame 1"
+
+# PASS:
+#  [frame] frame_unwind_try_unwinder: trying unwinder "arm exidx"
+#  [frame] frame_unwind_register_value: enter
+#...
+#  [frame] frame_unwind_register_value: exit
+#  [frame] frame_unwind_try_unwinder: yes
+#...
+#  [frame] get_prev_frame_always_1:   -> {level=0,type=NORMAL_FRAME,unwinder="arm exidx",pc=0xb6f8681c,id=<not computed>,func=<unknown>} // cached
+
+# FAIL:
+#  [frame] frame_unwind_try_unwinder: trying unwinder "arm exidx"
+#  [frame] frame_unwind_register_value: enter
+#...
+#  [frame] frame_unwind_register_value: exit
+#  [frame] frame_unwind_try_unwinder: no
+#  [frame] frame_unwind_try_unwinder: trying unwinder "arm epilogue"
+#  [frame] frame_unwind_register_value: enter
+#...
+#  [frame] frame_unwind_register_value: exit
+#  [frame] frame_unwind_try_unwinder: no
+#  [frame] frame_unwind_try_unwinder: trying unwinder "arm prologue"
+#  [frame] frame_unwind_try_unwinder: yes
+#...
+#  [frame] get_prev_frame_always_1:   -> {level=0,type=NORMAL_FRAME,unwinder="arm prologue",pc=0xb6f8681c,id=<not computed>,func=<unknown>} // cached
+
+set test "unwinder is arm exidx"
+# Switch the threads to reset frame cache.
+gdb_test_multiple {thread 2} $test {
+    -re "\{level=0,type=NORMAL_FRAME,unwinder=\"arm exidx\",pc=.*\r\n$gdb_prompt $" {
+	pass $test
+    }
+    -re "\{level=0,type=NORMAL_FRAME,unwinder=\"arm prologue\",pc=.*\r\n$gdb_prompt $" {
+	fail $test
+    }
+    -re "\r\n$gdb_prompt $" {
+	untested $test
+	return
+    }
+}
+
+gdb_test "thread 2" "Switching to thread 2 .*" "thread 2 for debug frame check"
+
+gdb_test_no_output "set debug frame 0"
+
+# PASS:
+# #0  0xb6f8681c in pthread_cond_timedwait@@GLIBC_2.4 () from /lib/arm-linux-gnueabihf/libpthread.so.0
+# #1  0x00010648 in fun (arg=0x0) at .../gdb/testsuite/gdb.arch/arm-pthread_cond_timedwait-bt.c:38
+# ...
+
+# FAIL:
+# #0  0xb6f8681c in pthread_cond_timedwait@@GLIBC_2.4 () from /lib/arm-linux-gnueabihf/libpthread.so.0
+# #1  0xb6e21f80 in ?? ()
+# Backtrace stopped: previous frame identical to this frame (corrupt stack?)
+
+gdb_test "bt" { in fun \(arg=.*} "unwind of pthread_cond_timedwait"