From patchwork Wed Mar 13 16:31:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom de Vries X-Patchwork-Id: 87150 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 063E8385781D for ; Wed, 13 Mar 2024 16:30:56 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) by sourceware.org (Postfix) with ESMTPS id 10B2A3857BAB for ; Wed, 13 Mar 2024 16:30:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 10B2A3857BAB Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.de ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 10B2A3857BAB Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=195.135.223.131 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710347429; cv=none; b=ggahM5iHWMSaEteNnPlVMYI0C4VR1L0A5GsRVxkgX1ml6Rho/J3VhW5lViJDY6q7H/O7zzQoQBUtf/SdaobxqEKEG9lcCEYtUrYUSX3kqcRRJgX99VPdPHzhwtoW1mwSV4SxuGKjiP5aM8hlQRr7rTs5yueRXcy/PmQdu2rmJU4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710347429; c=relaxed/simple; bh=iB8hkeyVB9kuPB+9jsWkEDDQ+l7wCWyOpKZ7Q1IfnkE=; h=DKIM-Signature:DKIM-Signature:DKIM-Signature:DKIM-Signature:From: To:Subject:Date:Message-Id:MIME-Version; b=URQkHW9CR8GIK4zO2qWyNH1JKPGXwO95LYml26A4iUcmw1glBVx47KAZTiMSBIL2paMkEZzVkVd3kBBhNPE5S0Z7pFeRHY9V0yUdI00WWyMpjyjAH5FUsJSTgjsoNjUWKY4H4Ik3KXDVILrtoYZJr3yJmnI2XyDhAQZNoRTsSn4= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id CE2051F7D2; Wed, 13 Mar 2024 16:30:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1710347426; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=Hkk6FqygNmuh9CXJQ5ogowJQFSNVChrXSrefctvLDMc=; b=RYywAiQxgMxy4gS5AOCTNbGkbdAh0j2ECsBVZ5AyhUdjZrVu6BFs9Z0VxgVFWzKbs+k+Ic 0xXU1NPTqWhVEOl1IKI1S2UrHMJfE98iocbNfgDxDyWfJytZOjTZI4o2MG+9t98j15J1tb 3209FqCCpuWjO0Ag2V6nIdzUs6sNkiY= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1710347426; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=Hkk6FqygNmuh9CXJQ5ogowJQFSNVChrXSrefctvLDMc=; b=61lQsFTgURQXRcIlvvRWI3EZHC7kMtF98XWe1kj3Fta1qCL1Uf2LOIsnYxZWWQDBAjL6sw /mGy/T1HXO+dD7Ag== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1710347425; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=Hkk6FqygNmuh9CXJQ5ogowJQFSNVChrXSrefctvLDMc=; b=FuYZA8JiqJ/ZdDAbxGSY9e3zT2DWKbxLb8bnT/9LecyIOC5qWXWYKSRkiZOSzq3fWarJHp KP1VdEyJioKSmwPA1uuooIoXSUDjNSeF2pApNIDo9BwaITmzRLcrrlk48mBs/GKl12tX+z 2ltff6a2ycCNfP59ebQmpcizAfBcuxc= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1710347425; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=Hkk6FqygNmuh9CXJQ5ogowJQFSNVChrXSrefctvLDMc=; b=9UhuIoiIa6Orsg0mKgtDmF4rx8MqSErnaxpqQp7R0HL5L5v88RAaHNVoYZjUm2cdzkbxAR FCLXBONwGku6IFCw== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id B527F13977; Wed, 13 Mar 2024 16:30:25 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id +UwPK6HU8WVBDQAAD6G6ig (envelope-from ); Wed, 13 Mar 2024 16:30:25 +0000 From: Tom de Vries To: gdb-patches@sourceware.org Cc: Luis Machado Subject: [PATCH v2] [gdb/tdep] Fix gdb.base/watchpoint-unaligned.exp on aarch64 Date: Wed, 13 Mar 2024 17:31:16 +0100 Message-Id: <20240313163116.16035-1-tdevries@suse.de> X-Mailer: git-send-email 2.35.3 MIME-Version: 1.0 X-Spam-Level: X-Spamd-Bar: / Authentication-Results: smtp-out2.suse.de; dkim=pass header.d=suse.de header.s=susede2_rsa header.b=FuYZA8Ji; dkim=pass header.d=suse.de header.s=susede2_ed25519 header.b=9UhuIoiI X-Rspamd-Server: rspamd2.dmz-prg2.suse.org X-Spamd-Result: default: False [0.49 / 50.00]; ARC_NA(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; R_DKIM_ALLOW(-0.20)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; SPAMHAUS_XBL(0.00)[2a07:de40:b281:104:10:150:64:97:from]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; R_MISSING_CHARSET(2.50)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; MIME_GOOD(-0.10)[text/plain]; BROKEN_CONTENT_TYPE(1.50)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; RCVD_COUNT_THREE(0.00)[3]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; DKIM_TRACE(0.00)[suse.de:+]; RCPT_COUNT_TWO(0.00)[2]; MID_CONTAINS_FROM(1.00)[]; MX_GOOD(-0.01)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:dkim]; FUZZY_BLOCKED(0.00)[rspamd.com]; FROM_EQ_ENVFROM(0.00)[]; MIME_TRACE(0.00)[0:+]; NEURAL_HAM_SHORT(-0.20)[-1.000]; RCVD_TLS_ALL(0.00)[]; BAYES_HAM(-3.00)[100.00%] X-Spam-Score: 0.49 X-Rspamd-Queue-Id: CE2051F7D2 X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_NUMSUBJECT, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org On aarch64-linux, with test-case gdb.base/watchpoint-unaligned.exp I run into: ... (gdb) watch data.u.size8twice[1]^M Hardware watchpoint 241: data.u.size8twice[1]^M (gdb) PASS: gdb.base/watchpoint-unaligned.exp: watch data.u.size8twice[1] continue^M Continuing.^M FAIL: gdb.base/watchpoint-unaligned.exp: continue (timeout) FAIL: gdb.base/watchpoint-unaligned.exp: size8twice write ... This happens as follows. We start the exec and set an 8-byte hardware watchpoint on data.u.size8twice[1] at address 0x440048: ... (gdb) p sizeof (data.u.size8twice[1]) $1 = 8 (gdb) p &data.u.size8twice[1] $2 = (uint64_t *) 0x440048 ... We continue execution, and a 16-byte write at address 0x440040 triggers the hardware watchpoint: ... 4101c8: a9000801 stp x1, x2, [x0] ... When checking whether a watchpoint has triggered in aarch64_stopped_data_address, we check against address 0x440040 (passed in parameter addr_trap). This behaviour is documented: ... /* ADDR_TRAP reports the first address of the memory range accessed by the CPU, regardless of what was the memory range watched. ... */ ... and consequently the matching logic compares against an addr_watch_aligned: ... && addr_trap >= addr_watch_aligned && addr_trap < addr_watch + len) ... However, the comparison fails: ... (gdb) p /x addr_watch_aligned $3 = 0x440048 (gdb) p addr_trap >= addr_watch_aligned $4 = false ... Consequently, aarch64_stopped_data_address returns false, and stopped_by_watchpoint returns false, and watchpoints_triggered returns 0, which make infrun think it's looking at a delayed hardware breakpoint/watchpoint trap: ... [infrun] handle_signal_stop: stop_pc=0x4101c8 [infrun] handle_signal_stop: delayed hardware breakpoint/watchpoint trap, ignoring ... Infrun then ignores the trap and continues, but runs into the same situation again and again, causing a hang which then causes the test timeout. Fix this by allowing a match 8 bytes below addr_watch_aligned. This introduces the possibility for false positives, so we only do this for regular "value changed" watchpoints. An earlier version of this patch worked by aligning addr_watch_aligned to 16 instead of 8: ... - const CORE_ADDR addr_watch_aligned = align_down (state->dr_addr_wp[i], 8); + const CORE_ADDR addr_watch_aligned = align_down (state->dr_addr_wp[i], 16); ... but while that fixed the test-case, it didn't fix the problem completely, so extend the test-case to check more scenarios. Tested on aarch64-linux. PR tdep/29423 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29423 Tested-By: Luis Machado --- gdb/aarch64-nat.c | 17 +++- gdb/testsuite/gdb.base/watchpoint-unaligned.c | 11 +-- .../gdb.base/watchpoint-unaligned.exp | 78 ++++++++++++------- 3 files changed, 68 insertions(+), 38 deletions(-) base-commit: 4810a2d92b9e1a13774c1286cd8a0f718f81abba diff --git a/gdb/aarch64-nat.c b/gdb/aarch64-nat.c index 6c72a8d6d9f..802bab6d682 100644 --- a/gdb/aarch64-nat.c +++ b/gdb/aarch64-nat.c @@ -269,7 +269,7 @@ aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state, = aarch64_watchpoint_length (state->dr_ctrl_wp[i]); const CORE_ADDR addr_watch = state->dr_addr_wp[i] + offset; const CORE_ADDR addr_watch_aligned - = align_down (state->dr_addr_wp[i], 8); + = align_down (state->dr_addr_wp[i], AARCH64_HWP_MAX_LEN_PER_REG); const CORE_ADDR addr_orig = state->dr_addr_orig_wp[i]; /* ADDR_TRAP reports the first address of the memory range @@ -283,8 +283,19 @@ aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state, |---- range watched ----| |----------- range accessed ------------| - In this case, ADDR_TRAP will be 4. */ - if (!(addr_trap >= addr_watch_aligned + In this case, ADDR_TRAP will be 4. + + The access size also can be larger than that of the watchpoint + itself. For instance, the access size of an stp instruction is 16. + So, if we use stp to store to address p, and set a watchpoint on + address p + 8, the reported ADDR_TRAP can be p + 8 (observed on + RK3399 SOC). But it also can be p (observed on M1 SOC). Checking + for this situation introduces the possibility of false positives, + so we only do this for hw_write watchpoints. */ + const CORE_ADDR max_access_size = type == hw_write ? 16 : 8; + const CORE_ADDR addr_watch_base = addr_watch_aligned - + (max_access_size - AARCH64_HWP_MAX_LEN_PER_REG); + if (!(addr_trap >= addr_watch_base && addr_trap < addr_watch + len)) { /* Not a match. */ diff --git a/gdb/testsuite/gdb.base/watchpoint-unaligned.c b/gdb/testsuite/gdb.base/watchpoint-unaligned.c index 64728bb9ea3..6f709259b6c 100644 --- a/gdb/testsuite/gdb.base/watchpoint-unaligned.c +++ b/gdb/testsuite/gdb.base/watchpoint-unaligned.c @@ -29,7 +29,7 @@ static volatile struct uint32_t size4[2]; uint16_t size2[4]; uint8_t size1[8]; - uint64_t size8twice[2]; + uint64_t size8twice[3]; } u; } data; @@ -44,13 +44,14 @@ write_size8twice (void) static const uint64_t second = 2; #ifdef __aarch64__ + volatile void *p = &data.u.size8twice[offset]; asm volatile ("stp %1, %2, [%0]" : /* output */ - : "r" (data.u.size8twice), "r" (first), "r" (second) /* input */ + : "r" (p), "r" (first), "r" (second) /* input */ : "memory" /* clobber */); #else - data.u.size8twice[0] = first; - data.u.size8twice[1] = second; + data.u.size8twice[offset] = first; + data.u.size8twice[offset + 1] = second; #endif } @@ -59,7 +60,7 @@ main (void) { volatile uint64_t local; - assert (sizeof (data) == 8 + 2 * 8); + assert (sizeof (data) == 8 + 3 * 8); write_size8twice (); diff --git a/gdb/testsuite/gdb.base/watchpoint-unaligned.exp b/gdb/testsuite/gdb.base/watchpoint-unaligned.exp index 8d985c03bfc..35e8868d39d 100644 --- a/gdb/testsuite/gdb.base/watchpoint-unaligned.exp +++ b/gdb/testsuite/gdb.base/watchpoint-unaligned.exp @@ -151,38 +151,56 @@ foreach wpcount {4 7} { gdb_assert $got_hit $test } -if ![runto_main] { - return -1 -} -gdb_breakpoint [gdb_get_line_number "final_return"] "Breakpoint $decimal at $hex" "final_return" -set test {watch data.u.size8twice[1]} -set wpnum 0 -gdb_test_multiple $test $test { - -re "Hardware watchpoint (\[0-9\]+): .*\r\n$gdb_prompt $" { - set wpnum $expect_out(1,string) - pass $gdb_test_name - } - -re "Watchpoint (\[0-9\]+): .*\r\n$gdb_prompt $" { - if {[istarget "arm*-*-*"]} { - untested $gdb_test_name - } else { - fail $gdb_test_name - } - } -} -if {$wpnum} { - set test "continue" - set got_hit 0 - gdb_test_multiple $test $test { - -re "\r\nCould not insert hardware watchpoint .*\r\n$gdb_prompt $" { +# We've got an array with 3 8-byte elements. Do a store of 16 bytes, +# to: +# - elements 0 and 1 (offset == 0), and +# - elements 1 and 2 (offset == 1). +# For each case, check setting a watchpoint at: +# - the first written element (index == 0), and +# - the second element (index == 1). +foreach_with_prefix offset { 0 1 } { + foreach_with_prefix index { 0 1 } { + + clean_restart $binfile + + if ![runto_main] { + return -1 } - -re "Hardware watchpoint $wpnum:.*New value = .*\r\n$gdb_prompt $" { - set got_hit 1 - send_gdb "continue\n" - exp_continue + + gdb_test_no_output "set var offset = $offset" + gdb_breakpoint [gdb_get_line_number "final_return"] \ + "Breakpoint $decimal at $hex" "final_return" + set watch_index [expr $offset + $index] + set test "watch data.u.size8twice\[$watch_index\]" + set wpnum 0 + gdb_test_multiple $test $test { + -re "Hardware watchpoint (\[0-9\]+): .*\r\n$gdb_prompt $" { + set wpnum $expect_out(1,string) + pass $gdb_test_name + } + -re "Watchpoint (\[0-9\]+): .*\r\n$gdb_prompt $" { + if {[istarget "arm*-*-*"]} { + untested $gdb_test_name + } else { + fail $gdb_test_name + } + } } - -re " final_return .*\r\n$gdb_prompt $" { + if {$wpnum} { + set test "continue" + set got_hit 0 + gdb_test_multiple $test $test { + -re "\r\nCould not insert hardware watchpoint .*\r\n$gdb_prompt $" { + } + -re "Hardware watchpoint $wpnum:.*New value = .*\r\n$gdb_prompt $" { + set got_hit 1 + send_gdb "continue\n" + exp_continue + } + -re " final_return .*\r\n$gdb_prompt $" { + } + } + gdb_assert $got_hit "size8twice write" } } - gdb_assert $got_hit "size8twice write" }