From patchwork Mon Apr 3 13:18:15 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antoine Tremblay X-Patchwork-Id: 19794 Received: (qmail 31367 invoked by alias); 3 Apr 2017 13:18:55 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 28583 invoked by uid 89); 3 Apr 2017 13:18:53 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.2 spammy=We'll, Advance, 29031, 634 X-HELO: sessmg23.ericsson.net Received: from sessmg23.ericsson.net (HELO sessmg23.ericsson.net) (193.180.251.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 03 Apr 2017 13:18:50 +0000 Received: from ESESSHC009.ericsson.se (Unknown_Domain [153.88.183.45]) by (Symantec Mail Security) with SMTP id FA.47.13281.8BB42E85; Mon, 3 Apr 2017 15:18:48 +0200 (CEST) Received: from EUR03-DB5-obe.outbound.protection.outlook.com (153.88.183.145) by oa.msg.ericsson.com (153.88.183.45) with Microsoft SMTP Server (TLS) id 14.3.339.0; Mon, 3 Apr 2017 15:18:47 +0200 Authentication-Results: sourceware.org; dkim=none (message not signed) header.d=none; sourceware.org; dmarc=none action=none header.from=ericsson.com; Received: from elxa4wqvvz1 (192.75.88.130) by VI1PR0701MB1887.eurprd07.prod.outlook.com (10.167.197.23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1019.8; Mon, 3 Apr 2017 13:18:41 +0000 References: <20161129120702.9490-1-antoine.tremblay@ericsson.com> <20170127150139.GB24676@E107787-LIN> <2255ed6f-a146-026c-f871-00e9a33dfcf0@redhat.com> <86d1cy4umo.fsf@gmail.com> <86d1cxwgpk.fsf@gmail.com> <86h925ll3f.fsf@gmail.com> User-agent: mu4e 0.9.19; emacs 25.1.1 From: Antoine Tremblay To: Yao Qi CC: Antoine Tremblay , Pedro Alves , "gdb-patches@sourceware.org" Subject: Re: [PATCH 1/2] This patch fixes GDBServer's run control for single stepping In-Reply-To: <86h925ll3f.fsf@gmail.com> Date: Mon, 3 Apr 2017 09:18:15 -0400 Message-ID: MIME-Version: 1.0 X-ClientProxiedBy: DM3PR12CA0045.namprd12.prod.outlook.com (10.161.151.13) To VI1PR0701MB1887.eurprd07.prod.outlook.com (10.167.197.23) X-MS-Office365-Filtering-Correlation-Id: 277b7eac-b0f6-4367-c75a-08d47a93f576 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(201703131423075)(201703031133081); SRVR:VI1PR0701MB1887; X-Microsoft-Exchange-Diagnostics: 1; VI1PR0701MB1887; 3:VEFID7/nJiNJM2m13zMlIo5CldB6SVBS4sQkDR1iZPH8us1GyJgYl0UI2u4S0wfrMsWFrKj0SNWnfC3b5bl3x+VCudWPe4+I7NMBkJcellpBy7onvX5/HfGruJuMYi4mJyUrbh0pxG/ZLbgbbvVUCE/Tm62PP0/MhbmTvj137nOuSpV6ptG5VSSDvQENzsn6FIYbKcRcpIoVkNjQ9oIsMSQETGWwppMjvaE5NswZ6iAXFblMCn65r2KHhrURiUp67CRWpGhcKDFiDzMz41AuSrYSyHBW9rFqdVuH/cFz98Qa+n15q7lCtNC/Gr+7g4Hpy8Otjk0DhfbbwjPvjyVZDw==; 25:2v/bTI0lGSBfnTpqO/rySRuUNhRWU1zToO6Aec5P2Ixw3XcSAGVFaKZ25xOBEY0/hgUCjexbsHtU4n7y9rvekkojrGrydzrdJqvPUMWYvIx3pG5j1pTCol94l/O9Qq/3nl3xv1hFR29g8v5VIJYyA93PpFSZ/p+s7uGYmw4ucAgB78KE69K1AX3+Mn0CrXOtv3kkB4BPax/RD69dy/Wt4UQxNUG8bzxhXag5YGqwxMtxIJk0z4ekcpRe3NizYezhfxaoEqwkryknHoC18u42YMk/0x6uyG8+uwRkxbWKwDiKPXnKkxCtYBdVEod0Sc7pcqQGetrKjA8D80iA2XpNUiM0EZKgZs3NBFIXXzMAb8/uEAEe9wuKnsQ7KsiQVTmgVB2LVqRMh2Dkw25VNefU0tvmLrQ/n4ttxG5sdDyaI5R/3Bk9tGx9ATE/YWb/IPrIZojBa8en5KdOeQ/jJ4WCkA== X-Microsoft-Exchange-Diagnostics: 1; VI1PR0701MB1887; 31:qQJETNBK7rJTYnmFZd/YI2I2u6FVbhSyfZdonNrFoHCqOO3L3FrQpxpWTSoVaFG6DVXyMFb5UZoF+oMG4XV076lqzXL0AaVEIZcRSla7MNX8Z0pCA3955NIFegTQ48HP/RH4sK3TsHTiTCS2W2+0HDIpHDP4gCTNJw3n/K3CUtsBHdWKzpg4NbrDpAv+ra9HoHkF5scHk9psEuLzBH1QTLkOEqXagxjizZ/Mw+rbKjj8w2Z2koMEq8c6FIDoyTLX; 20:2H5LhpnvB1QByevrwDo1JChkIclK0fo5GQ4YehM2muDz0BbC+QVKcEo4BvtFtTfOAwv18zBNxKjfjlwlxx/a9M46DSbYS7jZNOWHMEXjwYfk7ss/QVCZyB05cAzgwfCJ6lPJt5QlmcIb2auQgWKDBi5Agwf2lFQ1quWl8lFfNKOpB+bF06U/LOCQgBZ5+wKva35s/fIc03277YuCGggWKRh4HVBIklZ2EoM2qfb2VjsXzPUwryWuNubCw1u9iqLRqHJh0M4h6gXeVWQbWVwdxma/ydl9eiBYbV4jIHuhqXcvhms7h4BHH6K/9PeMEiPe6fCRCjtLdVYjOeOiy4xWYPV/Ey/Vf8zPMbeIYdwAogZQeoYUmghVmUluoD8+/b4Lsgr1gLlCxakJNSnu2UJMgFLCgcdzF4Fg0gTYwqcxV0DGqe7DWsq4jKzPDun8LgEsVK72Lmo8n3hVlTQz07GuXU+08tjqLgAzL2Psemtx01ddkXeKnuAeGE60mdkcml7H X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(37575265505322); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040450)(601004)(2401047)(8121501046)(5005006)(10201501046)(93006095)(93001095)(3002001)(6041248)(20161123560025)(20161123564025)(20161123562025)(20161123555025)(201703131423075)(201702281528075)(201703061421075)(6072148); SRVR:VI1PR0701MB1887; BCL:0; PCL:0; RULEID:; SRVR:VI1PR0701MB1887; X-Microsoft-Exchange-Diagnostics: 1; VI1PR0701MB1887; 4:wjF1mQ//t/ma9R/H+Xjwx/12g/pppYbyUqdpM6dM1kCmmktVRh+bCftYUqlFBd4RETPX0Ab11+JiO3D0coGzJVxQ6Rq2CuWVlE0FGbBs9nl6EifqPD698xz4zj8h1KDfoRKYduTa9g1D2m9UsFP6l74MRQ+9uDWdlkU3J79HDN9WEOnqpivWPpf3aKgSHpxS/bdlBdGxOxorxjswfw8ed7lAMFi9ESZa4PPhBo7i2+ymVPMgKW3N0gTRWrowqAweTD3rR7WBs0d6THpvC0xLzG3urpzhx/O0AKS8WMYfn3iDVuKng2y3PfEN+bLg1VT513FFz1s1vWpcrmluUeHhSV5xndZ0Tx7jbHhnfdRfHM0KC7rGcro98VIQga4h1czRhv/YV/IiI9t81qjmU5jMa5Owycg5tKjXidPFlLcuUCxr7R55aULcvwRgidFqtvzC8vYvTTKe9HjHMHovViO1rfWUJ1PVyqHmEMNuiJvNTE3Y4s2yMFFVsdnmB2mHgQPtX21GzTIODc7hdtSC6616Nbh62j6gPElPpNG4N0ON8ODx6QBZrch/kYWir67cMjx9Z3ST5xDHBjHVkWye6u5TSto1KPavE7KeiVylGSzE7gLeZy7wkiuSwfXVPWiXAkLqsVvJ9/hHM7RT06FYONGm1XRatrSNINj4rZK0Eqy4cQapr553Us804myvNLC7gRKyA0XXu/FoIjZT6YaPU4uwhLHhnntATmRy0YXqdjgX1Dn4p6xLDszdTbhyRprgM3XsO5lvkecoj0LR9WGFucwWww== X-Forefront-PRVS: 0266491E90 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4630300001)(6009001)(39840400002)(39860400002)(39410400002)(39450400003)(39850400002)(39400400002)(38730400002)(3846002)(6116002)(81166006)(8676002)(110136004)(5660300001)(1411001)(54356999)(42186005)(76176999)(5003940100001)(189998001)(2906002)(4001350100001)(50986999)(6666003)(2950100002)(6916009)(33646002)(6496005)(86362001)(575784001)(36756003)(66066001)(54906002)(83506001)(305945005)(6246003)(7736002)(53936002)(47776003)(4326008)(25786009)(229853002)(48376002)(6486002)(50466002); DIR:OUT; SFP:1101; SCL:1; SRVR:VI1PR0701MB1887; H:elxa4wqvvz1; FPR:; SPF:None; MLV:sfv; LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; VI1PR0701MB1887; 23:FinSHT+WgzvxJZzlxDiDrJ5h8a2GHNC1fdFneAt?= =?us-ascii?Q?BPDWZv7cN6vg31JJOvL2Lz9ESSDf9k9JSiTj2FTVtv+HQc7yq27AeJSsoNLw?= =?us-ascii?Q?+h0q7Jtpj0NhVLlLMpuBp3qZkTgPmBPZOpKhEc58kIoWTyPuVDRXCr7nymia?= =?us-ascii?Q?H+RwlFhkzywBENGETxtmVSBDaC4XsST+99ky2GYpgFqdQ9FpcydHKhy0A2ky?= =?us-ascii?Q?f6ci11ov3jt06O2TUgvEGptEiFypF/kYohWaIY51GCLlL2NwFUHEqNWa20yJ?= =?us-ascii?Q?r4NXFJDAjeldvlpNYNovtg0kgqDt7NAoWW5lUQn2ljF/RrbYAV7fKkHTxxmM?= =?us-ascii?Q?pjsEoSu0ohaonftHwQLkpD0jpqzHTE40YAyT7XVlG4e6Q8TQIQI9drl8msl5?= =?us-ascii?Q?ENa0rpUW5q0lI978j1auJtFtx17CGF6PQ579C9bpG711uVFNStA7qicTHKaS?= =?us-ascii?Q?h5HEmcUcTG6DXWdaZPf02zu3+LbQn9wpRI6b9WScnE66EeqwaHF1LGM6wMY+?= =?us-ascii?Q?HkumqomhSsVe4LflQc5aV6KwuNGU8OrHcsOEvoZjYJqD+XYoZ6WKdGZCMPS4?= =?us-ascii?Q?39Uod9MFVEU7mwQujfb7S7PiOohn/neqfT5g6fwRPiHlx012T3dtdYtiHEVC?= =?us-ascii?Q?8HU/kU6iG7TMyQZdP7WLxU+BO6dZCOfyUz+4OqR87W9YH4ZXK2ijAYAUW0QR?= =?us-ascii?Q?qOdiF+cW3NH+ff1saeNIReIPcv58kbNq2fVmf1wFlGJqMG4D9qDIaWKENJm8?= =?us-ascii?Q?nbVH7uTucpej2ltCwlXEiG3yg/VPmd5yCkRNBmpNSSGTFwFQ94G12YBVvPky?= =?us-ascii?Q?JNwEfYwxkUp23Hy0yW+qi9ZECiXk2DfGs1KgsFbNm9kOzDW/MYrAqjDoHbLD?= =?us-ascii?Q?T1kSYtE9G1jOn3eCdZb8rVgTk+V7Gpb1uX45xcEviZjuZqet88ydaxUANSjt?= =?us-ascii?Q?xJ7NtMIWlDZmUn8UHaOy5cqx/U1JO64TO7E3U4pyJw+3IfA+XzB1T9h2c+68?= =?us-ascii?Q?NvYMeObtKTuH+K0DwoktQJRvq8zGLwPM2oj5/TT1HdjgyjFvmtFjwRG8/IJ1?= =?us-ascii?Q?jefqc42ptfmxdnGNq+eGxBoxXOjD4S1NfgoG2w6eZH0gSlLg2aMAEfOuDo27?= =?us-ascii?Q?QZh0vWbVbA0b/rE+oKHZgkwMFry5gJcdF2g0DN2KGvJ09Yxt5/qHorA=3D?= =?us-ascii?Q?=3D?= X-Microsoft-Exchange-Diagnostics: 1; VI1PR0701MB1887; 6:DT/k7x2IRGyevaf/dXDNSxCY6sAp1B4a6CvF7+vOGXFQ7P+BaKP+QADKwD06vFn9ucrSd+p+U1rfhkk8h53v0X7ZYbQC74gkDI/8Qew8Wmk9Q1Z1Vq3L26lZhifvgETqRSf8gNgioJUVJ/wHXICf9C6gvk0L+wDLB2uwDWBVtBChBFscVgrX6yrwg15R71uqXVaUCtXKa0/s7wRnEFjHWaQR4LUHlDcD1We/cYdM9aqkdwbay9/7a+qO0VroY0FqP69UT9VpBWnkCQEdyis8v8nOiZ6jD/qIgzhSQzNuO/2tkFZxJ2HwKrziHqAY89pNzbwY0GUwijYuOTai9WLbBATF3Cr/Nqy/Wz4hRlPwwvJKOWLTOeKply5IUBsDWoFnEHIHZoERdlRZbwwFG+VL5A==; 5:YZ7H+7r992WP1/vxYt/YpnGkBZwEP0gih/Mcti+qII3a6cT/nsun8/Elc7Xi5Sr3TB2bl3pbfrTPQZajzUBcDaFDgaGvZjhZb7mxPBpID5SU1kw5kgL8ituUZhywA/N5rTWjNaMwB/lBFdovlB3znQ==; 24:bL0IncfuGuYe2UEp1RhWw3GH3OAP/84b5avW3n7zpH3FP2gU1BhqBwPDyTOER87pyk6u/cfTsZi2PzhdP3yQ5quaj5bdrwB3IRwNsoqwi7g= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; VI1PR0701MB1887; 7:/kx/iIecDrZkL93DAvN2tBc6aPmiB9LWtVXOd04fQkzNeMDy8moJbAhvZBQpu0jzBG0JpkwJbNyEX7hyqaOeAAKnGwlfpDnfxAriD1hk1s4BWZu9f0gKE/ecMjdmZ+ZJkF++VpO8qb+jfq9M54Si6lDCTittj2hd5j4RfPzr4SjpqjkLmGmv4+8eLcj7leyIs99qgmjf71bCuUA+rRbbSydsypdC96sRx6faOnu5k12Srr3tu8vS5eSgzc6V0dOWCYGVKF3HbQTktodLeS7CTzKJKQZRnKNKGAcukO9LYAmlLJ0vO2tUa/A+d7Z45EOvawtSguKl3QWbgevpQsafyA== X-MS-Exchange-CrossTenant-OriginalArrivalTime: 03 Apr 2017 13:18:41.5720 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0701MB1887 X-OriginatorOrg: ericsson.com X-IsSubscribed: yes Yao Qi writes: > Antoine Tremblay writes: > >> I think maybe the best solution would be to abstract only that part of >> get_next_pc in a function: the if block starting with if >> (self->has_thumb2_breakpoint) around line 301. >> >> And have only that part return the next_pc + the breakpoint kind, this >> would avoid breaking all the virtual get_next_pc functions just for that >> case and allow the same code to be used in kind_from_current_state. >> >> We'll still redo the work but at least the code will be in one >> place. WDYT ? > > That should be fine, although I am not exactly sure what are you > going to do. It looks like this, comments ?: ---- commit 9a8b46f9038e9d3805c8e6ec1bdf0dff1c95c065 Author: Antoine Tremblay Date: Mon Apr 3 09:13:20 2017 -0400 refactor get-next-pc --- gdb/arch/arm-get-next-pcs.c | 199 ++++++++++++++++++++++---------------- gdb/arch/arm-get-next-pcs.h | 9 ++ gdb/gdbserver/linux-aarch32-low.c | 46 ++++++++- gdb/gdbserver/linux-aarch32-low.h | 3 + gdb/gdbserver/linux-arm-low.c | 21 ---- gdb/gdbserver/mem-break.c | 16 ++- 6 files changed, 188 insertions(+), 106 deletions(-) diff --git a/gdb/arch/arm-get-next-pcs.c b/gdb/arch/arm-get-next-pcs.c index 398dd59a..d967e16 100644 --- a/gdb/arch/arm-get-next-pcs.c +++ b/gdb/arch/arm-get-next-pcs.c @@ -22,6 +22,7 @@ #include "common-regcache.h" #include "arm.h" #include "arm-get-next-pcs.h" +#include /* See arm-get-next-pcs.h. */ @@ -258,6 +259,115 @@ arm_deal_with_atomic_sequence_raw (struct arm_get_next_pcs *self) return next_pcs; } +/* See arm-get-next-pcs.h. */ + +std::vector > +thumb_get_next_pcs_raw_itblock +(CORE_ADDR pc, unsigned short inst1, + ULONGEST status, ULONGEST itstate, + ULONGEST (*read_mem_uint) (CORE_ADDR memaddr, int len, int byte_order), + int byte_order_for_code) +{ + std::vector > next_pcs; + + if ((inst1 & 0xff00) == 0xbf00 && (inst1 & 0x000f) != 0) + { + /* An IT instruction. Because this instruction does not + modify the flags, we can accurately predict the next + executed instruction. */ + itstate = inst1 & 0x00ff; + pc += thumb_insn_size (inst1); + + while (itstate != 0 && ! condition_true (itstate >> 4, status)) + { + inst1 = read_mem_uint (pc, 2,byte_order_for_code); + pc += thumb_insn_size (inst1); + itstate = thumb_advance_itstate (itstate); + } + next_pcs.push_back (std::pair + (MAKE_THUMB_ADDR (pc), ARM_BP_KIND_THUMB2)); + return next_pcs; + } + else if (itstate != 0) + { + /* We are in a conditional block. Check the condition. */ + if (! condition_true (itstate >> 4, status)) + { + /* Advance to the next executed instruction. */ + pc += thumb_insn_size (inst1); + itstate = thumb_advance_itstate (itstate); + + while (itstate != 0 && ! condition_true (itstate >> 4, status)) + { + inst1 = read_mem_uint (pc, 2, byte_order_for_code); + + pc += thumb_insn_size (inst1); + itstate = thumb_advance_itstate (itstate); + } + + next_pcs.push_back (std::pair + (MAKE_THUMB_ADDR (pc), ARM_BP_KIND_THUMB2)); + return next_pcs; + } + else if ((itstate & 0x0f) == 0x08) + { + /* This is the last instruction of the conditional + block, and it is executed. We can handle it normally + because the following instruction is not conditional, + and we must handle it normally because it is + permitted to branch. Fall through. */ + } + else + { + int cond_negated; + + /* There are conditional instructions after this one. + If this instruction modifies the flags, then we can + not predict what the next executed instruction will + be. Fortunately, this instruction is archi2tecturally + forbidden to branch; we know it will fall through. + Start by skipping past it. */ + pc += thumb_insn_size (inst1); + itstate = thumb_advance_itstate (itstate); + + /* Set a breakpoint on the following instruction. */ + gdb_assert ((itstate & 0x0f) != 0); + next_pcs.push_back (std::pair + (MAKE_THUMB_ADDR (pc), ARM_BP_KIND_THUMB2)); + + cond_negated = (itstate >> 4) & 1; + + /* Skip all following instructions with the same + condition. If there is a later instruction in the IT + block with the opposite condition, set the other + breakpoint there. If not, then set a breakpoint on + the instruction after the IT block. */ + do + { + inst1 = read_mem_uint (pc, 2, byte_order_for_code); + pc += thumb_insn_size (inst1); + itstate = thumb_advance_itstate (itstate); + } + while (itstate != 0 && ((itstate >> 4) & 1) == cond_negated); + + if (itstate != 0 && ((itstate >> 4) & 1) == cond_negated) + { + next_pcs.push_back (std::pair + (MAKE_THUMB_ADDR (pc), ARM_BP_KIND_THUMB2)); + } + else + { + next_pcs.push_back (std::pair + (MAKE_THUMB_ADDR (pc), ARM_BP_KIND_THUMB)); + } + + return next_pcs; + } + } + + return next_pcs; +} + /* Find the next possible PCs for thumb mode. */ static VEC (CORE_ADDR) * @@ -300,89 +410,14 @@ thumb_get_next_pcs_raw (struct arm_get_next_pcs *self) if (self->has_thumb2_breakpoint) { - if ((inst1 & 0xff00) == 0xbf00 && (inst1 & 0x000f) != 0) - { - /* An IT instruction. Because this instruction does not - modify the flags, we can accurately predict the next - executed instruction. */ - itstate = inst1 & 0x00ff; - pc += thumb_insn_size (inst1); - - while (itstate != 0 && ! condition_true (itstate >> 4, status)) - { - inst1 = self->ops->read_mem_uint (pc, 2,byte_order_for_code); - pc += thumb_insn_size (inst1); - itstate = thumb_advance_itstate (itstate); - } - - VEC_safe_push (CORE_ADDR, next_pcs, MAKE_THUMB_ADDR (pc)); - return next_pcs; - } - else if (itstate != 0) - { - /* We are in a conditional block. Check the condition. */ - if (! condition_true (itstate >> 4, status)) - { - /* Advance to the next executed instruction. */ - pc += thumb_insn_size (inst1); - itstate = thumb_advance_itstate (itstate); + std::vector > itblock_next_pcs + = thumb_get_next_pcs_raw_itblock + (pc, inst1, status, itstate, self->ops->read_mem_uint, + byte_order_for_code); - while (itstate != 0 && ! condition_true (itstate >> 4, status)) - { - inst1 = self->ops->read_mem_uint (pc, 2, byte_order_for_code); - - pc += thumb_insn_size (inst1); - itstate = thumb_advance_itstate (itstate); - } - - VEC_safe_push (CORE_ADDR, next_pcs, MAKE_THUMB_ADDR (pc)); - return next_pcs; - } - else if ((itstate & 0x0f) == 0x08) - { - /* This is the last instruction of the conditional - block, and it is executed. We can handle it normally - because the following instruction is not conditional, - and we must handle it normally because it is - permitted to branch. Fall through. */ - } - else - { - int cond_negated; - - /* There are conditional instructions after this one. - If this instruction modifies the flags, then we can - not predict what the next executed instruction will - be. Fortunately, this instruction is architecturally - forbidden to branch; we know it will fall through. - Start by skipping past it. */ - pc += thumb_insn_size (inst1); - itstate = thumb_advance_itstate (itstate); - - /* Set a breakpoint on the following instruction. */ - gdb_assert ((itstate & 0x0f) != 0); - VEC_safe_push (CORE_ADDR, next_pcs, MAKE_THUMB_ADDR (pc)); - - cond_negated = (itstate >> 4) & 1; - - /* Skip all following instructions with the same - condition. If there is a later instruction in the IT - block with the opposite condition, set the other - breakpoint there. If not, then set a breakpoint on - the instruction after the IT block. */ - do - { - inst1 = self->ops->read_mem_uint (pc, 2, byte_order_for_code); - pc += thumb_insn_size (inst1); - itstate = thumb_advance_itstate (itstate); - } - while (itstate != 0 && ((itstate >> 4) & 1) == cond_negated); - - VEC_safe_push (CORE_ADDR, next_pcs, MAKE_THUMB_ADDR (pc)); - - return next_pcs; - } - } + for(auto const &nextpc : itblock_next_pcs) { + VEC_safe_push (CORE_ADDR, next_pcs, nextpc.first); + } } else if (itstate & 0x0f) { diff --git a/gdb/arch/arm-get-next-pcs.h b/gdb/arch/arm-get-next-pcs.h index 2300ac1..830844b 100644 --- a/gdb/arch/arm-get-next-pcs.h +++ b/gdb/arch/arm-get-next-pcs.h @@ -20,6 +20,7 @@ #ifndef ARM_GET_NEXT_PCS_H #define ARM_GET_NEXT_PCS_H 1 #include "gdb_vecs.h" +#include /* Forward declaration. */ struct arm_get_next_pcs; @@ -63,4 +64,12 @@ void arm_get_next_pcs_ctor (struct arm_get_next_pcs *self, /* Find the next possible PCs after the current instruction executes. */ VEC (CORE_ADDR) *arm_get_next_pcs (struct arm_get_next_pcs *self); +/* Return the next possible PCs after PC if those are in a thumb2 it block. */ +std::vector > +thumb_get_next_pcs_raw_itblock +(CORE_ADDR pc, unsigned short inst1, + ULONGEST status, ULONGEST itstate, + ULONGEST (*read_mem_uint) (CORE_ADDR memaddr, int len, int byte_order), + int byte_order_for_code); + #endif /* ARM_GET_NEXT_PCS_H */ diff --git a/gdb/gdbserver/linux-aarch32-low.c b/gdb/gdbserver/linux-aarch32-low.c index 2b710ba..ff4869f 100644 --- a/gdb/gdbserver/linux-aarch32-low.c +++ b/gdb/gdbserver/linux-aarch32-low.c @@ -18,6 +18,7 @@ #include "server.h" #include "arch/arm.h" #include "arch/arm-linux.h" +#include "arch/arm-get-next-pcs.h" #include "linux-low.h" #include "linux-aarch32-low.h" @@ -28,6 +29,8 @@ #include #endif +#include + /* Correct in either endianness. */ #define arm_abi_breakpoint 0xef9f0001UL @@ -287,8 +290,31 @@ arm_breakpoint_kind_from_current_state (CORE_ADDR *pcptr) { if (arm_is_thumb_mode ()) { - *pcptr = MAKE_THUMB_ADDR (*pcptr); - return arm_breakpoint_kind_from_pc (pcptr); + struct regcache *regcache = get_thread_regcache (current_thread, 1); + CORE_ADDR pc = regcache_read_pc (regcache); + ULONGEST status, itstate; + unsigned short inst1; + + *pcptr = UNMAKE_THUMB_ADDR (*pcptr); + + inst1 = get_next_pcs_read_memory_unsigned_integer + (pc, 2, 0); + status = regcache_raw_get_unsigned (regcache, ARM_PS_REGNUM); + itstate = ((status >> 8) & 0xfc) | ((status >> 25) & 0x3); + + std::vector > itblock_next_pcs + = thumb_get_next_pcs_raw_itblock + (pc, inst1, status, itstate, + get_next_pcs_read_memory_unsigned_integer, + 0); + + /* If this PC is in an itblock let thumb_get_next_pcs_raw_itblock + decide the kind. */ + for(auto const &nextpc : itblock_next_pcs) { + if (MAKE_THUMB_ADDR (*pcptr) == nextpc.first) + return nextpc.second; + } + return ARM_BP_KIND_THUMB; } else { @@ -296,6 +322,22 @@ arm_breakpoint_kind_from_current_state (CORE_ADDR *pcptr) } } +/* Read memory from the inferiror. + BYTE_ORDER is ignored and there to keep compatiblity with GDB's + read_memory_unsigned_integer. */ +ULONGEST +get_next_pcs_read_memory_unsigned_integer (CORE_ADDR memaddr, + int len, + int byte_order) +{ + ULONGEST res; + + res = 0; + target_read_memory (memaddr, (unsigned char *) &res, len); + + return res; +} + void initialize_low_arch_aarch32 (void) { diff --git a/gdb/gdbserver/linux-aarch32-low.h b/gdb/gdbserver/linux-aarch32-low.h index fecfcbe..77fca32 100644 --- a/gdb/gdbserver/linux-aarch32-low.h +++ b/gdb/gdbserver/linux-aarch32-low.h @@ -27,6 +27,9 @@ int arm_breakpoint_kind_from_pc (CORE_ADDR *pcptr); const gdb_byte *arm_sw_breakpoint_from_kind (int kind , int *size); int arm_breakpoint_kind_from_current_state (CORE_ADDR *pcptr); int arm_breakpoint_at (CORE_ADDR where); +ULONGEST get_next_pcs_read_memory_unsigned_integer (CORE_ADDR memaddr, + int len, + int byte_order); void initialize_low_arch_aarch32 (void); diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c index fc2b348..fc6b5cc 100644 --- a/gdb/gdbserver/linux-arm-low.c +++ b/gdb/gdbserver/linux-arm-low.c @@ -139,11 +139,6 @@ static int arm_regmap[] = { 64 }; -/* Forward declarations needed for get_next_pcs ops. */ -static ULONGEST get_next_pcs_read_memory_unsigned_integer (CORE_ADDR memaddr, - int len, - int byte_order); - static CORE_ADDR get_next_pcs_addr_bits_remove (struct arm_get_next_pcs *self, CORE_ADDR val); @@ -252,22 +247,6 @@ get_next_pcs_is_thumb (struct arm_get_next_pcs *self) return arm_is_thumb_mode (); } -/* Read memory from the inferiror. - BYTE_ORDER is ignored and there to keep compatiblity with GDB's - read_memory_unsigned_integer. */ -static ULONGEST -get_next_pcs_read_memory_unsigned_integer (CORE_ADDR memaddr, - int len, - int byte_order) -{ - ULONGEST res; - - res = 0; - target_read_memory (memaddr, (unsigned char *) &res, len); - - return res; -} - /* Fetch the thread-local storage pointer for libthread_db. */ ps_err_e diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c index 6e6926a..f3845cf 100644 --- a/gdb/gdbserver/mem-break.c +++ b/gdb/gdbserver/mem-break.c @@ -855,7 +855,21 @@ set_breakpoint_type_at (enum bkpt_type type, CORE_ADDR where, { int err_ignored; CORE_ADDR placed_address = where; - int breakpoint_kind = target_breakpoint_kind_from_pc (&placed_address); + int breakpoint_kind; + + /* Get the kind of breakpoint to PLACED_ADDRESS except single-step + breakpoint. Get the kind of single-step breakpoint according to + the current register state. */ + if (type == single_step_breakpoint) + { + breakpoint_kind + = target_breakpoint_kind_from_current_state (&placed_address); + } + else + { + breakpoint_kind + = target_breakpoint_kind_from_pc (&placed_address); + } return set_breakpoint (type, raw_bkpt_type_sw, placed_address, breakpoint_kind, handler,