From patchwork Thu Mar 15 15:54:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: pedromfc X-Patchwork-Id: 26322 Received: (qmail 73777 invoked by alias); 15 Mar 2018 15:54:50 -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 73764 invoked by uid 89); 15 Mar 2018 15:54:50 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, NO_DNS_FOR_FROM, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy=H*Ad:U*uweigand, H*Ad:D*de.ibm.com X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0a-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.156.1) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 15 Mar 2018 15:54:48 +0000 Received: from pps.filterd (m0098393.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w2FFs9FX123954 for ; Thu, 15 Mar 2018 11:54:47 -0400 Received: from e17.ny.us.ibm.com (e17.ny.us.ibm.com [129.33.205.207]) by mx0a-001b2d01.pphosted.com with ESMTP id 2gqs5s0v3x-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Thu, 15 Mar 2018 11:54:46 -0400 Received: from localhost by e17.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 15 Mar 2018 11:54:45 -0400 Received: from b01cxnp22033.gho.pok.ibm.com (9.57.198.23) by e17.ny.us.ibm.com (146.89.104.204) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 15 Mar 2018 11:54:43 -0400 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp22033.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w2FFsgcv41484416; Thu, 15 Mar 2018 15:54:42 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id AF5B0AE03C; Thu, 15 Mar 2018 11:56:12 -0400 (EDT) Received: from pedro.localdomain (unknown [9.18.235.179]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP id 831B6AE034; Thu, 15 Mar 2018 11:56:12 -0400 (EDT) Received: by pedro.localdomain (Postfix, from userid 1000) id 188073C4D44; Thu, 15 Mar 2018 12:54:41 -0300 (-03) From: Pedro Franco de Carvalho To: gdb-patches@sourceware.org Cc: uweigand@de.ibm.com Subject: [PATCH] [PowerPC] Detect when LR is saved through frame pointer Date: Thu, 15 Mar 2018 12:54:20 -0300 X-TM-AS-GCONF: 00 x-cbid: 18031515-0040-0000-0000-0000040831C2 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008679; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000254; SDB=6.01003455; UDB=6.00510681; IPR=6.00782780; MB=3.00020051; MTD=3.00000008; XFM=3.00000015; UTC=2018-03-15 15:54:44 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18031515-0041-0000-0000-000008093375 Message-Id: <20180315155420.3341-1-pedromfc@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-03-15_08:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1011 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1803150174 X-IsSubscribed: yes This patch extends rs6000-tdep.c:skip_prologue so that it can detect when the Link Register is saved using the frame pointer (usually r31) in adition to the stack pointer (r1). The frame pointer offset from the frame base is tracked separately from the stack pointer offset for cases when the frame pointer is not in synch with the stack pointer at the moment of the LR save. Previously, "stq" could also be detected as an isntruction that saves LR or CR. Because this was likely unintentional, this patch also restricts the matches to stw/stwu/std/stdu. 2018-mm-dd Pedro Franco de Carvalho * rs6000-tdep.c (store_insn_p): New function. (skip_prologue): New variable alloca_reg_offset. Set lr_reg and cr_reg to their unshifted values. Use store_insn_p to match LR saves using either R1 or fdata->alloca_reg. Use store_insn_p to match CR saves. Set alloca_reg_offset when alloca_reg and framep are set. Remove lr_reg shift when assigning to fdata->lr_register. --- gdb/rs6000-tdep.c | 71 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index a5b70917b7..d61fe58d22 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -1357,6 +1357,39 @@ bl_to_blrl_insn_p (CORE_ADDR pc, int insn, enum bfd_endian byte_order) return 0; } +/* Return true if OP is a stw or std instruction with + register operands RS and RA and any immediate offset. + + If WITH_UPDATE is true, also return true if OP is + a stwu or stdu instruction with the same operands. + + Return false otherwise. + */ +static bool +store_insn_p (unsigned long op, unsigned long rs, + unsigned long ra, bool with_update) +{ + rs = rs << 21; + ra = ra << 16; + + if (/* std RS, SIMM(RA) */ + ((op & 0xffff0003) == (rs | ra | 0xf8000000)) || + /* stw RS, SIMM(RA) */ + ((op & 0xffff0000) == (rs | ra | 0x90000000))) + return true; + + if (with_update) + { + if (/* stdu RS, SIMM(RA) */ + ((op & 0xffff0003) == (rs | ra | 0xf8000001)) || + /* stwu RS, SIMM(RA) */ + ((op & 0xffff0000) == (rs | ra | 0x94000000))) + return true; + } + + return false; +} + /* Masks for decoding a branch-and-link (bl) instruction. BL_MASK and BL_INSTRUCTION are used in combination with each other. @@ -1583,6 +1616,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, gdb_byte buf[4]; unsigned long op; long offset = 0; + long alloca_reg_offset = 0; long vr_saved_offset = 0; int lr_reg = -1; int cr_reg = -1; @@ -1654,14 +1688,14 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, remember just the first one, but skip over additional ones. */ if (lr_reg == -1) - lr_reg = (op & 0x03e00000); + lr_reg = (op & 0x03e00000) >> 21; if (lr_reg == 0) r0_contains_arg = 0; continue; } else if ((op & 0xfc1fffff) == 0x7c000026) { /* mfcr Rx */ - cr_reg = (op & 0x03e00000); + cr_reg = (op & 0x03e00000) >> 21; if (cr_reg == 0) r0_contains_arg = 0; continue; @@ -1738,14 +1772,17 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, } else if (lr_reg >= 0 && - /* std Rx, NUM(r1) || stdu Rx, NUM(r1) */ - (((op & 0xffff0000) == (lr_reg | 0xf8010000)) || - /* stw Rx, NUM(r1) */ - ((op & 0xffff0000) == (lr_reg | 0x90010000)) || - /* stwu Rx, NUM(r1) */ - ((op & 0xffff0000) == (lr_reg | 0x94010000)))) - { /* where Rx == lr */ - fdata->lr_offset = offset; + ((store_insn_p (op, lr_reg, 1, true)) || + (framep && + (store_insn_p (op, lr_reg, + fdata->alloca_reg - tdep->ppc_gp0_regnum, + false))))) + { + if (store_insn_p (op, lr_reg, 1, true)) + fdata->lr_offset = offset; + else /* LR save through frame pointer. */ + fdata->lr_offset = alloca_reg_offset; + fdata->nosavedpc = 0; /* Invalidate lr_reg, but don't set it to -1. That would mean that it had never been set. */ @@ -1760,13 +1797,8 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, } else if (cr_reg >= 0 && - /* std Rx, NUM(r1) || stdu Rx, NUM(r1) */ - (((op & 0xffff0000) == (cr_reg | 0xf8010000)) || - /* stw Rx, NUM(r1) */ - ((op & 0xffff0000) == (cr_reg | 0x90010000)) || - /* stwu Rx, NUM(r1) */ - ((op & 0xffff0000) == (cr_reg | 0x94010000)))) - { /* where Rx == cr */ + (store_insn_p (op, cr_reg, 1, true))) + { fdata->cr_offset = offset; /* Invalidate cr_reg, but don't set it to -1. That would mean that it had never been set. */ @@ -1920,6 +1952,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, fdata->frameless = 0; framep = 1; fdata->alloca_reg = (tdep->ppc_gp0_regnum + 29); + alloca_reg_offset = offset; continue; /* Another way to set up the frame pointer. */ @@ -1930,6 +1963,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, fdata->frameless = 0; framep = 1; fdata->alloca_reg = (tdep->ppc_gp0_regnum + 31); + alloca_reg_offset = offset; continue; /* Another way to set up the frame pointer. */ @@ -1940,6 +1974,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, framep = 1; fdata->alloca_reg = (tdep->ppc_gp0_regnum + ((op & ~0x38010000) >> 21)); + alloca_reg_offset = offset; continue; } /* AltiVec related instructions. */ @@ -2180,7 +2215,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, #endif /* 0 */ if (pc == lim_pc && lr_reg >= 0) - fdata->lr_register = lr_reg >> 21; + fdata->lr_register = lr_reg; fdata->offset = -fdata->offset; return last_prologue_pc;