From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from EUR01-HE1-obe.outbound.protection.outlook.com (mail-eopbgr130080.outbound.protection.outlook.com [40.107.13.80]) by sourceware.org (Postfix) with ESMTPS id 3BB85385840F for ; Thu, 17 Mar 2022 15:36:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3BB85385840F Received: from AM6PR01CA0072.eurprd01.prod.exchangelabs.com (2603:10a6:20b:e0::49) by AM5PR0802MB2595.eurprd08.prod.outlook.com (2603:10a6:203:a2::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5081.14; Thu, 17 Mar 2022 15:36:01 +0000 Received: from VE1EUR03FT008.eop-EUR03.prod.protection.outlook.com (2603:10a6:20b:e0:cafe::c8) by AM6PR01CA0072.outlook.office365.com (2603:10a6:20b:e0::49) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5081.17 via Frontend Transport; Thu, 17 Mar 2022 15:36:01 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 63.35.35.123) smtp.mailfrom=arm.com; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com;dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 63.35.35.123 as permitted sender) receiver=protection.outlook.com; client-ip=63.35.35.123; helo=64aa7808-outbound-1.mta.getcheckrecipient.com; Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VE1EUR03FT008.mail.protection.outlook.com (10.152.18.75) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5081.14 via Frontend Transport; Thu, 17 Mar 2022 15:36:01 +0000 Received: ("Tessian outbound 63bb5eb69ee8:v113"); Thu, 17 Mar 2022 15:36:01 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 187f846a1f2059a7 X-CR-MTA-TID: 64aa7808 Received: from 0658f21f1b0e.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id B68CF5FE-09FC-43C9-B078-6CF6EBBDA05F.1; Thu, 17 Mar 2022 15:35:54 +0000 Received: from EUR05-VI1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 0658f21f1b0e.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Thu, 17 Mar 2022 15:35:54 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Ri6/3n/nyvb6ByKMHmUXB1EWOQP6VENQVot+XG63Wal/OTutGtJ5weA/krCAuPjZy9ihCYcKvT+O0nCaxjFiWlCAcDhBoG36alkKPVVEJa6oYrj22wnuWhmc+aRUwxD7joFEsMTv2HGK+hcCDvGazS00rjEaQlbhC3zEHjzDGi4pY+9gyCeUWS85ymjdl5Jj1Lzai+3vzYklFqHbdbs6M3YmB7RBg4C5VfPhWmNkXDZoPTQYUb4i3Ch9safc7eny99/4upIdENkpS6M5QbIXf8udcLyF7hnU/hOFO0ZhfYB67hx3Xohs8CRVpTNJY/vPwnZLv7T0x5gNznMzQsmG7g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=rJcS9n5YzVLoRBHAGHyjCM5OwELg99ymI/FkLtzvrEQ=; b=Tz404LAgCRFJGAisGGb21iNAY1CzW+50NW/u1suRKtUfBNxHM4do+ck+ciiUQfysb/hE1WKPiDhEcKrcn0juHhK4n2H+5WO6zL0VyDaCL1fJQ53vSs5AeQjpEWFdd99hWpsLsKuulParVEm5cVwYstoUOKtN4EXVhpIYnxkngg1laCWnHiqX59ank0GYS5RSHw2ba9sA3OTx+Kue9xgLjmUmCF416qZufAX3rCZkmc0E0eHkb/9THj0qFof7AeIjaRHr9gXy20dQZrZxOxP3ypkz11TNB55lGjg0AI0y1FieDd7+K5b+zbrNaaBH+Z/9g5pSt/90cDZ2DfhtXAljcg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=arm.com; dmarc=pass action=none header.from=arm.com; dkim=pass header.d=arm.com; arc=none Authentication-Results-Original: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; Received: from VI1PR08MB3919.eurprd08.prod.outlook.com (2603:10a6:803:c4::31) by AM0PR08MB3347.eurprd08.prod.outlook.com (2603:10a6:208:5f::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5081.14; Thu, 17 Mar 2022 15:35:51 +0000 Received: from VI1PR08MB3919.eurprd08.prod.outlook.com ([fe80::4d3d:c632:297e:1dcc]) by VI1PR08MB3919.eurprd08.prod.outlook.com ([fe80::4d3d:c632:297e:1dcc%5]) with mapi id 15.20.5081.017; Thu, 17 Mar 2022 15:35:50 +0000 Message-ID: <5878cf50-18f1-7f36-c861-d020262ee513@arm.com> Date: Thu, 17 Mar 2022 15:35:48 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.5.0 Subject: Re: [PATCH v2 08/12] aarch64: Add an aarch64_nat_target mixin class. Content-Language: en-US To: John Baldwin , gdb-patches@sourceware.org References: <20220316201923.89694-1-jhb@FreeBSD.org> <20220316201923.89694-9-jhb@FreeBSD.org> From: Luis Machado In-Reply-To: <20220316201923.89694-9-jhb@FreeBSD.org> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-ClientProxiedBy: LNXP265CA0063.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:5d::27) To VI1PR08MB3919.eurprd08.prod.outlook.com (2603:10a6:803:c4::31) MIME-Version: 1.0 X-MS-Office365-Filtering-Correlation-Id: efcc0bd0-bd00-4d5d-3166-08da082bd731 X-MS-TrafficTypeDiagnostic: AM0PR08MB3347:EE_|VE1EUR03FT008:EE_|AM5PR0802MB2595:EE_ X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: U8f6uUl145DBTKfl/+2/27oy1GvzB4C7QpJfxoKT3dQYUrkQbq5aK58+/o8lvNNQSLNzf8snaxE2IjJXDDDj8Q5nq7zwkMKufA/kNDoQRFb2g8aZV+rAe7UoEW+RTloY2D2HBmaBXuw1+ZK3H578l1AlYyjfKhcQKFF6zr6ZbkXgpU4dwVD3V3WAC9leLIbWYZdWQJBk6CdR6n0HpgtNtyv3Dnaxo1XfsGg77eAwk4cO5YLMZGc7yP1wdNTCQ42wdGp0GqrCxGv9lYmC6K5+sDJ4DtWlr+SBviULDDoMyjJrMA7c4+5/GD7o+OkLC22IaL88+gFF7DvYr1koSh6KMhowVOTVpjIdQLfxJrBC06bdT5Z/5XAIbL0phG04zRpYD8mcRSxiy7aMUdhuHfOUff8xOicZJkKdr+KV+nom0j1tgknny8uTF9WvY4A5wq6at/gubPoW2ToCbuPjXjZUBTllyFYrFFy+tL7m+lVp3Yr/GYUq3x4qZ7pJLAh/KSIXmY++gM/NObKMIcqHVJGzegwah5Zwwbplq5r7Ka2Du4cJh54V92cSz6QqEZmovkFzk0vRuP0fzTjCcIPeOafzTKk9fO1/koWUR8Sx/Rs+namsrbOOY2Wa04Kyl7+Cor1LbFquphsZfbH5WWohiXVWUCXjc8oNgnOofuMVpeL3GWDoeX8oKwaoXounmkBA5+kcPbIuFMWVp3ZGfHpqnmyXa2hM/jy6fJKxhT/9xXz7+rTLl/6MCH6tRyPI4uApztuik8nidIXdezJ3dzcb7kCk/GgLPqM4GHD07lVCu+Obj0pEr7hhZ4Kmkf7jzBzu4nYXqkrZ5Ur9Z282yJmH/TZijw== X-Forefront-Antispam-Report-Untrusted: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:VI1PR08MB3919.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230001)(4636009)(366004)(38100700002)(508600001)(6486002)(5660300002)(31686004)(44832011)(8936002)(36756003)(6512007)(30864003)(83380400001)(31696002)(2906002)(6506007)(86362001)(316002)(2616005)(186003)(26005)(53546011)(8676002)(66476007)(66946007)(66556008)(2004002)(43740500002)(45980500001); DIR:OUT; SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM0PR08MB3347 Original-Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VE1EUR03FT008.eop-EUR03.prod.protection.outlook.com X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id-Prvs: d2c31489-d632-4754-b87b-08da082bd0c1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 8saOHo5b2MKYKVATBhQKFo32DesWftkSUfpnOAcBv7Q1O/EhzCweM6X5woBHTjGTpbhPXX5x6/PI0teZAQEtPGzvD9cEjFZC3iZ3qxJ/7BKMGqHjXHB0Gl/Wq07XCv1PAySRAxIk/v4OnIHPmD4e0qlfIyKizrwCc9xZkveeLAkDqMrQUUtUW7yuKxnsZ5+4EBJryXNW/cfuHcj3q3NSN+WuYAnBGwniVDZB9xXz6D30wFnYpddkf+5oHJ6IhpfxcnpwstMJMLOVIKIVK8l5VNGM6XbzpJxnF1p42AaNXYNOOD9dhBYQrFZAVVtPnP1PYsR7FrpoKSrdUALx32hgN27E1PxlugZnNSK1M8O1wCLtvfQFSmCHgu5tj26vFslSWctI31lmt9adKOK1pbmwxh7xH4v/jA9y6lbi5wtY5pCQSqx7h/Se7cY/M2bG1okkjxMirhMbFQj3p0E0FoxpFVd+UkxQ68/ZAM8k4AVDdP+tSi7x69Mmt5pLcDUlwMpAb39vBnWL0fkRYd5cepNxC1txGISbRTGQnVjJEzX2XStvwJok3iWmidSZsbY2NmfSxy1A+18X2Qk/F0f5xU5pK53yFQkyx8gCBLcJQxUGoaWzb47e/c4ZqVzDtLXa3ph8eOTsLSmJB8ECaxNZJvKUZLPpti1lCdi5dNnkaR987JLUP8Gcqjo2cf2yvACWLbC4VTw4Oqta+18HjVeKQ9FS1/Gm9p+Af5p3LWpxRJPExySK4OR+nx7QGAWScN6wmwFrs9eN/cBQoG9ehxo899lWrTY+QF8yiWd/KQDNz/at1WI9quAvZxvHeQ6KzWIu094i X-Forefront-Antispam-Report: CIP:63.35.35.123; CTRY:IE; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:64aa7808-outbound-1.mta.getcheckrecipient.com; PTR:ec2-63-35-35-123.eu-west-1.compute.amazonaws.com; CAT:NONE; SFS:(13230001)(4636009)(36840700001)(40470700004)(46966006)(40460700003)(336012)(26005)(186003)(83380400001)(36756003)(44832011)(31686004)(2906002)(30864003)(8936002)(5660300002)(36860700001)(508600001)(82310400004)(6486002)(70586007)(70206006)(6512007)(53546011)(6506007)(2616005)(47076005)(81166007)(31696002)(356005)(86362001)(8676002)(316002)(2004002)(43740500002); DIR:OUT; SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 17 Mar 2022 15:36:01.1855 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: efcc0bd0-bd00-4d5d-3166-08da082bd731 X-MS-Exchange-CrossTenant-Id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=f34e5979-57d9-4aaa-ad4d-b122a662184d; Ip=[63.35.35.123]; Helo=[64aa7808-outbound-1.mta.getcheckrecipient.com] X-MS-Exchange-CrossTenant-AuthSource: VE1EUR03FT008.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM5PR0802MB2595 X-Spam-Status: No, score=-12.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, KAM_SHORT, NICE_REPLY_A, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE, UNPARSEABLE_RELAY autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Mar 2022 15:36:10 -0000 Hi, LGTM from aarch64's side. Just a nit below, if you'd like to address it. On 3/16/22 20:19, John Baldwin wrote: > This class includes platform-independent target methods for hardware > breakpoints and watchpoints using routines from nat/aarch64-hw-point.c. > > stopped_data_address is not platform-independent since the FAR register > holding the address for a breakpoint hit must be fetched in a > platform-specific manner. However, aarch64_stopped_data_address is > provided as a helper routine which performs platform-independent > validation given the value of the FAR register. > > For tracking the per-process debug register mirror state, use an > unordered_map indexed by pid as recently adopted in x86-nat.c rather > than a manual linked-list. > --- > gdb/aarch64-linux-nat.c | 356 +--------------------------------------- > gdb/aarch64-nat.c | 302 ++++++++++++++++++++++++++++++++++ > gdb/aarch64-nat.h | 109 ++++++++++++ > gdb/configure.nat | 2 +- > 4 files changed, 418 insertions(+), 351 deletions(-) > create mode 100644 gdb/aarch64-nat.c > create mode 100644 gdb/aarch64-nat.h > > diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c > index dd072d9315e..7bb82d17cc8 100644 > --- a/gdb/aarch64-linux-nat.c > +++ b/gdb/aarch64-linux-nat.c > @@ -27,6 +27,7 @@ > #include "target-descriptions.h" > #include "auxv.h" > #include "gdbcmd.h" > +#include "aarch64-nat.h" > #include "aarch64-tdep.h" > #include "aarch64-linux-tdep.h" > #include "aarch32-linux-nat.h" > @@ -58,7 +59,8 @@ > #define TRAP_HWBKPT 0x0004 > #endif > > -class aarch64_linux_nat_target final : public linux_nat_target > +class aarch64_linux_nat_target final > + : public aarch64_nat_target > { > public: > /* Add our register access methods. */ > @@ -68,17 +70,8 @@ class aarch64_linux_nat_target final : public linux_nat_target > const struct target_desc *read_description () override; > > /* Add our hardware breakpoint and watchpoint implementation. */ > - int can_use_hw_breakpoint (enum bptype, int, int) override; > - int insert_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override; > - int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override; > - int region_ok_for_hw_watchpoint (CORE_ADDR, int) override; > - int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type, > - struct expression *) override; > - int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type, > - struct expression *) override; > bool stopped_by_watchpoint () override; > bool stopped_data_address (CORE_ADDR *) override; > - bool watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, int) override; > > int can_do_single_step () override; > > @@ -118,103 +111,13 @@ class aarch64_linux_nat_target final : public linux_nat_target > > static aarch64_linux_nat_target the_aarch64_linux_nat_target; > > -/* Per-process data. We don't bind this to a per-inferior registry > - because of targets like x86 GNU/Linux that need to keep track of > - processes that aren't bound to any inferior (e.g., fork children, > - checkpoints). */ > - > -struct aarch64_process_info > -{ > - /* Linked list. */ > - struct aarch64_process_info *next; > - > - /* The process identifier. */ > - pid_t pid; > - > - /* Copy of aarch64 hardware debug registers. */ > - struct aarch64_debug_reg_state state; > -}; > - > -static struct aarch64_process_info *aarch64_process_list = NULL; > - > -/* Find process data for process PID. */ > - > -static struct aarch64_process_info * > -aarch64_find_process_pid (pid_t pid) > -{ > - struct aarch64_process_info *proc; > - > - for (proc = aarch64_process_list; proc; proc = proc->next) > - if (proc->pid == pid) > - return proc; > - > - return NULL; > -} > - > -/* Add process data for process PID. Returns newly allocated info > - object. */ > - > -static struct aarch64_process_info * > -aarch64_add_process (pid_t pid) > -{ > - struct aarch64_process_info *proc; > - > - proc = XCNEW (struct aarch64_process_info); > - proc->pid = pid; > - > - proc->next = aarch64_process_list; > - aarch64_process_list = proc; > - > - return proc; > -} > - > -/* Get data specific info for process PID, creating it if necessary. > - Never returns NULL. */ > - > -static struct aarch64_process_info * > -aarch64_process_info_get (pid_t pid) > -{ > - struct aarch64_process_info *proc; > - > - proc = aarch64_find_process_pid (pid); > - if (proc == NULL) > - proc = aarch64_add_process (pid); > - > - return proc; > -} > - > /* Called whenever GDB is no longer debugging process PID. It deletes > data structures that keep track of debug register state. */ > > void > aarch64_linux_nat_target::low_forget_process (pid_t pid) > { > - struct aarch64_process_info *proc, **proc_link; > - > - proc = aarch64_process_list; > - proc_link = &aarch64_process_list; > - > - while (proc != NULL) > - { > - if (proc->pid == pid) > - { > - *proc_link = proc->next; > - > - xfree (proc); > - return; > - } > - > - proc_link = &proc->next; > - proc = *proc_link; > - } > -} > - > -/* Get debug registers state for process PID. */ > - > -struct aarch64_debug_reg_state * > -aarch64_get_debug_reg_state (pid_t pid) > -{ > - return &aarch64_process_info_get (pid)->state; > + aarch64_remove_debug_reg_state (pid); > } > > /* Fill GDB's register array with the general-purpose register values > @@ -775,192 +678,12 @@ aarch64_linux_nat_target::low_siginfo_fixup (siginfo_t *native, gdb_byte *inf, > return false; > } > > -/* Returns the number of hardware watchpoints of type TYPE that we can > - set. Value is positive if we can set CNT watchpoints, zero if > - setting watchpoints of type TYPE is not supported, and negative if > - CNT is more than the maximum number of watchpoints of type TYPE > - that we can support. TYPE is one of bp_hardware_watchpoint, > - bp_read_watchpoint, bp_write_watchpoint, or bp_hardware_breakpoint. > - CNT is the number of such watchpoints used so far (including this > - one). OTHERTYPE is non-zero if other types of watchpoints are > - currently enabled. */ > - > -int > -aarch64_linux_nat_target::can_use_hw_breakpoint (enum bptype type, > - int cnt, int othertype) > -{ > - if (type == bp_hardware_watchpoint || type == bp_read_watchpoint > - || type == bp_access_watchpoint || type == bp_watchpoint) > - { > - if (aarch64_num_wp_regs == 0) > - return 0; > - } > - else if (type == bp_hardware_breakpoint) > - { > - if (aarch64_num_bp_regs == 0) > - return 0; > - } > - else > - gdb_assert_not_reached ("unexpected breakpoint type"); > - > - /* We always return 1 here because we don't have enough information > - about possible overlap of addresses that they want to watch. As an > - extreme example, consider the case where all the watchpoints watch > - the same address and the same region length: then we can handle a > - virtually unlimited number of watchpoints, due to debug register > - sharing implemented via reference counts. */ > - return 1; > -} > - > -/* Insert a hardware-assisted breakpoint at BP_TGT->reqstd_address. > - Return 0 on success, -1 on failure. */ > - > -int > -aarch64_linux_nat_target::insert_hw_breakpoint (struct gdbarch *gdbarch, > - struct bp_target_info *bp_tgt) > -{ > - int ret; > - CORE_ADDR addr = bp_tgt->placed_address = bp_tgt->reqstd_address; > - int len; > - const enum target_hw_bp_type type = hw_execute; > - struct aarch64_debug_reg_state *state > - = aarch64_get_debug_reg_state (inferior_ptid.pid ()); > - > - gdbarch_breakpoint_from_pc (gdbarch, &addr, &len); > - > - if (show_debug_regs) > - fprintf_unfiltered > - (gdb_stdlog, > - "insert_hw_breakpoint on entry (addr=0x%08lx, len=%d))\n", > - (unsigned long) addr, len); > - > - ret = aarch64_handle_breakpoint (type, addr, len, 1 /* is_insert */, > - inferior_ptid, state); > - > - if (show_debug_regs) > - { > - aarch64_show_debug_reg_state (state, > - "insert_hw_breakpoint", addr, len, type); > - } > - > - return ret; > -} > - > -/* Remove a hardware-assisted breakpoint at BP_TGT->placed_address. > - Return 0 on success, -1 on failure. */ > - > -int > -aarch64_linux_nat_target::remove_hw_breakpoint (struct gdbarch *gdbarch, > - struct bp_target_info *bp_tgt) > -{ > - int ret; > - CORE_ADDR addr = bp_tgt->placed_address; > - int len = 4; > - const enum target_hw_bp_type type = hw_execute; > - struct aarch64_debug_reg_state *state > - = aarch64_get_debug_reg_state (inferior_ptid.pid ()); > - > - gdbarch_breakpoint_from_pc (gdbarch, &addr, &len); > - > - if (show_debug_regs) > - fprintf_unfiltered > - (gdb_stdlog, "remove_hw_breakpoint on entry (addr=0x%08lx, len=%d))\n", > - (unsigned long) addr, len); > - > - ret = aarch64_handle_breakpoint (type, addr, len, 0 /* is_insert */, > - inferior_ptid, state); > - > - if (show_debug_regs) > - { > - aarch64_show_debug_reg_state (state, > - "remove_hw_watchpoint", addr, len, type); > - } > - > - return ret; > -} > - > -/* Implement the "insert_watchpoint" target_ops method. > - > - Insert a watchpoint to watch a memory region which starts at > - address ADDR and whose length is LEN bytes. Watch memory accesses > - of the type TYPE. Return 0 on success, -1 on failure. */ > - > -int > -aarch64_linux_nat_target::insert_watchpoint (CORE_ADDR addr, int len, > - enum target_hw_bp_type type, > - struct expression *cond) > -{ > - int ret; > - struct aarch64_debug_reg_state *state > - = aarch64_get_debug_reg_state (inferior_ptid.pid ()); > - > - if (show_debug_regs) > - fprintf_unfiltered (gdb_stdlog, > - "insert_watchpoint on entry (addr=0x%08lx, len=%d)\n", > - (unsigned long) addr, len); > - > - gdb_assert (type != hw_execute); > - > - ret = aarch64_handle_watchpoint (type, addr, len, 1 /* is_insert */, > - inferior_ptid, state); > - > - if (show_debug_regs) > - { > - aarch64_show_debug_reg_state (state, > - "insert_watchpoint", addr, len, type); > - } > - > - return ret; > -} > - > -/* Implement the "remove_watchpoint" target_ops method. > - Remove a watchpoint that watched the memory region which starts at > - address ADDR, whose length is LEN bytes, and for accesses of the > - type TYPE. Return 0 on success, -1 on failure. */ > - > -int > -aarch64_linux_nat_target::remove_watchpoint (CORE_ADDR addr, int len, > - enum target_hw_bp_type type, > - struct expression *cond) > -{ > - int ret; > - struct aarch64_debug_reg_state *state > - = aarch64_get_debug_reg_state (inferior_ptid.pid ()); > - > - if (show_debug_regs) > - fprintf_unfiltered (gdb_stdlog, > - "remove_watchpoint on entry (addr=0x%08lx, len=%d)\n", > - (unsigned long) addr, len); > - > - gdb_assert (type != hw_execute); > - > - ret = aarch64_handle_watchpoint (type, addr, len, 0 /* is_insert */, > - inferior_ptid, state); > - > - if (show_debug_regs) > - { > - aarch64_show_debug_reg_state (state, > - "remove_watchpoint", addr, len, type); > - } > - > - return ret; > -} > - > -/* Implement the "region_ok_for_hw_watchpoint" target_ops method. */ > - > -int > -aarch64_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len) > -{ > - return aarch64_region_ok_for_watchpoint (addr, len); > -} > - > /* Implement the "stopped_data_address" target_ops method. */ > > bool > aarch64_linux_nat_target::stopped_data_address (CORE_ADDR *addr_p) > { > siginfo_t siginfo; > - int i; > struct aarch64_debug_reg_state *state; > > if (!linux_nat_get_siginfo (inferior_ptid, &siginfo)) > @@ -980,44 +703,7 @@ aarch64_linux_nat_target::stopped_data_address (CORE_ADDR *addr_p) > > /* Check if the address matches any watched address. */ > state = aarch64_get_debug_reg_state (inferior_ptid.pid ()); > - for (i = aarch64_num_wp_regs - 1; i >= 0; --i) > - { > - const unsigned int offset > - = aarch64_watchpoint_offset (state->dr_ctrl_wp[i]); > - const unsigned int len = 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); > - const CORE_ADDR addr_orig = state->dr_addr_orig_wp[i]; > - > - if (state->dr_ref_count_wp[i] > - && DR_CONTROL_ENABLED (state->dr_ctrl_wp[i]) > - && addr_trap >= addr_watch_aligned > - && addr_trap < addr_watch + len) > - { > - /* ADDR_TRAP reports the first address of the memory range > - accessed by the CPU, regardless of what was the memory > - range watched. Thus, a large CPU access that straddles > - the ADDR_WATCH..ADDR_WATCH+LEN range may result in an > - ADDR_TRAP that is lower than the > - ADDR_WATCH..ADDR_WATCH+LEN range. E.g.: > - > - addr: | 4 | 5 | 6 | 7 | 8 | > - |---- range watched ----| > - |----------- range accessed ------------| > - > - In this case, ADDR_TRAP will be 4. > - > - To match a watchpoint known to GDB core, we must never > - report *ADDR_P outside of any ADDR_WATCH..ADDR_WATCH+LEN > - range. ADDR_WATCH <= ADDR_TRAP < ADDR_ORIG is a false > - positive on kernels older than 4.10. See PR > - external/20207. */ > - *addr_p = addr_orig; > - return true; > - } > - } > - > - return false; > + return aarch64_stopped_data_address (state, addr_trap, addr_p); > } > > /* Implement the "stopped_by_watchpoint" target_ops method. */ > @@ -1030,15 +716,6 @@ aarch64_linux_nat_target::stopped_by_watchpoint () > return stopped_data_address (&addr); > } > > -/* Implement the "watchpoint_addr_within_range" target_ops method. */ > - > -bool > -aarch64_linux_nat_target::watchpoint_addr_within_range (CORE_ADDR addr, > - CORE_ADDR start, int length) > -{ > - return start <= addr && start + length - 1 >= addr; > -} > - > /* Implement the "can_do_single_step" target_ops method. */ > > int > @@ -1114,32 +791,11 @@ aarch64_linux_nat_target::store_memtags (CORE_ADDR address, size_t len, > return false; > } > > -/* Define AArch64 maintenance commands. */ > - > -static void > -add_show_debug_regs_command (void) > -{ > - /* A maintenance command to enable printing the internal DRi mirror > - variables. */ > - add_setshow_boolean_cmd ("show-debug-regs", class_maintenance, > - &show_debug_regs, _("\ > -Set whether to show variables that mirror the AArch64 debug registers."), _("\ > -Show whether to show variables that mirror the AArch64 debug registers."), _("\ > -Use \"on\" to enable, \"off\" to disable.\n\ > -If enabled, the debug registers values are shown when GDB inserts\n\ > -or removes a hardware breakpoint or watchpoint, and when the inferior\n\ > -triggers a breakpoint or watchpoint."), > - NULL, > - NULL, > - &maintenance_set_cmdlist, > - &maintenance_show_cmdlist); > -} > - > void _initialize_aarch64_linux_nat (); > void > _initialize_aarch64_linux_nat () > { > - add_show_debug_regs_command (); > + aarch64_initialize_hw_point (); > > /* Register the target. */ > linux_target = &the_aarch64_linux_nat_target; > diff --git a/gdb/aarch64-nat.c b/gdb/aarch64-nat.c > new file mode 100644 > index 00000000000..85cf7f2011a > --- /dev/null > +++ b/gdb/aarch64-nat.c > @@ -0,0 +1,302 @@ > +/* Native-dependent code for AArch64. > + > + Copyright (C) 2011-2022 Free Software Foundation, Inc. > + > + This file is part of GDB. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see . */ > + > +#include "defs.h" > +#include "gdbarch.h" > +#include "inferior.h" > +#include "cli/cli-cmds.h" > +#include "aarch64-nat.h" > + > +#include > + > +/* Hash table storing per-process data. We don't bind this to a > + per-inferior registry because of targets like x86 GNU/Linux that > + need to keep track of processes that aren't bound to any inferior > + (e.g., fork children, checkpoints). */ > + > +static std::unordered_map > +aarch64_debug_process_state; > + > +/* See aarch64-nat.h. */ > + > +struct aarch64_debug_reg_state * > +aarch64_lookup_debug_reg_state (pid_t pid) > +{ > + auto it = aarch64_debug_process_state.find (pid); > + if (it != aarch64_debug_process_state.end ()) > + return &it->second; > + > + return nullptr; > +} > + > +/* See aarch64-nat.h. */ > + > +struct aarch64_debug_reg_state * > +aarch64_get_debug_reg_state (pid_t pid) > +{ > + return &aarch64_debug_process_state[pid]; > +} > + > +/* See aarch64-nat.h. */ > + > +void > +aarch64_remove_debug_reg_state (pid_t pid) > +{ > + aarch64_debug_process_state.erase (pid); > +} > + > +/* Returns the number of hardware watchpoints of type TYPE that we can > + set. Value is positive if we can set CNT watchpoints, zero if > + setting watchpoints of type TYPE is not supported, and negative if > + CNT is more than the maximum number of watchpoints of type TYPE > + that we can support. TYPE is one of bp_hardware_watchpoint, > + bp_read_watchpoint, bp_write_watchpoint, or bp_hardware_breakpoint. > + CNT is the number of such watchpoints used so far (including this > + one). OTHERTYPE is non-zero if other types of watchpoints are > + currently enabled. */ > + > +int > +aarch64_can_use_hw_breakpoint (enum bptype type, int cnt, int othertype) > +{ > + if (type == bp_hardware_watchpoint || type == bp_read_watchpoint > + || type == bp_access_watchpoint || type == bp_watchpoint) > + { > + if (aarch64_num_wp_regs == 0) > + return 0; > + } > + else if (type == bp_hardware_breakpoint) > + { > + if (aarch64_num_bp_regs == 0) > + return 0; > + } > + else > + gdb_assert_not_reached ("unexpected breakpoint type"); > + > + /* We always return 1 here because we don't have enough information > + about possible overlap of addresses that they want to watch. As an > + extreme example, consider the case where all the watchpoints watch > + the same address and the same region length: then we can handle a > + virtually unlimited number of watchpoints, due to debug register > + sharing implemented via reference counts. */ > + return 1; > +} > + > +/* Insert a hardware-assisted breakpoint at BP_TGT->reqstd_address. > + Return 0 on success, -1 on failure. */ > + > +int > +aarch64_insert_hw_breakpoint (struct gdbarch *gdbarch, > + struct bp_target_info *bp_tgt) > +{ > + int ret; > + CORE_ADDR addr = bp_tgt->placed_address = bp_tgt->reqstd_address; > + int len; > + const enum target_hw_bp_type type = hw_execute; > + struct aarch64_debug_reg_state *state > + = aarch64_get_debug_reg_state (inferior_ptid.pid ()); > + > + gdbarch_breakpoint_from_pc (gdbarch, &addr, &len); > + > + if (show_debug_regs) > + fprintf_unfiltered > + (gdb_stdlog, > + "insert_hw_breakpoint on entry (addr=0x%08lx, len=%d))\n", > + (unsigned long) addr, len); > + > + ret = aarch64_handle_breakpoint (type, addr, len, 1 /* is_insert */, > + inferior_ptid, state); > + > + if (show_debug_regs) > + { > + aarch64_show_debug_reg_state (state, > + "insert_hw_breakpoint", addr, len, type); > + } > + > + return ret; > +} > + > +/* Remove a hardware-assisted breakpoint at BP_TGT->placed_address. > + Return 0 on success, -1 on failure. */ > + > +int > +aarch64_remove_hw_breakpoint (struct gdbarch *gdbarch, > + struct bp_target_info *bp_tgt) > +{ > + int ret; > + CORE_ADDR addr = bp_tgt->placed_address; > + int len = 4; > + const enum target_hw_bp_type type = hw_execute; > + struct aarch64_debug_reg_state *state > + = aarch64_get_debug_reg_state (inferior_ptid.pid ()); > + > + gdbarch_breakpoint_from_pc (gdbarch, &addr, &len); > + > + if (show_debug_regs) > + fprintf_unfiltered > + (gdb_stdlog, "remove_hw_breakpoint on entry (addr=0x%08lx, len=%d))\n", > + (unsigned long) addr, len); > + > + ret = aarch64_handle_breakpoint (type, addr, len, 0 /* is_insert */, > + inferior_ptid, state); > + > + if (show_debug_regs) > + { > + aarch64_show_debug_reg_state (state, > + "remove_hw_watchpoint", addr, len, type); > + } > + > + return ret; > +} > + > +/* Insert a watchpoint to watch a memory region which starts at > + address ADDR and whose length is LEN bytes. Watch memory accesses > + of the type TYPE. Return 0 on success, -1 on failure. */ > + > +int > +aarch64_insert_watchpoint (CORE_ADDR addr, int len, enum target_hw_bp_type type, > + struct expression *cond) > +{ > + int ret; > + struct aarch64_debug_reg_state *state > + = aarch64_get_debug_reg_state (inferior_ptid.pid ()); > + > + if (show_debug_regs) > + fprintf_unfiltered (gdb_stdlog, > + "insert_watchpoint on entry (addr=0x%08lx, len=%d)\n", > + (unsigned long) addr, len); > + > + gdb_assert (type != hw_execute); > + > + ret = aarch64_handle_watchpoint (type, addr, len, 1 /* is_insert */, > + inferior_ptid, state); > + > + if (show_debug_regs) > + { > + aarch64_show_debug_reg_state (state, > + "insert_watchpoint", addr, len, type); > + } > + > + return ret; > +} > + > +/* Remove a watchpoint that watched the memory region which starts at > + address ADDR, whose length is LEN bytes, and for accesses of the > + type TYPE. Return 0 on success, -1 on failure. */ > + > +int > +aarch64_remove_watchpoint (CORE_ADDR addr, int len, enum target_hw_bp_type type, > + struct expression *cond) > +{ > + int ret; > + struct aarch64_debug_reg_state *state > + = aarch64_get_debug_reg_state (inferior_ptid.pid ()); > + > + if (show_debug_regs) > + fprintf_unfiltered (gdb_stdlog, > + "remove_watchpoint on entry (addr=0x%08lx, len=%d)\n", > + (unsigned long) addr, len); > + > + gdb_assert (type != hw_execute); > + > + ret = aarch64_handle_watchpoint (type, addr, len, 0 /* is_insert */, > + inferior_ptid, state); > + > + if (show_debug_regs) > + { > + aarch64_show_debug_reg_state (state, > + "remove_watchpoint", addr, len, type); > + } > + > + return ret; > +} > + > +/* See aarch64-nat.h. */ > + > +bool > +aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state, > + CORE_ADDR addr_trap, CORE_ADDR *addr_p) > +{ > + int i; Nit: We could declare i in the for loop below. > + > + for (i = aarch64_num_wp_regs - 1; i >= 0; --i) > + { > + const unsigned int offset > + = aarch64_watchpoint_offset (state->dr_ctrl_wp[i]); > + const unsigned int len = 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); > + const CORE_ADDR addr_orig = state->dr_addr_orig_wp[i]; > + > + if (state->dr_ref_count_wp[i] > + && DR_CONTROL_ENABLED (state->dr_ctrl_wp[i]) > + && addr_trap >= addr_watch_aligned > + && addr_trap < addr_watch + len) > + { > + /* ADDR_TRAP reports the first address of the memory range > + accessed by the CPU, regardless of what was the memory > + range watched. Thus, a large CPU access that straddles > + the ADDR_WATCH..ADDR_WATCH+LEN range may result in an > + ADDR_TRAP that is lower than the > + ADDR_WATCH..ADDR_WATCH+LEN range. E.g.: > + > + addr: | 4 | 5 | 6 | 7 | 8 | > + |---- range watched ----| > + |----------- range accessed ------------| > + > + In this case, ADDR_TRAP will be 4. > + > + To match a watchpoint known to GDB core, we must never > + report *ADDR_P outside of any ADDR_WATCH..ADDR_WATCH+LEN > + range. ADDR_WATCH <= ADDR_TRAP < ADDR_ORIG is a false > + positive on kernels older than 4.10. See PR > + external/20207. */ > + *addr_p = addr_orig; > + return true; > + } > + } > + > + return false; > +} > + > +/* Define AArch64 maintenance commands. */ > + > +static void > +add_show_debug_regs_command (void) > +{ > + /* A maintenance command to enable printing the internal DRi mirror > + variables. */ > + add_setshow_boolean_cmd ("show-debug-regs", class_maintenance, > + &show_debug_regs, _("\ > +Set whether to show variables that mirror the AArch64 debug registers."), _("\ > +Show whether to show variables that mirror the AArch64 debug registers."), _("\ > +Use \"on\" to enable, \"off\" to disable.\n\ > +If enabled, the debug registers values are shown when GDB inserts\n\ > +or removes a hardware breakpoint or watchpoint, and when the inferior\n\ > +triggers a breakpoint or watchpoint."), > + NULL, > + NULL, > + &maintenance_set_cmdlist, > + &maintenance_show_cmdlist); > +} > + > +void > +aarch64_initialize_hw_point () > +{ > + add_show_debug_regs_command (); > +} > diff --git a/gdb/aarch64-nat.h b/gdb/aarch64-nat.h > new file mode 100644 > index 00000000000..56e720f02ee > --- /dev/null > +++ b/gdb/aarch64-nat.h > @@ -0,0 +1,109 @@ > +/* Native-dependent code for AArch64. > + > + Copyright (C) 2011-2022 Free Software Foundation, Inc. > + > + This file is part of GDB. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see . */ > + > +#ifndef AARCH64_NAT_H > +#define AARCH64_NAT_H > + > +#include "breakpoint.h" > +#include "nat/aarch64-hw-point.h" > +#include "target.h" > + > +/* Hardware-assisted breakpoints and watchpoints. */ > + > +/* Initialize platform-independent state for hardware-assisted > + breakpoints and watchpoints. */ > + > +void aarch64_initialize_hw_point (); > + > +/* Return the debug register state for process PID. If no existing > + state is found for this process, return nullptr. */ > + > +struct aarch64_debug_reg_state *aarch64_lookup_debug_reg_state (pid_t pid); > + > +/* Return the debug register state for process PID. If no existing > + state is found for this process, create new state. */ > + > +struct aarch64_debug_reg_state *aarch64_get_debug_reg_state (pid_t pid); > + > +/* Remove any existing per-process debug state for process PID. */ > + > +void aarch64_remove_debug_reg_state (pid_t pid); > + > +/* Helper for the "stopped_data_address" target method. Returns TRUE > + if a hardware watchpoint trap at ADDR_TRAP matches a set > + watchpoint. The address of the matched watchpoint is returned in > + *ADDR_P. */ > + > +bool aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state, > + CORE_ADDR addr_trap, CORE_ADDR *addr_p); > + > +/* Helper functions used by aarch64_nat_target below. See their > + definitions. */ > + > +int aarch64_can_use_hw_breakpoint (enum bptype type, int cnt, int othertype); > +int aarch64_insert_watchpoint (CORE_ADDR addr, int len, > + enum target_hw_bp_type type, > + struct expression *cond); > +int aarch64_remove_watchpoint (CORE_ADDR addr, int len, > + enum target_hw_bp_type type, > + struct expression *cond); > +int aarch64_insert_hw_breakpoint (struct gdbarch *gdbarch, > + struct bp_target_info *bp_tgt); > +int aarch64_remove_hw_breakpoint (struct gdbarch *gdbarch, > + struct bp_target_info *bp_tgt); > +int aarch64_stopped_by_hw_breakpoint (); > + > +/* Convenience template mixin used to add aarch64 watchpoints support to a > + target. */ > + > +template > +struct aarch64_nat_target : public BaseTarget > +{ > + /* Hook in common aarch64 hardware watchpoints/breakpoints support. */ > + > + int can_use_hw_breakpoint (enum bptype type, int cnt, int othertype) override > + { return aarch64_can_use_hw_breakpoint (type, cnt, othertype); } > + > + int region_ok_for_hw_watchpoint (CORE_ADDR addr, int len) override > + { return aarch64_region_ok_for_watchpoint (addr, len); } > + > + int insert_watchpoint (CORE_ADDR addr, int len, > + enum target_hw_bp_type type, > + struct expression *cond) override > + { return aarch64_insert_watchpoint (addr, len, type, cond); } > + > + int remove_watchpoint (CORE_ADDR addr, int len, > + enum target_hw_bp_type type, > + struct expression *cond) override > + { return aarch64_remove_watchpoint (addr, len, type, cond); } > + > + int insert_hw_breakpoint (struct gdbarch *gdbarch, > + struct bp_target_info *bp_tgt) override > + { return aarch64_insert_hw_breakpoint (gdbarch, bp_tgt); } > + > + int remove_hw_breakpoint (struct gdbarch *gdbarch, > + struct bp_target_info *bp_tgt) override > + { return aarch64_remove_hw_breakpoint (gdbarch, bp_tgt); } > + > + bool watchpoint_addr_within_range (CORE_ADDR addr, CORE_ADDR start, > + int length) override > + { return start <= addr && start + length - 1 >= addr; } > +}; > + > +#endif /* AARCH64_NAT_H */ > diff --git a/gdb/configure.nat b/gdb/configure.nat > index ad6d35babc2..4f5850dd595 100644 > --- a/gdb/configure.nat > +++ b/gdb/configure.nat > @@ -233,7 +233,7 @@ case ${gdb_host} in > case ${gdb_host_cpu} in > aarch64) > # Host: AArch64 based machine running GNU/Linux > - NATDEPFILES="${NATDEPFILES} aarch64-linux-nat.o \ > + NATDEPFILES="${NATDEPFILES} aarch64-nat.o aarch64-linux-nat.o \ > aarch32-linux-nat.o nat/aarch64-hw-point.o \ > nat/aarch64-linux-hw-point.o \ > nat/aarch64-linux.o \