From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28019 invoked by alias); 14 Feb 2006 15:45:52 -0000 Received: (qmail 27982 invoked by uid 22791); 14 Feb 2006 15:45:51 -0000 X-Spam-Check-By: sourceware.org Received: from sibelius.xs4all.nl (HELO sibelius.xs4all.nl) (82.92.89.47) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 14 Feb 2006 15:45:45 +0000 Received: from elgar.sibelius.xs4all.nl (root@elgar.sibelius.xs4all.nl [192.168.0.2]) by sibelius.xs4all.nl (8.13.4/8.13.4) with ESMTP id k1EFjf9r000687; Tue, 14 Feb 2006 16:45:41 +0100 (CET) Received: from elgar.sibelius.xs4all.nl (kettenis@localhost.sibelius.xs4all.nl [127.0.0.1]) by elgar.sibelius.xs4all.nl (8.13.4/8.13.3) with ESMTP id k1EFjf54000237; Tue, 14 Feb 2006 16:45:41 +0100 (CET) Received: (from kettenis@localhost) by elgar.sibelius.xs4all.nl (8.13.4/8.13.4/Submit) id k1EFjeGb005665; Tue, 14 Feb 2006 16:45:40 +0100 (CET) Date: Tue, 14 Feb 2006 15:45:00 -0000 Message-Id: <200602141545.k1EFjeGb005665@elgar.sibelius.xs4all.nl> From: Mark Kettenis To: gdb-patches@sourceware.org, fnf@specifix.com Subject: Fix PR breakpoints/2080 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2006-02/txt/msg00302.txt.bz2 This fixes the testcase I checked in yesterday, so I committed it. Fred, can you check whether this also fixes your problem? Mark Index: ChangeLog from Mark Kettenis Fix PR breakpoints/2080. * i386-tdep.c (struct i386_frame_cache): Add stack_align member. (i386_analyze_stack_align): New function. (i386_analyze_prologue): Use i386_analyze_stack_align. (i386_frame_cache): Deal with stack realignment. Index: i386-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/i386-tdep.c,v retrieving revision 1.222 diff -u -p -r1.222 i386-tdep.c --- i386-tdep.c 21 Jan 2006 20:59:50 -0000 1.222 +++ i386-tdep.c 14 Feb 2006 15:40:43 -0000 @@ -308,6 +308,7 @@ struct i386_frame_cache /* Saved registers. */ CORE_ADDR saved_regs[I386_NUM_SAVED_REGS]; CORE_ADDR saved_sp; + int stack_align; int pc_in_eax; /* Stack space reserved for local variables. */ @@ -334,6 +335,7 @@ i386_alloc_frame_cache (void) for (i = 0; i < I386_NUM_SAVED_REGS; i++) cache->saved_regs[i] = -1; cache->saved_sp = 0; + cache->stack_align = 0; cache->pc_in_eax = 0; /* Frameless until proven otherwise. */ @@ -485,6 +487,33 @@ i386_skip_probe (CORE_ADDR pc) return pc; } +/* GCC 4.1 and later, can put code in the prologue to realign the + stack pointer. Check whether PC points to such code, and update + CACHE accordingly. Return the first instruction after the code + sequence or CURRENT_PC, whichever is smaller. If we don't + recognize the code, return PC. */ + +static CORE_ADDR +i386_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc, + struct i386_frame_cache *cache) +{ + static const gdb_byte insns[10] = { + 0x8d, 0x4c, 0x24, 0x04, /* leal 4(%esp), %ecx */ + 0x83, 0xe4, 0xf0, /* andl $-16, %esp */ + 0xff, 0x71, 0xfc /* pushl -4(%ecx) */ + }; + gdb_byte buf[10]; + + if (target_read_memory (pc, buf, sizeof buf) + || memcmp (buf, insns, sizeof buf) != 0) + return pc; + + if (current_pc > pc + 4) + cache->stack_align = 1; + + return min (pc + 10, current_pc); +} + /* Maximum instruction length we need to handle. */ #define I386_MAX_INSN_LEN 6 @@ -777,6 +806,7 @@ i386_analyze_prologue (CORE_ADDR pc, COR pc = i386_follow_jump (pc); pc = i386_analyze_struct_return (pc, current_pc, cache); pc = i386_skip_probe (pc); + pc = i386_analyze_stack_align (pc, current_pc, cache); pc = i386_analyze_frame_setup (pc, current_pc, cache); return i386_analyze_register_saves (pc, current_pc, cache); } @@ -907,6 +937,13 @@ i386_frame_cache (struct frame_info *nex if (cache->pc != 0) i386_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); + if (cache->stack_align) + { + /* Saved stack pointer has been saved in %ecx. */ + frame_unwind_register (next_frame, I386_ECX_REGNUM, buf); + cache->saved_sp = extract_unsigned_integer(buf, 4); + } + if (cache->locals < 0) { /* We didn't find a valid frame, which means that CACHE->base @@ -917,13 +954,26 @@ i386_frame_cache (struct frame_info *nex frame by looking at the stack pointer. For truly "frameless" functions this might work too. */ - frame_unwind_register (next_frame, I386_ESP_REGNUM, buf); - cache->base = extract_unsigned_integer (buf, 4) + cache->sp_offset; + if (cache->stack_align) + { + /* We're halfway aligning the stack. */ + cache->base = ((cache->saved_sp - 4) & 0xfffffff0) - 4; + cache->saved_regs[I386_EIP_REGNUM] = cache->saved_sp - 4; + + /* This will be added back below. */ + cache->saved_regs[I386_EIP_REGNUM] -= cache->base; + } + else + { + frame_unwind_register (next_frame, I386_ESP_REGNUM, buf); + cache->base = extract_unsigned_integer (buf, 4) + cache->sp_offset; + } } /* Now that we have the base address for the stack frame we can calculate the value of %esp in the calling frame. */ - cache->saved_sp = cache->base + 8; + if (cache->saved_sp == 0) + cache->saved_sp = cache->base + 8; /* Adjust all the saved registers such that they contain addresses instead of offsets. */