From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6333 invoked by alias); 16 Jun 2012 14:42:05 -0000 Received: (qmail 6324 invoked by uid 22791); 16 Jun 2012 14:42:03 -0000 X-SWARE-Spam-Status: No, hits=-5.0 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,KHOP_RCVD_TRUST,KHOP_THREADED,RCVD_IN_DNSWL_LOW,RCVD_IN_HOSTKARMA_YE,TW_XF X-Spam-Check-By: sourceware.org Received: from mail-qc0-f169.google.com (HELO mail-qc0-f169.google.com) (209.85.216.169) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 16 Jun 2012 14:41:49 +0000 Received: by qcsd16 with SMTP id d16so2560007qcs.0 for ; Sat, 16 Jun 2012 07:41:48 -0700 (PDT) MIME-Version: 1.0 Received: by 10.224.42.146 with SMTP id s18mr17492293qae.26.1339857708012; Sat, 16 Jun 2012 07:41:48 -0700 (PDT) Received: by 10.229.192.129 with HTTP; Sat, 16 Jun 2012 07:41:47 -0700 (PDT) In-Reply-To: <201206161127.q5GBRASA028790@glazunov.sibelius.xs4all.nl> References: <20120613230825.GA11653@intel.com> <201206161127.q5GBRASA028790@glazunov.sibelius.xs4all.nl> Date: Sat, 16 Jun 2012 14:42:00 -0000 Message-ID: Subject: Re: [PATCH 5/5] Add x32 support to amd64_analyze_stack_align From: "H.J. Lu" To: Mark Kettenis Cc: gdb-patches@sourceware.org Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-06/txt/msg00543.txt.bz2 On Sat, Jun 16, 2012 at 4:27 AM, Mark Kettenis wr= ote: >> Date: Wed, 13 Jun 2012 16:08:25 -0700 >> From: "H.J. Lu" >> >> Hi, >> >> This patch adds support to amd64_analyze_stack_align. =A0OK to install? > > Sorry, no. =A0I think this function is complex enough as it is now. > Please create a seperate function for x32. =A0That may lead to some code > duplication, but that is better than increasing the complexity of this > already complex function. > This patch adds amd64_x32_analyze_stack_align and uses it for x32. OK to install? Thanks. --=20 H.J. --- * amd64-tdep.c (amd64_x32_analyze_stack_align): New function. (amd64_analyze_prologue): Call amd64_x32_analyze_stack_align for x32. diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index 27f115b..5424926 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -1861,6 +1861,188 @@ amd64_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc, return min (pc + offset + 2, current_pc); } +/* Similar to amd64_analyze_stack_align for x32. */ + +static CORE_ADDR +amd64_x32_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc, + struct amd64_frame_cache *cache) +{ + /* There are 2 code sequences to re-align stack before the frame + gets set up: + + 1. Use a caller-saved saved register: + + leaq 8(%rsp), %reg + andq $-XXX, %rsp + pushq -8(%reg) + + or + + [addr32] leal 8(%rsp), %reg + andl $-XXX, %esp + [addr32] pushq -8(%reg) + + 2. Use a callee-saved saved register: + + pushq %reg + leaq 16(%rsp), %reg + andq $-XXX, %rsp + pushq -8(%reg) + + or + + pushq %reg + [addr32] leal 16(%rsp), %reg + andl $-XXX, %esp + [addr32] pushq -8(%reg) + + "andq $-XXX, %rsp" can be either 4 bytes or 7 bytes: + + 0x48 0x83 0xe4 0xf0 andq $-16, %rsp + 0x48 0x81 0xe4 0x00 0xff 0xff 0xff andq $-256, %rsp + + "andl $-XXX, %esp" can be either 3 bytes or 6 bytes: + + 0x83 0xe4 0xf0 andl $-16, %esp + 0x81 0xe4 0x00 0xff 0xff 0xff andl $-256, %esp + */ + + gdb_byte buf[19]; + int reg, r; + int offset, offset_and; + + if (target_read_memory (pc, buf, sizeof buf)) + return pc; + + /* Skip optional addr32 prefix. */ + offset =3D buf[0] =3D=3D 0x67 ? 1 : 0; + + /* Check caller-saved saved register. The first instruction has + to be "leaq 8(%rsp), %reg" or "leal 8(%rsp), %reg". */ + if (((buf[offset] & 0xfb) =3D=3D 0x48 || (buf[offset] & 0xfb) =3D=3D 0x4= 0) + && buf[offset + 1] =3D=3D 0x8d + && buf[offset + 3] =3D=3D 0x24 + && buf[offset + 4] =3D=3D 0x8) + { + /* MOD must be binary 10 and R/M must be binary 100. */ + if ((buf[offset + 2] & 0xc7) !=3D 0x44) + return pc; + + /* REG has register number. */ + reg =3D (buf[offset + 2] >> 3) & 7; + + /* Check the REX.R bit. */ + if ((buf[offset] & 0x4) !=3D 0) + reg +=3D 8; + + offset +=3D 5; + } + else + { + /* Check callee-saved saved register. The first instruction + has to be "pushq %reg". */ + reg =3D 0; + if ((buf[offset] & 0xf6) =3D=3D 0x40 + && (buf[offset + 1] & 0xf8) =3D=3D 0x50) + { + /* Check the REX.B bit. */ + if ((buf[offset] & 1) !=3D 0) + reg =3D 8; + + offset +=3D 1; + } + else if ((buf[offset] & 0xf8) !=3D 0x50) + return pc; + + /* Get register. */ + reg +=3D buf[offset] & 0x7; + + offset++; + + /* Skip optional addr32 prefix. */ + if (buf[offset] =3D=3D 0x67) + offset++; + + /* The next instruction has to be "leaq 16(%rsp), %reg" or + "leal 16(%rsp), %reg". */ + if (((buf[offset] & 0xfb) !=3D 0x48 && (buf[offset] & 0xfb) !=3D 0x4= 0) + || buf[offset + 1] !=3D 0x8d + || buf[offset + 3] !=3D 0x24 + || buf[offset + 4] !=3D 0x10) + return pc; + + /* MOD must be binary 10 and R/M must be binary 100. */ + if ((buf[offset + 2] & 0xc7) !=3D 0x44) + return pc; + + /* REG has register number. */ + r =3D (buf[offset + 2] >> 3) & 7; + + /* Check the REX.R bit. */ + if ((buf[offset] & 0x4) !=3D 0) + r +=3D 8; + + /* Registers in pushq and leaq have to be the same. */ + if (reg !=3D r) + return pc; + + offset +=3D 5; + } + + /* Rigister can't be %rsp nor %rbp. */ + if (reg =3D=3D 4 || reg =3D=3D 5) + return pc; + + /* The next instruction may be "andq $-XXX, %rsp" or + "andl $-XXX, %esp". */ + if (buf[offset] !=3D 0x48) + offset--; + + if (buf[offset + 2] !=3D 0xe4 + || (buf[offset + 1] !=3D 0x81 && buf[offset + 1] !=3D 0x83)) + return pc; + + offset_and =3D offset; + offset +=3D buf[offset + 1] =3D=3D 0x81 ? 7 : 4; + + /* Skip optional addr32 prefix. */ + if (buf[offset] =3D=3D 0x67) + offset++; + + /* The next instruction has to be "pushq -8(%reg)". */ + r =3D 0; + if (buf[offset] =3D=3D 0xff) + offset++; + else if ((buf[offset] & 0xf6) =3D=3D 0x40 + && buf[offset + 1] =3D=3D 0xff) + { + /* Check the REX.B bit. */ + if ((buf[offset] & 0x1) !=3D 0) + r =3D 8; + offset +=3D 2; + } + else + return pc; + + /* 8bit -8 is 0xf8. REG must be binary 110 and MOD must be binary + 01. */ + if (buf[offset + 1] !=3D 0xf8 + || (buf[offset] & 0xf8) !=3D 0x70) + return pc; + + /* R/M has register. */ + r +=3D buf[offset] & 7; + + /* Registers in leaq and pushq have to be the same. */ + if (reg !=3D r) + return pc; + + if (current_pc > pc + offset_and) + cache->saved_sp_reg =3D amd64_arch_reg_to_regnum (reg); + + return min (pc + offset + 2, current_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. @@ -1898,7 +2080,10 @@ amd64_analyze_prologue (struct gdbarch *gdbarch, if (current_pc <=3D pc) return current_pc; - pc =3D amd64_analyze_stack_align (pc, current_pc, cache); + if (gdbarch_ptr_bit (gdbarch) =3D=3D 32) + pc =3D amd64_x32_analyze_stack_align (pc, current_pc, cache); + else + pc =3D amd64_analyze_stack_align (pc, current_pc, cache); op =3D read_memory_unsigned_integer (pc, 1, byte_order);