Re: [PATCH] parisc: Improve ptrace support for gdb single-step

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 29-Dec-12, at 8:31 AM, Carlos O'Donell wrote:


On Dec 28, 2012 6:18 PM, "John David Anglin" <dave.anglin@xxxxxxxx> wrote:
>
> Various GCC tests use gdb to simulate a multithreaded application. Many
> of these tests have been failing on parisc linux.
>
> GCC does this by using gdb to single-step the application, then gdb is used to > call other test specific code. Where this fails is when the application is stepped > into the delay slot of a taken branch. This sets the PSW B bit. When the test > specific code is executed, this usually clears the PSW B bit. Currently, gdb is > not allowed to set the B bit. So, the code falls through what should be a taken
> branch.

How exactly does this trigger? Step into delay slot, then what, call an inferior function, then resume?

Yes.

I have attached a test case and gdb script which show bug.

Compile testcase with something like the following:
Executing on host: /home/dave/gnu/gcc/objdir/gcc/xgcc -B/home/dave/gnu/ gcc/objdir/gcc/ /home/dave/gnu/gcc/gcc/gcc/testsuite/gcc.dg/simulate- thread/speculative-store-4.c -fno-diagnostics-show-caret -O0 -g -- param allow-store-data-races=0 -lm -o speculative-store-4.exe

Execute with something like:
gdb -nx -nw -x /home/dave/gnu/gcc/gcc/gcc/testsuite/gcc.dg/simulate- thread/simulate-thread.gdb ./speculative-store-4.exe

You can see that the gdb script executes inferior functions to simulate thread behavior and to determine
whether the test is done.

I debugged this by adding extra print and disp statements to the kernel, gdb and the gdb script.

According to the PA 2.0 arch, a non sequential iaoq queue without the B bit being set invokes undefined behavior. Possibly, this should be checked for when the return is setup after pt_regs_ok. However, I think it is ok to let gdb play with the B bit. See the definition of USER_PSW_MASK in psw.h:

#define USER_PSW_MASK (WIDE_PSW | PSW_T | PSW_N | PSW_X | PSW_B | PSW_V | PSW_CB)

This defines the PSW bits that the user can change using exception support. Probably, the two sets
should be the same.

> The attached patch adds the PSW B bit to the set of bits that gdb is allowed to > set. In order to set the B bit, the trace system call must return using an interrupt > restore. The patch also modifies this code to use the saved IAOQ values when
> they are saved by a ptrace syscall or interruption.
>
> Signed-off-by: John David Anglin <dave.anglin@xxxxxxxx>

What testing did you do with patch?

I have been running the change with 3.7.x kernels for a couple of weeks. I checked that strace still works and GCC test results for tests using gdb are now similar to the results on hpux.

I believe gdb still has problems regarding delay slots, PSW bits and inferior function calls. This mainly shows up in the GCC guality tests. Of course, there are hundreds of FAILs in the gdb testsuite...

Dave
--
John David Anglin	dave.anglin@xxxxxxxx


/* { dg-do link } */
/* { dg-options "--param allow-store-data-races=0" } */
/* { dg-final { simulate-thread } } */

#include <stdio.h>
#include <stdlib.h>

#include "simulate-thread.h"

/* PR 54139 */
/* Test that speculative stores do not happen for --param
   allow-store-data-races=0.  */

int g_13=1, insns=1;

__attribute__((noinline))
void simulate_thread_main()
{
  int l_245;

  /* Since g_13 is unilaterally set positive above, there should be
     no store to g_13 below.  */
  for (l_245 = 0; l_245 <= 1; l_245 += 1)
    for (; g_13 <= 0; g_13 = 1)
      ;
}

int main()
{
  simulate_thread_main ();
  simulate_thread_done ();
  return 0;
}

void simulate_thread_other_threads ()
{
  ++g_13;
  ++insns;
}

int simulate_thread_step_verify ()
{
  return 0;
}

int simulate_thread_final_verify ()
{
  if (g_13 != insns)
    {
      printf("FAIL: g_13 was incorrectly cached\n");
      return 1;
    }
  return 0;
}
set height 0
break simulate_thread_main
# disp/i $pc
run

set $ret = 0
while (simulate_thread_fini != 1) && (! $ret)
  set $ret |= simulate_thread_wrapper_other_threads()
  stepi
  set $ret |= simulate_thread_step_verify()
end

if (! $ret)
  set $ret |= simulate_thread_wrapper_final_verify()
end
continue
quit $ret

[Index of Archives]     [Linux SoC]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux