From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19579 invoked by alias); 23 May 2008 15:19:51 -0000 Received: (qmail 19483 invoked by uid 22791); 23 May 2008 15:19:50 -0000 X-Spam-Check-By: sourceware.org Received: from main.gmane.org (HELO ciao.gmane.org) (80.91.229.2) by sourceware.org (qpsmtpd/0.31) with ESMTP; Fri, 23 May 2008 15:19:26 +0000 Received: from list by ciao.gmane.org with local (Exim 4.43) id 1JzZ39-0006tP-Jp for gdb@sources.redhat.com; Fri, 23 May 2008 15:19:19 +0000 Received: from entropy.qnx.com ([209.226.137.107]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Fri, 23 May 2008 15:19:19 +0000 Received: from aristovski by entropy.qnx.com with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Fri, 23 May 2008 15:19:19 +0000 To: gdb@sources.redhat.com From: Aleksandar Ristovski Subject: Re: Frame lost after 'leave' and before 'ret' instruction on i386? Date: Tue, 27 May 2008 21:33:00 -0000 Message-ID: <4836E0A7.8050800@qnx.com> References: <482DA814.7030703@qnx.com> <20080516155828.GA31038@caradoc.them.org> <48358355.7050500@qnx.com> <20080522143936.GA32221@caradoc.them.org> <48358860.5010703@qnx.com> <1211479573.3601.84.camel@localhost.localdomain> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------050006080704020807080005" Cc: Daniel Jacobowitz , gdb@sourceware.org, Mark Kettenis User-Agent: Thunderbird 2.0.0.14 (Windows/20080421) In-Reply-To: <1211479573.3601.84.camel@localhost.localdomain> X-IsSubscribed: yes Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org X-SW-Source: 2008-05/txt/msg00166.txt.bz2 Message-ID: <20080527213300.RwQg1NPJaljCzJvwMlclhSRMwuCqfNeZos86rJase2E@z> This is a multi-part message in MIME format. --------------050006080704020807080005 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1044 Hello, The patch is an attempt to solve the issue from the subject. It introduces a check for in_function_epilogue_p and introduces architecture level prev_register_from_epilogue. The patch is a draft (works but is not complete). Rationale: Dealing with epilogue in frame unwinders needs to be done only in sentinel frame (older frames will never be in epilogue). Comments appreciated. Thanks, Aleksandar Ristovski QNX Software Systems ChangeLog (for reference only): * gdbarch.c, gdbarch.h: Regenerated. * gdbarch.sh: Introduce gdbarch_prev_frame_from_epilogue and provide default_prev_frame_from_epilogue. * i386-tdep.c (i386_in_function_epilogue_p, i386_prev_register_from_epilogue): New functions. (struct frame_unwind_cache): Struct definition. (i386_gdbarch_init): Register i386_prev_register_from_epilogue and i386_in_function_epilogue_p. * sentinel-frame.c (sentinel_frame_prev_register): Check if we are in epilogue and if so, call gdbarch provided prev_frame_from_epilogue. If this returns NULL do as before. --------------050006080704020807080005 Content-Type: text/plain; name="epilogue.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="epilogue.diff" Content-length: 11475 Index: gdb/gdbarch.c =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.c,v retrieving revision 1.427 diff -u -p -r1.427 gdbarch.c --- gdb/gdbarch.c 16 May 2008 00:27:23 -0000 1.427 +++ gdb/gdbarch.c 23 May 2008 15:13:39 -0000 @@ -52,7 +52,12 @@ /* Static function declarations */ static void alloc_gdbarch_data (struct gdbarch *); - +static struct value * +default_prev_register_from_epilogue (struct gdbarch *gdbarch, + struct frame_info *this_frame, + void **this_prologue_cache, + int regnum, + CORE_ADDR pc); /* Non-zero if we want to trace architecture code. */ #ifndef GDBARCH_DEBUG @@ -237,6 +242,7 @@ struct gdbarch gdbarch_target_signal_from_host_ftype *target_signal_from_host; gdbarch_target_signal_to_host_ftype *target_signal_to_host; gdbarch_record_special_symbol_ftype *record_special_symbol; + gdbarch_prev_register_from_epilogue_ftype *prev_register_from_epilogue; }; @@ -366,6 +372,7 @@ struct gdbarch startup_gdbarch = default_target_signal_from_host, /* target_signal_from_host */ default_target_signal_to_host, /* target_signal_to_host */ 0, /* record_special_symbol */ + default_prev_register_from_epilogue, /* prev_register_from_epilogue */ /* startup_gdbarch() */ }; @@ -449,6 +456,7 @@ gdbarch_alloc (const struct gdbarch_info gdbarch->displaced_step_location = NULL; gdbarch->target_signal_from_host = default_target_signal_from_host; gdbarch->target_signal_to_host = default_target_signal_to_host; + gdbarch->prev_register_from_epilogue = default_prev_register_from_epilogue; /* gdbarch_alloc() */ return gdbarch; @@ -617,6 +625,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of target_signal_from_host, invalid_p == 0 */ /* Skip verify of target_signal_to_host, invalid_p == 0 */ /* Skip verify of record_special_symbol, has predicate */ + /* Skip verify of prev_register_from_epilogue, invalid_p == 0 */ buf = ui_file_xstrdup (log, &dummy); make_cleanup (xfree, buf); if (strlen (buf) > 0) @@ -889,6 +898,9 @@ gdbarch_dump (struct gdbarch *gdbarch, s "gdbarch_dump: pointer_to_address = <0x%lx>\n", (long) gdbarch->pointer_to_address); fprintf_unfiltered (file, + "gdbarch_dump: prev_register_from_epilogue = <0x%lx>\n", + (long) gdbarch->prev_register_from_epilogue); + fprintf_unfiltered (file, "gdbarch_dump: gdbarch_print_float_info_p() = %d\n", gdbarch_print_float_info_p (gdbarch)); fprintf_unfiltered (file, @@ -3190,6 +3202,23 @@ set_gdbarch_record_special_symbol (struc gdbarch->record_special_symbol = record_special_symbol; } +struct value * +gdbarch_prev_register_from_epilogue (struct gdbarch *gdbarch, struct frame_info *this_frame, void **this_prologue_cache, int regnum, CORE_ADDR pc) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->prev_register_from_epilogue != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_prev_register_from_epilogue called\n"); + return gdbarch->prev_register_from_epilogue (gdbarch, this_frame, this_prologue_cache, regnum, pc); +} + +void +set_gdbarch_prev_register_from_epilogue (struct gdbarch *gdbarch, + gdbarch_prev_register_from_epilogue_ftype prev_register_from_epilogue) +{ + gdbarch->prev_register_from_epilogue = prev_register_from_epilogue; +} + /* Keep a registry of per-architecture data-pointers required by GDB modules. */ @@ -3600,6 +3629,16 @@ deprecated_current_gdbarch_select_hack ( reinit_frame_cache (); } +static struct value * +default_prev_register_from_epilogue (struct gdbarch *gdbarch, + struct frame_info *this_frame, + void **this_prologue_cache, + int regnum, + CORE_ADDR pc) +{ + return NULL; +} + extern void _initialize_gdbarch (void); void Index: gdb/gdbarch.h =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.h,v retrieving revision 1.382 diff -u -p -r1.382 gdbarch.h --- gdb/gdbarch.h 16 May 2008 00:27:23 -0000 1.382 +++ gdb/gdbarch.h 23 May 2008 15:13:39 -0000 @@ -798,6 +798,12 @@ typedef void (gdbarch_record_special_sym extern void gdbarch_record_special_symbol (struct gdbarch *gdbarch, struct objfile *objfile, asymbol *sym); extern void set_gdbarch_record_special_symbol (struct gdbarch *gdbarch, gdbarch_record_special_symbol_ftype *record_special_symbol); +/* Create architecture dependent sentinel_frame. */ + +typedef struct value * (gdbarch_prev_register_from_epilogue_ftype) (struct gdbarch *gdbarch, struct frame_info *this_frame, void **this_prologue_cache, int regnum, CORE_ADDR pc); +extern struct value * gdbarch_prev_register_from_epilogue (struct gdbarch *gdbarch, struct frame_info *this_frame, void **this_prologue_cache, int regnum, CORE_ADDR pc); +extern void set_gdbarch_prev_register_from_epilogue (struct gdbarch *gdbarch, gdbarch_prev_register_from_epilogue_ftype *prev_register_from_epilogue); + extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch); Index: gdb/gdbarch.sh =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.sh,v retrieving revision 1.468 diff -u -p -r1.468 gdbarch.sh --- gdb/gdbarch.sh 16 May 2008 00:27:23 -0000 1.468 +++ gdb/gdbarch.sh 23 May 2008 15:13:39 -0000 @@ -703,6 +703,10 @@ m:int:target_signal_to_host:enum target_ # Record architecture-specific information from the symbol table. M:void:record_special_symbol:struct objfile *objfile, asymbol *sym:objfile, sym + +# Create architecture dependent sentinel_frame. +m:struct value *:prev_register_from_epilogue:struct frame_info *this_frame, void **this_prologue_cache, int regnum, CORE_ADDR pc:this_frame, this_prologue_cache, regnum, pc::default_prev_register_from_epilogue::0 + EOF } @@ -1133,7 +1137,12 @@ cat <regcache, I386_ESP_REGNUM, + value_contents_raw (value)); + esp = value_as_address (value); + esp -= 4; + store_unsigned_integer (value_contents_raw (value), 4, esp); + return value; + } + + /* Use the regcache_cooked_read() method so that it, on the fly, + constructs either a raw or pseudo register from the raw + register cache. */ + regcache_cooked_read (cache->regcache, regnum, value_contents_raw (value)); + + return value; +} static struct gdbarch * i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) @@ -2587,6 +2648,7 @@ i386_gdbarch_init (struct gdbarch_info i set_gdbarch_return_value (gdbarch, i386_return_value); set_gdbarch_skip_prologue (gdbarch, i386_skip_prologue); + set_gdbarch_in_function_epilogue_p (gdbarch, i386_in_function_epilogue_p); /* Stack grows downward. */ set_gdbarch_inner_than (gdbarch, core_addr_lessthan); @@ -2625,6 +2687,8 @@ i386_gdbarch_init (struct gdbarch_info i frame_unwind_append_unwinder (gdbarch, &i386_sigtramp_frame_unwind); frame_unwind_append_unwinder (gdbarch, &i386_frame_unwind); + set_gdbarch_prev_register_from_epilogue (gdbarch, + i386_prev_register_from_epilogue); /* If we have a register mapping, enable the generic core file support, unless it has already been enabled. */ Index: gdb/sentinel-frame.c =================================================================== RCS file: /cvs/src/src/gdb/sentinel-frame.c,v retrieving revision 1.18 diff -u -p -r1.18 sentinel-frame.c --- gdb/sentinel-frame.c 30 Apr 2008 21:16:45 -0000 1.18 +++ gdb/sentinel-frame.c 23 May 2008 15:13:40 -0000 @@ -49,8 +49,25 @@ sentinel_frame_prev_register (struct fra { struct gdbarch *gdbarch = get_frame_arch (this_frame); struct frame_unwind_cache *cache = *this_prologue_cache; - struct value *value; + struct value *value = NULL; + if (regnum != gdbarch_pc_regnum (gdbarch)) + { + struct value *value_pc; + CORE_ADDR pc; + value_pc = sentinel_frame_prev_register (this_frame, + this_prologue_cache, + gdbarch_pc_regnum (gdbarch)); + pc = value_as_address (value_pc); + if (gdbarch_in_function_epilogue_p (gdbarch, pc)) + value = gdbarch_prev_register_from_epilogue (gdbarch, + this_frame, + this_prologue_cache, + regnum, + pc); + if (value) + return value; + } /* Return the actual value. */ value = allocate_value (register_type (gdbarch, regnum)); VALUE_LVAL (value) = lval_register; @@ -84,3 +101,4 @@ const struct frame_unwind sentinel_frame }; const struct frame_unwind *const sentinel_frame_unwind = &sentinel_frame_unwinder; + --------------050006080704020807080005--