From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id wEAFO+y9Y2gYnCcAWB0awg (envelope-from ) for ; Tue, 01 Jul 2025 06:52:28 -0400 Authentication-Results: simark.ca; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=NOzT/5yN; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id EC0661E11E; Tue, 1 Jul 2025 06:52:28 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-10.1 required=5.0 tests=ARC_SIGNED,ARC_VALID, BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU, MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED, RCVD_IN_VALIDITY_RPBL,RCVD_IN_VALIDITY_SAFE autolearn=ham autolearn_force=no version=4.0.1 Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 0226E1E102 for ; Tue, 1 Jul 2025 06:52:28 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A7B9A3858294 for ; Tue, 1 Jul 2025 10:52:27 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A7B9A3858294 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=NOzT/5yN Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) by sourceware.org (Postfix) with ESMTPS id 3604D385C6E0 for ; Tue, 1 Jul 2025 10:49:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 3604D385C6E0 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 3604D385C6E0 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1751366946; cv=none; b=HAKd09YJzzAnn1yS2I17f8lQMWyU9lT9RfntyFbmGdWiLmrBNNq6olf1cNm7IG3zTDkwvuba4VMIFJ62TZUYc2mND7s0FkFEGFGoY8E7G6AFPySJqXnWAI/TI+mBMhwK+DKKZnx9Sr4eP1QkOaQcR6RgWRVS4DVVfWPPcslaeJk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1751366946; c=relaxed/simple; bh=jT7wUghaK0TmKnbP5WfExC1IGMsqGrLDKJBpbm45yK4=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=i/C3MXhXK35qeOR8D0yTUOrnjh/gLh/yKlMtRb6QGa6FuI7/ThClRwbMNAXokiD1mXzCaEApKe2FdFy9Ve7qYLKsYQuwra9+jirdkRpCfoxB/aj27m0KTYkD9kNICZxbkmSjlw3tOH3PHClX4MqlLyEOK5IXkdyuG8GLVCOMAaU= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3604D385C6E0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1751366946; x=1782902946; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=jT7wUghaK0TmKnbP5WfExC1IGMsqGrLDKJBpbm45yK4=; b=NOzT/5yNDHj1Twxk96xrLMm1KoRzLBY75rQnmrrzCvsxf9rPluqcA9nU g1UdWU2tqWN1isvMBwmdJPdMMYUVOT0mRnRtmzC5Xz8T4LBSb15eyNrjv VeQPgRWwV1Tw8HwkrRr98JSra0ttnMzZMkwrn01oGjSetluDgTwZn4PML +YnVHxY4qxTsEXHjGH63/JnemUayHQcjtjmkEQF4BDV+1CARweWKjV/4x S6IRZXrx1R7RUTM/LTEWI27invlt/ZBpOohZ+l08Ft/FE/z/XnlWsKQN0 x59sQ5/Hv7K7oOrA5x0V8DWJynXBEPgGwCVDJzj7leUz0bUVuU4pkV3/f Q==; X-CSE-ConnectionGUID: bUaeSmMmQbOULDu64fpreQ== X-CSE-MsgGUID: oD73T2enQ92R+kZ30LO5uA== X-IronPort-AV: E=McAfee;i="6800,10657,11480"; a="57306670" X-IronPort-AV: E=Sophos;i="6.16,279,1744095600"; d="scan'208";a="57306670" Received: from orviesa010.jf.intel.com ([10.64.159.150]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Jul 2025 03:49:05 -0700 X-CSE-ConnectionGUID: C/BAetxaTMiKo+/0DTlPNQ== X-CSE-MsgGUID: 8IQFDZmZTWuSqGTp18bqYw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,279,1744095600"; d="scan'208";a="153135556" Received: from gkldtt-dev-003.igk.intel.com (HELO localhost) ([10.123.221.128]) by orviesa010-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Jul 2025 03:49:05 -0700 From: Pawel Kupczak To: gdb-patches@sourceware.org Subject: [PATCH 3/3] gdb, amd64: extend the amd64 prologue analyzer to skip stack alloc Date: Tue, 1 Jul 2025 10:47:59 +0000 Message-Id: <20250701104759.52595-4-pawel.kupczak@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250701104759.52595-1-pawel.kupczak@intel.com> References: <20250701104759.52595-1-pawel.kupczak@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 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~public-inbox=simark.ca@sourceware.org Following the previous patch (gdb, amd64: extend the amd64 prologue analyzer to skip register pushes), this patch extends the analyzer further to be able to skip stack space allocation as the next prologue part, for functions with a frame pointer. Implementation was based on the i386 counterpart, which already had that functionality. As of now, the stack allocation is not skipped. Examples below use C source listed below, compiled with gcc 11.4.0. ``` int foo (int n) { int ns[] = { 1, 4, 9, 16, 25 }; return ns[n]; } int main (int argc, char **argv) { return foo (argc); } ``` Compiling with "gcc -O0 -fno-omit-frame-pointer" we get: ``` (gdb) b foo Breakpoint 1 at 0x1151 (gdb) r ... Breakpoint 1, 0x0000555555555151 in foo () (gdb) disassemble Dump of assembler code for function foo: 0x0000555555555149 <+0>: endbr64 0x000055555555514d <+4>: push %rbp 0x000055555555514e <+5>: mov %rsp,%rbp => 0x0000555555555151 <+8>: sub $0x30,%rsp 0x0000555555555155 <+12>: mov %edi,-0x24(%rbp) ... ``` With this patch, it gets skipped the same way register pushes are: ``` (gdb) b foo Breakpoint 1 at 0x1155 (gdb) r ... Breakpoint 1, 0x0000555555555155 in foo () (gdb) disassemble Dump of assembler code for function foo: 0x0000555555555149 <+0>: endbr64 0x000055555555514d <+4>: push %rbp 0x000055555555514e <+5>: mov %rsp,%rbp 0x0000555555555151 <+8>: sub $0x30,%rsp => 0x0000555555555155 <+12>: mov %edi,-0x24(%rbp) ... ``` --- gdb/amd64-tdep.c | 70 ++++++++++++++++++- .../amd64-extended-prologue-analysis.c | 11 ++- .../amd64-extended-prologue-analysis.exp | 10 +-- 3 files changed, 83 insertions(+), 8 deletions(-) diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index e4eb076a55a..a147d07d9b6 100755 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -2603,6 +2603,70 @@ amd64_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc, return pc; } +/* Check whether PC points at code allocating space on the stack. + If so, update CACHE and return pc past it or CURRENT_PC, whichever is + smaller. Otherwise, return PC passed to this function. */ + +static CORE_ADDR +amd64_analyze_stack_alloc (gdbarch *arch, CORE_ADDR pc, CORE_ADDR current_pc, + amd64_frame_cache *cache) +{ + static const gdb_byte sub_imm8_rsp[] = { 0x83, 0xec }; + static const gdb_byte sub_imm32_rsp[] = { 0x81, 0xec }; + static const gdb_byte lea_disp_rsp[] = { 0x8D, 0x64 }; + + bfd_endian byte_order = gdbarch_byte_order (arch); + const CORE_ADDR start_pc = pc; + + gdb_byte op; + if (target_read_code (pc, &op, 1) == -1) + return pc; + + /* Check for REX.W. */ + if (op == 0x48) + pc++; + + if (current_pc <= pc) + return current_pc; + + gdb_byte buf[2]; + read_code (pc, buf, 2); + + /* Check for instruction allocating space on the stack, which looks like + sub imm8/32, %rsp + or + lea -imm (%rsp), %rsp + + and forward pc past it + update cache. */ + + /* sub imm8, %rsp. */ + if (memcmp (buf, sub_imm8_rsp, 2) == 0) + { + /* Instruction is 3 bytes long. The imm8 arg is the 3rd, single + byte. */ + cache->sp_offset += read_code_integer (pc + 2, 1, byte_order); + return pc + 3; + } + /* sub imm32, %rsp. */ + else if (memcmp (buf, sub_imm32_rsp, 2) == 0) + { + /* Instruction is 6 bytes long. The imm32 arg is stored in 4 bytes, + starting from 3rd one. */ + cache->sp_offset += read_code_integer (pc + 2, 4, byte_order); + return pc + 6; + } + /* lea -imm (%rsp), %rsp. */ + else if (memcmp (buf, lea_disp_rsp, 2) == 0) + { + /* Instruction is 4 bytes long. The imm arg is the 4th, single + byte. */ + cache->sp_offset += -1 * read_code_integer (pc + 3, 1, byte_order); + return pc + 4; + } + + return start_pc; +} + /* Do a limited analysis of the prologue at PC and update CACHE accordingly. Bail out early if CURRENT_PC is reached. Return the address where the analysis stopped. @@ -2648,7 +2712,11 @@ amd64_analyze_prologue (gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR current_pc, if (current_pc <= pc) return current_pc; - return amd64_analyze_register_saves (pc, current_pc, cache); + pc = amd64_analyze_register_saves (pc, current_pc, cache); + if (current_pc <= pc) + return current_pc; + + return amd64_analyze_stack_alloc (gdbarch, pc, current_pc, cache); } /* Work around false termination of prologue - GCC PR debug/48827. diff --git a/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.c b/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.c index 7d777d23236..e4805ec6f55 100644 --- a/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.c +++ b/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.c @@ -29,15 +29,22 @@ bar (int x) .cfi_def_cfa_register %rbp push %reg1 push %reg2 + sub $XXX, %rsp .cfi_offset %reg2, 32 .cfi_offset %reg1, 24 So to be able to unwind a register, GDB needs to skip prologue past - register pushes (to access .cfi directives). */ + register pushes and stack allocation (to access .cfi directives). */ int __attribute__ ((noinline)) foo (int a, int b, int c, int d) { - a += bar (a) + bar (b) + bar (c); + /* "volatile" alone isn't enough for clang to not optimize it out and + allocate space on the stack. */ + volatile char s[256]; + for (int i = 0; i < 256; i++) + s[i] = (char) (a + i); + + a += bar (a) + bar (b) + bar (c) + bar (d); return a; } diff --git a/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.exp b/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.exp index 49e03357995..5aeff028a6c 100644 --- a/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.exp +++ b/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.exp @@ -14,11 +14,11 @@ # along with this program. If not, see . # # This test verifies that when placing a breakpoint on a function with a frame -# pointer, instructions that push callee-saved registers in the prologue are -# skipped, without debug info. When stopped on such breakpoint, the pushed -# registers should be able to be immediately unwound. With debug info present, -# GDB would try to use prologue-end markers found in the line table to -# determine where the prologue ends. +# pointer, instructions that push callee-saved registers and stack allocation +# in the prologue are skipped, without debug info. When stopped on such +# breakpoint, the pushed registers should be able to be immediately unwound. +# With debug info present, GDB would try to use prologue-end markers found in +# the line table to determine where the prologue ends. # # It is also tested both with and without .eh_frame's .cfi directives - with # them, GDB can only unwind a register once stopped after .cfi directive for -- 2.34.1 --------------------------------------------------------------------- Intel Technology Poland sp. z o.o. ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN. Spolka oswiadcza, ze posiada status duzego przedsiebiorcy w rozumieniu ustawy z dnia 8 marca 2013 r. o przeciwdzialaniu nadmiernym opoznieniom w transakcjach handlowych. Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek przegladanie lub rozpowszechnianie jest zabronione. This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by others is strictly prohibited.