[prev in list] [next in list] [prev in thread] [next in thread]
List: netbsd-port-arm
Subject: [PATCH] - gdb crashes in call command.
From: Gopikrishnan S <gokrix () yahoo ! com>
Date: 2019-09-25 21:07:26
Message-ID: 909128281.6768892.1569445646516 () mail ! yahoo ! com
[Download RAW message or body]
------=_Part_6768891_1887562626.1569445646515
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
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)=
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic