Re: ping: [patch] aarch64: PR 19806: watchpoints: false negatives + PR 20207 contiguous ones

Jan Kratochvil
2018-04-26T20:12:24Z

[-- Attachment #1: Type: text/plain, Size: 4293 bytes --]

On Fri, 20 Apr 2018 16:49:39 +0200, Pedro Alves wrote:
> ~~~~~~~~~~~~
> Previously, when the hardware reported a watchpoint hit on an address
> that did not match our watchpoint (this happens in case of instructions
> which access large chunks of memory such as "stp") the process would
> enter a loop where we would be continually resuming it (because we did
> not recognise that watchpoint hit) and it would keep hitting the
> watchpoint again and again. The tracing process would never get
> notified of the watchpoint hit.
> ~~~~~~~~~~~~
>
> ... I'm left with the impression that ADDR_TRAP could be even
> lower than addr_watch_aligned, in which case we'll still miss
> watchpoints. I wondering whether GDB should be using a similar
> trick as that kernel patch does.

This is new for me what you found. I just did not expect the changed region
region could be larger than aligned 8 bytes.

Unfortunately I cannot reproduce that so I cannot do much with that.
Does anyone know how to reproduce it?

Thanks,
Jan

I was unable to make GCC use the "stp" instruction so I hand-edited it there:
# gcc -o w2.S w2.c -Wall -g -O3 -S -dA
# output attached+edited
gcc -o w2 w2.S -Wall

aarch64-7s-rhel-alt-v1.ss.eng.rdu.redhat.com
kernel-4.14.0-49.el7a.aarch64

../gdb -data-directory ../data-directory/ ./w2 -batch -ex 'b main' -ex r -ex 'p &g1' -ex 'p &g2' -ex 'b 8' -ex 'watch g2' -ex 'set debug infrun 1' -ex c -ex disas
Breakpoint 1 at 0x400458: file w2.c, line 7.
Breakpoint 1, main () at w2.c:7
7 f(1,2);
$1 = (long *) 0x420030 <g1>
$2 = (long *) 0x420038 <g2>
Breakpoint 2 at 0x400464: file w2.c, line 9.
Hardware watchpoint 3: g2
infrun: clear_proceed_status_thread (process 30847)
infrun: proceed (addr=0xffffffffffffffff, signal=GDB_SIGNAL_DEFAULT)
infrun: step-over queue now empty
infrun: resuming [process 30847] for step-over
infrun: resume (step=1, signal=GDB_SIGNAL_0), trap_expected=1, current thread [process 30847] at 0x400458
infrun: infrun_async(1)
infrun: prepare_to_wait
infrun: proceed: [process 30847] resumed
infrun: target_wait (-1.0.0, status) =
infrun: 30847.30847.0 [process 30847],
infrun: status->kind = stopped, signal = GDB_SIGNAL_TRAP
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x40045c
infrun: no stepping, continue
infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 30847] at 0x40045c
infrun: prepare_to_wait
infrun: target_wait (-1.0.0, status) =
infrun: 30847.30847.0 [process 30847],
infrun: status->kind = stopped, signal = GDB_SIGNAL_TRAP
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x4005d8
infrun: stopped by watchpoint
infrun: stopped data address = 0x420038
infrun: stop_all_threads
infrun: stop_all_threads, pass=0, iterations=0
infrun: process 30847 not executing
infrun: stop_all_threads, pass=1, iterations=1
infrun: process 30847 not executing
infrun: stop_all_threads done
infrun: stepping past non-steppable watchpoint. skipping watchpoint at 0x420038:8
infrun: stepping past non-steppable watchpoint. skipping watchpoint at 0x420038:8
infrun: stepping past non-steppable watchpoint. skipping watchpoint at 0x420038:8
infrun: stepping past non-steppable watchpoint. skipping watchpoint at 0x420038:8
infrun: resume (step=1, signal=GDB_SIGNAL_0), trap_expected=1, current thread [process 30847] at 0x4005d8
infrun: prepare_to_wait
infrun: target_wait (-1.0.0, status) =
infrun: 30847.30847.0 [process 30847],
infrun: status->kind = stopped, signal = GDB_SIGNAL_TRAP
infrun: TARGET_WAITKIND_STOPPED
infrun: clear_step_over_info
infrun: restart threads: [process 30847] is event thread
infrun: stop_pc = 0x4005dc
infrun: BPSTAT_WHAT_STOP_NOISY
infrun: stop_waiting
infrun: stop_all_threads
infrun: stop_all_threads, pass=0, iterations=0
infrun: process 30847 not executing
infrun: stop_all_threads, pass=1, iterations=1
infrun: process 30847 not executing
infrun: stop_all_threads done
Hardware watchpoint 3: g2
Old value = 0
New value = 2
f (p1=p1@entry=1, p2=p2@entry=2) at w2.c:5
5 }
infrun: infrun_async(0)
Dump of assembler code for function f:
0x00000000004005d0 <+0>: adrp x2, 0x420000 <__libc_start_main@got.plt>
0x00000000004005d4 <+4>: add x2, x2, #0x30
0x00000000004005d8 <+8>: stp x0, x1, [x2]
=> 0x00000000004005dc <+12>: ret
End of assembler dump.

[-- Attachment #2: w2.S --]
[-- Type: text/plain, Size: 9977 bytes --]

.cpu generic+fp+simd
.file "w2.c"
.text
.Ltext0:
.align 2
.global f
.type f, %function
f:
.LFB0:
.file 1 "w2.c"
// w2.c:2
.loc 1 2 0
.cfi_startproc
.LVL0:
// BLOCK 2 freq:10000 seq:0
// PRED: ENTRY [100.0%] (FALLTHRU)
// w2.c:3
.loc 1 3 0
adrp x2, .LANCHOR0
add x2, x2, :lo12:.LANCHOR0
#if 0
str x0, [x2]
// w2.c:4
.loc 1 4 0
str x1, [x2,8]
#else
stp x0, x1, [x2]
#endif
// SUCC: EXIT [100.0%]
// w2.c:5
.loc 1 5 0
ret
.cfi_endproc
.LFE0:
.size f, .-f
.section .text.startup,"ax",%progbits
.align 2
.global main
.type main, %function
main:
.LFB1:
// w2.c:6
.loc 1 6 0
.cfi_startproc
// BLOCK 2 freq:10000 seq:0
// PRED: ENTRY [100.0%] (FALLTHRU)
stp x29, x30, [sp, -16]!
.cfi_def_cfa_offset 16
.cfi_offset 29, -16
.cfi_offset 30, -8
add x29, sp, 0
.cfi_def_cfa_register 29
// w2.c:7
.loc 1 7 0
mov x0, 1
mov x1, 2
bl f
.LVL1:
// w2.c:9
.loc 1 9 0
mov w0, 0
ldp x29, x30, [sp], 16
.cfi_restore 30
.cfi_restore 29
.cfi_def_cfa 31, 0
// SUCC: EXIT [100.0%]
ret
.cfi_endproc
.LFE1:
.size main, .-main
.bss
.align 3
.zero 8
.LANCHOR0 = . + 0
.type g1, %object
.size g1, 8
g1:
.zero 8
.type g2, %object
.size g2, 8
g2:
.zero 8
.text
.Letext0:
.section .debug_info,"",%progbits
.Ldebug_info0:
.4byte 0xca // Length of Compilation Unit Info
.2byte 0x4 // DWARF version number
.4byte .Ldebug_abbrev0 // Offset Into Abbrev. Section
.byte 0x8 // Pointer Size (in bytes)
.uleb128 0x1 // (DIE (0xb) DW_TAG_compile_unit)
.4byte .LASF1 // DW_AT_producer: "GNU C 4.8.5 20150623 (Red Hat 4.8.5-28) -g -O3"
.byte 0x1 // DW_AT_language
.4byte .LASF2 // DW_AT_name: "w2.c"
.4byte .LASF3 // DW_AT_comp_dir: "/root/jkratoch/redhat/gdb-git/gdb/testsuite"
.4byte .Ldebug_ranges0+0 // DW_AT_ranges
.8byte 0 // DW_AT_low_pc
.4byte .Ldebug_line0 // DW_AT_stmt_list
.uleb128 0x2 // (DIE (0x29) DW_TAG_subprogram)
// DW_AT_external
.ascii "f\0" // DW_AT_name
.byte 0x1 // DW_AT_decl_file (w2.c)
.byte 0x2 // DW_AT_decl_line
// DW_AT_prototyped
.8byte .LFB0 // DW_AT_low_pc
.8byte .LFE0-.LFB0 // DW_AT_high_pc
.uleb128 0x1 // DW_AT_frame_base
.byte 0x9c // DW_OP_call_frame_cfa
// DW_AT_GNU_all_call_sites
.4byte 0x5d // DW_AT_sibling
.uleb128 0x3 // (DIE (0x44) DW_TAG_formal_parameter)
.ascii "p1\0" // DW_AT_name
.byte 0x1 // DW_AT_decl_file (w2.c)
.byte 0x2 // DW_AT_decl_line
.4byte 0x5d // DW_AT_type
.uleb128 0x1 // DW_AT_location
.byte 0x50 // DW_OP_reg0
.uleb128 0x3 // (DIE (0x50) DW_TAG_formal_parameter)
.ascii "p2\0" // DW_AT_name
.byte 0x1 // DW_AT_decl_file (w2.c)
.byte 0x2 // DW_AT_decl_line
.4byte 0x5d // DW_AT_type
.uleb128 0x1 // DW_AT_location
.byte 0x51 // DW_OP_reg1
.byte 0 // end of children of DIE 0x29
.uleb128 0x4 // (DIE (0x5d) DW_TAG_base_type)
.byte 0x8 // DW_AT_byte_size
.byte 0x5 // DW_AT_encoding
.4byte .LASF0 // DW_AT_name: "long int"
.uleb128 0x5 // (DIE (0x64) DW_TAG_subprogram)
// DW_AT_external
.4byte .LASF4 // DW_AT_name: "main"
.byte 0x1 // DW_AT_decl_file (w2.c)
.byte 0x6 // DW_AT_decl_line
// DW_AT_prototyped
.4byte 0x9e // DW_AT_type
.8byte .LFB1 // DW_AT_low_pc
.8byte .LFE1-.LFB1 // DW_AT_high_pc
.uleb128 0x1 // DW_AT_frame_base
.byte 0x9c // DW_OP_call_frame_cfa
// DW_AT_GNU_all_call_sites
.4byte 0x9e // DW_AT_sibling
.uleb128 0x6 // (DIE (0x85) DW_TAG_GNU_call_site)
.8byte .LVL1 // DW_AT_low_pc
.4byte 0x29 // DW_AT_abstract_origin
.uleb128 0x7 // (DIE (0x92) DW_TAG_GNU_call_site_parameter)
.uleb128 0x1 // DW_AT_location
.byte 0x51 // DW_OP_reg1
.uleb128 0x1 // DW_AT_GNU_call_site_value
.byte 0x32 // DW_OP_lit2
.uleb128 0x7 // (DIE (0x97) DW_TAG_GNU_call_site_parameter)
.uleb128 0x1 // DW_AT_location
.byte 0x50 // DW_OP_reg0
.uleb128 0x1 // DW_AT_GNU_call_site_value
.byte 0x31 // DW_OP_lit1
.byte 0 // end of children of DIE 0x85
.byte 0 // end of children of DIE 0x64
.uleb128 0x8 // (DIE (0x9e) DW_TAG_base_type)
.byte 0x4 // DW_AT_byte_size
.byte 0x5 // DW_AT_encoding
.ascii "int\0" // DW_AT_name
.uleb128 0x9 // (DIE (0xa5) DW_TAG_variable)
.ascii "g1\0" // DW_AT_name
.byte 0x1 // DW_AT_decl_file (w2.c)
.byte 0x1 // DW_AT_decl_line
.4byte 0x5d // DW_AT_type
.uleb128 0x9 // DW_AT_location
.byte 0x3 // DW_OP_addr
.8byte g1
.uleb128 0x9 // (DIE (0xb9) DW_TAG_variable)
.ascii "g2\0" // DW_AT_name
.byte 0x1 // DW_AT_decl_file (w2.c)
.byte 0x1 // DW_AT_decl_line
.4byte 0x5d // DW_AT_type
.uleb128 0x9 // DW_AT_location
.byte 0x3 // DW_OP_addr
.8byte g2
.byte 0 // end of children of DIE 0xb
.section .debug_abbrev,"",%progbits
.Ldebug_abbrev0:
.uleb128 0x1 // (abbrev code)
.uleb128 0x11 // (TAG: DW_TAG_compile_unit)
.byte 0x1 // DW_children_yes
.uleb128 0x25 // (DW_AT_producer)
.uleb128 0xe // (DW_FORM_strp)
.uleb128 0x13 // (DW_AT_language)
.uleb128 0xb // (DW_FORM_data1)
.uleb128 0x3 // (DW_AT_name)
.uleb128 0xe // (DW_FORM_strp)
.uleb128 0x1b // (DW_AT_comp_dir)
.uleb128 0xe // (DW_FORM_strp)
.uleb128 0x55 // (DW_AT_ranges)
.uleb128 0x17 // (DW_FORM_sec_offset)
.uleb128 0x11 // (DW_AT_low_pc)
.uleb128 0x1 // (DW_FORM_addr)
.uleb128 0x10 // (DW_AT_stmt_list)
.uleb128 0x17 // (DW_FORM_sec_offset)
.byte 0
.byte 0
.uleb128 0x2 // (abbrev code)
.uleb128 0x2e // (TAG: DW_TAG_subprogram)
.byte 0x1 // DW_children_yes
.uleb128 0x3f // (DW_AT_external)
.uleb128 0x19 // (DW_FORM_flag_present)
.uleb128 0x3 // (DW_AT_name)
.uleb128 0x8 // (DW_FORM_string)
.uleb128 0x3a // (DW_AT_decl_file)
.uleb128 0xb // (DW_FORM_data1)
.uleb128 0x3b // (DW_AT_decl_line)
.uleb128 0xb // (DW_FORM_data1)
.uleb128 0x27 // (DW_AT_prototyped)
.uleb128 0x19 // (DW_FORM_flag_present)
.uleb128 0x11 // (DW_AT_low_pc)
.uleb128 0x1 // (DW_FORM_addr)
.uleb128 0x12 // (DW_AT_high_pc)
.uleb128 0x7 // (DW_FORM_data8)
.uleb128 0x40 // (DW_AT_frame_base)
.uleb128 0x18 // (DW_FORM_exprloc)
.uleb128 0x2117 // (DW_AT_GNU_all_call_sites)
.uleb128 0x19 // (DW_FORM_flag_present)
.uleb128 0x1 // (DW_AT_sibling)
.uleb128 0x13 // (DW_FORM_ref4)
.byte 0
.byte 0
.uleb128 0x3 // (abbrev code)
.uleb128 0x5 // (TAG: DW_TAG_formal_parameter)
.byte 0 // DW_children_no
.uleb128 0x3 // (DW_AT_name)
.uleb128 0x8 // (DW_FORM_string)
.uleb128 0x3a // (DW_AT_decl_file)
.uleb128 0xb // (DW_FORM_data1)
.uleb128 0x3b // (DW_AT_decl_line)
.uleb128 0xb // (DW_FORM_data1)
.uleb128 0x49 // (DW_AT_type)
.uleb128 0x13 // (DW_FORM_ref4)
.uleb128 0x2 // (DW_AT_location)
.uleb128 0x18 // (DW_FORM_exprloc)
.byte 0
.byte 0
.uleb128 0x4 // (abbrev code)
.uleb128 0x24 // (TAG: DW_TAG_base_type)
.byte 0 // DW_children_no
.uleb128 0xb // (DW_AT_byte_size)
.uleb128 0xb // (DW_FORM_data1)
.uleb128 0x3e // (DW_AT_encoding)
.uleb128 0xb // (DW_FORM_data1)
.uleb128 0x3 // (DW_AT_name)
.uleb128 0xe // (DW_FORM_strp)
.byte 0
.byte 0
.uleb128 0x5 // (abbrev code)
.uleb128 0x2e // (TAG: DW_TAG_subprogram)
.byte 0x1 // DW_children_yes
.uleb128 0x3f // (DW_AT_external)
.uleb128 0x19 // (DW_FORM_flag_present)
.uleb128 0x3 // (DW_AT_name)
.uleb128 0xe // (DW_FORM_strp)
.uleb128 0x3a // (DW_AT_decl_file)
.uleb128 0xb // (DW_FORM_data1)
.uleb128 0x3b // (DW_AT_decl_line)
.uleb128 0xb // (DW_FORM_data1)
.uleb128 0x27 // (DW_AT_prototyped)
.uleb128 0x19 // (DW_FORM_flag_present)
.uleb128 0x49 // (DW_AT_type)
.uleb128 0x13 // (DW_FORM_ref4)
.uleb128 0x11 // (DW_AT_low_pc)
.uleb128 0x1 // (DW_FORM_addr)
.uleb128 0x12 // (DW_AT_high_pc)
.uleb128 0x7 // (DW_FORM_data8)
.uleb128 0x40 // (DW_AT_frame_base)
.uleb128 0x18 // (DW_FORM_exprloc)
.uleb128 0x2117 // (DW_AT_GNU_all_call_sites)
.uleb128 0x19 // (DW_FORM_flag_present)
.uleb128 0x1 // (DW_AT_sibling)
.uleb128 0x13 // (DW_FORM_ref4)
.byte 0
.byte 0
.uleb128 0x6 // (abbrev code)
.uleb128 0x4109 // (TAG: DW_TAG_GNU_call_site)
.byte 0x1 // DW_children_yes
.uleb128 0x11 // (DW_AT_low_pc)
.uleb128 0x1 // (DW_FORM_addr)
.uleb128 0x31 // (DW_AT_abstract_origin)
.uleb128 0x13 // (DW_FORM_ref4)
.byte 0
.byte 0
.uleb128 0x7 // (abbrev code)
.uleb128 0x410a // (TAG: DW_TAG_GNU_call_site_parameter)
.byte 0 // DW_children_no
.uleb128 0x2 // (DW_AT_location)
.uleb128 0x18 // (DW_FORM_exprloc)
.uleb128 0x2111 // (DW_AT_GNU_call_site_value)
.uleb128 0x18 // (DW_FORM_exprloc)
.byte 0
.byte 0
.uleb128 0x8 // (abbrev code)
.uleb128 0x24 // (TAG: DW_TAG_base_type)
.byte 0 // DW_children_no
.uleb128 0xb // (DW_AT_byte_size)
.uleb128 0xb // (DW_FORM_data1)
.uleb128 0x3e // (DW_AT_encoding)
.uleb128 0xb // (DW_FORM_data1)
.uleb128 0x3 // (DW_AT_name)
.uleb128 0x8 // (DW_FORM_string)
.byte 0
.byte 0
.uleb128 0x9 // (abbrev code)
.uleb128 0x34 // (TAG: DW_TAG_variable)
.byte 0 // DW_children_no
.uleb128 0x3 // (DW_AT_name)
.uleb128 0x8 // (DW_FORM_string)
.uleb128 0x3a // (DW_AT_decl_file)
.uleb128 0xb // (DW_FORM_data1)
.uleb128 0x3b // (DW_AT_decl_line)
.uleb128 0xb // (DW_FORM_data1)
.uleb128 0x49 // (DW_AT_type)
.uleb128 0x13 // (DW_FORM_ref4)
.uleb128 0x2 // (DW_AT_location)
.uleb128 0x18 // (DW_FORM_exprloc)
.byte 0
.byte 0
.byte 0
.section .debug_aranges,"",%progbits
.4byte 0x3c // Length of Address Ranges Info
.2byte 0x2 // DWARF Version
.4byte .Ldebug_info0 // Offset of Compilation Unit Info
.byte 0x8 // Size of Address
.byte 0 // Size of Segment Descriptor
.2byte 0 // Pad to 16 byte boundary
.2byte 0
.8byte .Ltext0 // Address
.8byte .Letext0-.Ltext0 // Length
.8byte .LFB1 // Address
.8byte .LFE1-.LFB1 // Length
.8byte 0
.8byte 0
.section .debug_ranges,"",%progbits
.Ldebug_ranges0:
.8byte .Ltext0 // Offset 0
.8byte .Letext0
.8byte .LFB1 // Offset 0x10
.8byte .LFE1
.8byte 0
.8byte 0
.section .debug_line,"",%progbits
.Ldebug_line0:
.section .debug_str,"MS",%progbits,1
.LASF3:
.string "/root/jkratoch/redhat/gdb-git/gdb/testsuite"
.LASF2:
.string "w2.c"
.LASF0:
.string "long int"
.LASF4:
.string "main"
.LASF1:
.string "GNU C 4.8.5 20150623 (Red Hat 4.8.5-28) -g -O3"
.ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-28)"
.section .note.GNU-stack,"",%progbits