Port-arm archive

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

[PATCH] - gdb crashes in call command.




Hello,

I have NetBSD 8.99.51 running on a Raspberry Pi 3B. When invoking a function in the inferior from the gdb command line with the call command gdb crashes:

Reading symbols from test...
(gdb) b main
Breakpoint 1 at 0x106f0: file test.c, line 13.
(gdb) r
Starting program: /home/gopikris/C/test 
 
Breakpoint 1, main () at test.c:13
13              printf("Hello, World!\n");
(gdb) li 0
1       #include <stdlib.h>
2       #include <stdio.h>
3
4       static int m = 10;
5
6       int func(int p)
7       {
8               return m + p;
9       }
10
(gdb)
11      int main(void)
12      {
13              printf("Hello, World!\n");
14              return EXIT_SUCCESS;
15      }
(gdb) call func(1)
[ 547105.5763672] sorry, pid 10467 was killed: orphaned traced process
Segmentation fault (core dumped)

We never get a proper stack-trace for this crash, since the crash is caused by a stack corruption as described below.


I debugged this and found out that gdb was crashing in the function regcache::restore() in regcache.c, in the 19th iteration of the following loop:

 /* Copy over any registers, being careful to only restore those that
     were both saved and need to be restored.  The full [0 .. gdbarch_num_regs
     + gdbarch_num_pseudo_regs) range is checked since some architectures need
     to save/restore `cooked' registers that live in memory.  */
  for (regnum = 0; regnum < m_descr->nr_cooked_registers; regnum++)
    {
      if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup))
    {
      if (src->m_register_status[regnum] == REG_VALID)
        cooked_write (regnum, src->register_buffer (regnum));
    }
    }
The loop executes from regnum == 0 to regnum == 90, since m_descr->nr_cooked_registers is 91, by virtue of the constant ARM_NUM_REGS in the enum gdb_regnum in arch/arm.h being 91.

cooked_write() ultimately calls arm_nbsd_nat_target::store_registers() with regno == 19, which in turn passes this regno to store_register().

In store_reg() the default case (cases other than special registers like cpsr, sp, lr, and pc) is to update the regno-th member of the array regs.r. But for arm, regs.r is an array of length 13 and so when regno is greater than 12 this overwrites various parts of the stack. In particular, it overwrites the area of the stack where the r11 register is stored at function entry, and thus at function exit gdb goes off into the weeds with a wrong pc.

The solution in the patch pasted below is for arm_nbsd_nat_target::store_registers() to call store_register() only when we know that regnum corresponds to a register defined in struct reg, i.e., only when the regnum corresponds to ARM_A1_REGNUM (reg.r[0]) to ARM_PC_REGNUM(reg.r_pc) and for ARM_PS_REGNUM (reg.r_cpsr).

A corresponding change has been made in fetch_registers as well.

This change applies only to the NetBSD version of gdb. The upstream code is subtly different and thus does not have this bug (but may have other bugs)


Home | Main Index | Thread Index | Old Index