#916910 gdb: Hardware watchpoints do not trigger on i.MX6 (armhf)

Package:
gdb
Source:
gdb
Description:
GNU Debugger
Submitter:
Bob Ham
Date:
2018-12-20 12:03:04 UTC
Severity:
normal
#916910#5
Date:
2018-12-20 11:05:33 UTC
From:
To:
Dear Maintainer,

I'm trying to debug a complex program and came across this
reproducible behaviour.  On an i.MX6 QuadPlus CPU (Boundary Devices
Nitrogen6_Max board) hardware watchpoints are not triggered in my
complex case and in a trivial test case:

============= t.c =============
#include <stdio.h>

int main ()
{
  int a = 1;

  a = 2;

  printf("a: %i\n", a);

  return 0;
}
===============================


Compiled with `cc -g -O0 t.c -o t' using GCC (version (Debian
6.3.0-18+deb9u1) 6.3.0 20170516) on an amd64 box gives the following
successful triggers:

===============================
(gdb) l
1       #include <stdio.h>
2
3       int main ()
4       {
5         int a = 1;
6
7         a = 2;
8
9         printf("a: %i\n", a);
10
(gdb)
11        return 0;
12      }
(gdb) break 5
Breakpoint 1 at 0x6b8: file t.c, line 5.
(gdb) run
Starting program: /store-f/rah/proj/gdb-watchpoint/t
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main () at t.c:5
5         int a = 1;
(gdb) p &a
$1 = (int *) 0x7fffffffe08c
(gdb) watch *0x7fffffffe08c
Hardware watchpoint 2: *0x7fffffffe08c
(gdb) c
Continuing.

Hardware watchpoint 2: *0x7fffffffe08c

Old value = 0
New value = 1
main () at t.c:7
7         a = 2;
(gdb) c
Continuing.

Hardware watchpoint 2: *0x7fffffffe08c

Old value = 1
New value = 2
main () at t.c:9
9         printf("a: %i\n", a);
(gdb) c
Continuing.
a: 2
===============================


However, compiling with GCC (version (Debian 8.2.0-12) 8.2.0) on the
i.MX6 board results in no trigger:

===============================
(gdb) break 5
Breakpoint 1 at 0x512: file t.c, line 5.
(gdb) run
Starting program: /srv/proj/chive/gdb-watchpoint/t

Breakpoint 1, main () at t.c:5
5         int a = 1;
(gdb) p &a
$1 = (int *) 0xbefff46c
(gdb) watch *0xbefff46c
Hardware watchpoint 2: *0xbefff46c
(gdb) c
Continuing.
a: 2
[Inferior 1 (process 1435) exited normally]
===============================


The program contains writes to the `a' variable, as shown in the
following assembler extract:

===============================
 516:   2302            movs    r3, #2
 518:   607b            str     r3, [r7, #4]
===============================

from the disassembled main function:

===============================
0000050c <main>:
 50c:   b580            push    {r7, lr}
 50e:   b082            sub     sp, #8
 510:   af00            add     r7, sp, #0
 512:   2301            movs    r3, #1
 514:   607b            str     r3, [r7, #4]
 516:   2302            movs    r3, #2
 518:   607b            str     r3, [r7, #4]
 51a:   6879            ldr     r1, [r7, #4]
 51c:   4b04            ldr     r3, [pc, #16]   ; (530 <main+0x24>)
 51e:   447b            add     r3, pc
 520:   4618            mov     r0, r3
 522:   f7ff ef54       blx     3cc <printf@plt>
 526:   2300            movs    r3, #0
 528:   4618            mov     r0, r3
 52a:   3708            adds    r7, #8
 52c:   46bd            mov     sp, r7
 52e:   bd80            pop     {r7, pc}
 530:   00000062        .word   0x00000062
===============================


and as demonstrated in the following transcript:

===============================
(gdb) break 5
Breakpoint 1 at 0x512: file t.c, line 5.
(gdb) run
Starting program: /srv/proj/chive/gdb-watchpoint/t

Breakpoint 1, main () at t.c:5
5         int a = 1;
(gdb) p &a
$1 = (int *) 0xbefff46c
(gdb) watch *0xbefff46c
Hardware watchpoint 2: *0xbefff46c
(gdb) display /x *((int *) 0xbefff46c)
1: /x *((int *) 0xbefff46c) = 0x0
(gdb) n
7         a = 2;
1: /x *((int *) 0xbefff46c) = 0x1
(gdb) n
9         printf("a: %i\n", a);
1: /x *((int *) 0xbefff46c) = 0x2
(gdb) c
Continuing.
a: 2
[Inferior 1 (process 1484) exited normally]
===============================


Regards,

Bob Ham