From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4571 invoked by alias); 17 Aug 2009 00:22:05 -0000 Received: (qmail 4562 invoked by uid 22791); 17 Aug 2009 00:22:04 -0000 X-SWARE-Spam-Status: No, hits=-2.4 required=5.0 tests=AWL,BAYES_00 X-Spam-Check-By: sourceware.org Received: from smtp-outbound-1.vmware.com (HELO smtp-outbound-1.vmware.com) (65.115.85.69) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 17 Aug 2009 00:21:57 +0000 Received: from jupiter.vmware.com (mailhost5.vmware.com [10.16.68.131]) by smtp-outbound-1.vmware.com (Postfix) with ESMTP id 440731304A for ; Sun, 16 Aug 2009 17:21:54 -0700 (PDT) Received: from [10.20.94.141] (msnyder-server.eng.vmware.com [10.20.94.141]) by jupiter.vmware.com (Postfix) with ESMTP id 3A31ADC059 for ; Sun, 16 Aug 2009 17:21:54 -0700 (PDT) Message-ID: <4A88A1EA.8010705@vmware.com> Date: Mon, 17 Aug 2009 03:35:00 -0000 From: Michael Snyder User-Agent: Thunderbird 1.5.0.12 (X11/20080411) MIME-Version: 1.0 To: "gdb-patches@sourceware.org" Subject: [RFA] Add epilogue unwinder for AMD64 Content-Type: multipart/mixed; boundary="------------090508020105020906050303" 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: 2009-08/txt/msg00227.txt.bz2 This is a multi-part message in MIME format. --------------090508020105020906050303 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 286 This patch corresponds to the similar one in i386-tdep.c, and corrects for a gcc issue with elf/dwarf debug info in function epilogues. It is needed in order to make reverse-step and next work properly for stepping backward through a return. No testsuite regressions. OK to commit? --------------090508020105020906050303 Content-Type: text/plain; name="amd64-2.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="amd64-2.txt" Content-length: 3801 2009-08-16 Michael Snyder * amd64-tdep.c: Add a frame unwinder for function epilogues. (amd64_in_function_epilogue_p): New function. (amd64_epilogue_frame_sniffer): New function. (amd64_epilogue_frame_cache): New function. (amd64_epilogue_frame_this_id): New function. (amd64_epilogue_frame_unwind): New struct frame_unwind. (amd64_init_abi): Hook the new unwinder. Index: amd64-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/amd64-tdep.c,v retrieving revision 1.64 diff -u -p -r1.64 amd64-tdep.c --- amd64-tdep.c 10 Aug 2009 03:02:39 -0000 1.64 +++ amd64-tdep.c 16 Aug 2009 23:12:25 -0000 @@ -1887,6 +1887,89 @@ static const struct frame_base amd64_fra amd64_frame_base_address }; +/* Normal frames, but in a function epilogue. */ + +/* The epilogue is defined here as the 'ret' instruction, which will + follow any instruction such as 'leave' or 'pop %ebp' that destroys + the function's stack frame. */ + +static int +amd64_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + gdb_byte insn; + + if (target_read_memory (pc, &insn, 1)) + return 0; /* Can't read memory at pc. */ + + if (insn != 0xc3) /* 'ret' instruction. */ + return 0; + + return 1; +} + +static int +amd64_epilogue_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_prologue_cache) +{ + if (frame_relative_level (this_frame) == 0) + return amd64_in_function_epilogue_p (get_frame_arch (this_frame), + get_frame_pc (this_frame)); + else + return 0; +} + +static struct amd64_frame_cache * +amd64_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + struct amd64_frame_cache *cache; + gdb_byte buf[4]; + + if (*this_cache) + return *this_cache; + + cache = amd64_alloc_frame_cache (); + *this_cache = cache; + + /* Cache base will be %esp plus cache->sp_offset (-8). */ + get_frame_register (this_frame, AMD64_RSP_REGNUM, buf); + cache->base = extract_unsigned_integer (buf, 8, + byte_order) + cache->sp_offset; + + /* Cache pc will be the frame func. */ + cache->pc = get_frame_pc (this_frame); + + /* The saved %esp will be at cache->base plus 16. */ + cache->saved_sp = cache->base + 16; + + /* The saved %eip will be at cache->base plus 8. */ + cache->saved_regs[AMD64_RIP_REGNUM] = cache->base + 8; + + return cache; +} + +static void +amd64_epilogue_frame_this_id (struct frame_info *this_frame, + void **this_cache, + struct frame_id *this_id) +{ + struct amd64_frame_cache *cache = amd64_epilogue_frame_cache (this_frame, + this_cache); + + (*this_id) = frame_id_build (cache->base + 8, cache->pc); +} + +static const struct frame_unwind amd64_epilogue_frame_unwind = +{ + NORMAL_FRAME, + amd64_epilogue_frame_this_id, + amd64_frame_prev_register, + NULL, + amd64_epilogue_frame_sniffer +}; + static struct frame_id amd64_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame) { @@ -2065,6 +2148,12 @@ amd64_init_abi (struct gdbarch_info info set_gdbarch_dummy_id (gdbarch, amd64_dummy_id); + /* Hook the function epilogue frame unwinder. This unwinder is + appended to the list first, so that it supercedes the other + unwinders in function epilogues. */ + frame_unwind_prepend_unwinder (gdbarch, &amd64_epilogue_frame_unwind); + + /* Hook the prologue-based frame unwinders. */ frame_unwind_append_unwinder (gdbarch, &amd64_sigtramp_frame_unwind); frame_unwind_append_unwinder (gdbarch, &amd64_frame_unwind); frame_base_set_default (gdbarch, &amd64_frame_base); --------------090508020105020906050303--