From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7023 invoked by alias); 13 Oct 2007 19:58:00 -0000 Received: (qmail 7012 invoked by uid 22791); 13 Oct 2007 19:57:57 -0000 X-Spam-Check-By: sourceware.org Received: from ug-out-1314.google.com (HELO ug-out-1314.google.com) (66.249.92.170) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sat, 13 Oct 2007 19:57:50 +0000 Received: by ug-out-1314.google.com with SMTP id o2so831805uge for ; Sat, 13 Oct 2007 12:57:47 -0700 (PDT) Received: by 10.66.249.16 with SMTP id w16mr5868522ugh.1192305467053; Sat, 13 Oct 2007 12:57:47 -0700 (PDT) Received: from ?88.210.73.151? ( [88.210.73.151]) by mx.google.com with ESMTPS id d23sm3539029nfh.2007.10.13.12.57.38 (version=TLSv1/SSLv3 cipher=RC4-MD5); Sat, 13 Oct 2007 12:57:42 -0700 (PDT) Message-ID: <47112285.2080100@portugalmail.pt> Date: Sat, 13 Oct 2007 20:26:00 -0000 From: Pedro Alves User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR; rv:1.8.1.6) Gecko/20070728 Thunderbird/2.0.0.6 Mnenhy/0.7.5.0 MIME-Version: 1.0 To: gdb-patches@sourceware.org Subject: [rfc] Teach i386 prologue reader about _alloca and __main Content-Type: multipart/mixed; boundary="------------050901060709020901000901" 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: 2007-10/txt/msg00362.txt.bz2 This is a multi-part message in MIME format. --------------050901060709020901000901 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 9474 Hi guys, This is a new take on solving the issue described here: http://www.sourceware.org/ml/gdb/2006-11/msg00140.html On a nutshell, breaking on main is broken on Cygwin, and all targets where gcc emits a call to __main in main, right after the prologue. __main is responsible for calling the c++ constructors of global objects, and registering the destructors of the same objects to run at exit. This call is inserted on targets that don't have an .init section. http://sources.redhat.com/ml/gdb-patches/2006-12/msg00140.html My first aproach tackled it by making i386 skip the prologue using the debug info, and teaching gcc to put the line marker that marks the end of the prologue after the __main call. http://sources.redhat.com/ml/gdb-patches/2006-12/msg00140.html http://gcc.gnu.org/ml/gcc-patches/2006-12/msg00633.html Mark didn't like it, because: "The last time I tried using sals on i386, I simply encountered too many cases where the line number information couldn't be trusted and putting a breakpoint on a function that was defenitely called never hit." http://sources.redhat.com/ml/gdb-patches/2006-12/msg00375.html To which Daniel responded: "Yeah. That's definitely the biggest risk. I think the first step, for Pedro's specific problem, should be to recognize the call to __main as special and skippable. We can play with sals later." The attached patch does that - make __main skippable. This version doesn't need any gcc changes. There are a few complications, though. On NT, the stack must be grown page wise, by touching a guard page. Because of that we often see calls to _alloca AKA __chkstk (gcc/config/i386/cygwin.asm) in the prologue: http://cygwin.com/ml/cygwin-developers/2001-10/msg00108.html http://cygwin.com/ml/cygwin-developers/2001-10/msg00118.html There is another problem with the prologue analysing, which is visible on i386 targets using stabs debug info on gcc >= 4.1.0. eg: int main (int argc, char **argv) { On stabs, the debugger only knows that argc is the first parameter to the function and that its type is int. It is up to the debugger to know how to extract it from the frame. Gcc >= 4.1 can put code in the prologue to realign the stack pointer. In that case, the frame base will not be the same as the incoming args address, so gdb prints garbage for the arguments: main (argc=2280856, argv=0x61006198) at main.c:8 The prologue analyser already knows about a saved_sp, and that it can be extracted from %ecx, but on cygwin, %ecx will be clobbered by the __main call, before we get to user code: int main (int argc, char ** argv) { 401050: 8d 4c 24 04 lea 0x4(%esp),%ecx 401054: 83 e4 f0 and $0xfffffff0,%esp 401057: ff 71 fc pushl 0xfffffffc(%ecx) 40105a: 55 push %ebp 40105b: 89 e5 mov %esp,%ebp 40105d: 53 push %ebx 40105e: 51 push %ecx 40105f: b8 20 40 00 00 mov $0x4020,%eax 401064: e8 d7 00 00 00 call 401140 <___chkstk> 401069: 89 cb mov %ecx,%ebx 40106b: e8 60 01 00 00 call 4011d0 <___main> char asdf[0x4001]; printf ("argc %d\n", argc); 401070: 8b 03 mov (%ebx),%eax Luckilly, %ecx is pushed on the stack, and we already know how to get at it thanks to i386_analyze_register_saves. Follows a listing of prologue patterns I see here on i386 Cygwin. --- #include int main (int argc, char ** argv) { char asdf[0x4001]; printf ("argc %d\n", argc); ... } gcc3.4.4 (cygming special) -O0 _main: .stabn 68,0,8,LM1-_main LM1: pushl %ebp ;frame setup movl %esp, %ebp ; movl $16440, %eax ;local space call __alloca ; andl $-16, %esp ;alignment movl $0, %eax ;local space addl $15, %eax ; addl $15, %eax ; shrl $4, %eax ; sall $4, %eax ; movl %eax, -16412(%ebp) ; movl -16412(%ebp), %eax ; call __alloca ; .stabn 68,0,8,LM2-_main LM2: call ___main ;__main call .stabn 68,0,11,LM3-_main LM3: --- gcc3.4.4 (cygming special) -O1 _main: .stabn 68,0,8,LM1-_main LM1: pushl %ebp ;frame setup movl %esp, %ebp ; pushl %ebx movl $16420, %eax ;local space call __alloca ; movl 8(%ebp), %ebx andl $-16, %esp ;alignment movl $16, %eax ;local space call __alloca .stabn 68,0,8,LM2-_main LM2: call ___main ;__main call .stabn 68,0,11,LM3-_main LM3: --- gcc3.4.4 (cygming special) -O2 _main: .stabn 68,0,8,LM1-_main LM1: pushl %ebp ;frame setup movl $16420, %eax ;parameter to __alloca migrated here. movl %esp, %ebp ;frame setup pushl %ebx call __alloca .stabn 68,0,8,LM2-_main LM2: movl 8(%ebp), %ebx andl $-16, %esp movl $16, %eax call __alloca call ___main .stabn 68,0,11,LM3-_main LM3: --- gcc 4.3.0 20070824 -O0 _main: .stabd 46,0,0 .stabn 68,0,8,LM0-LFBB1 LM0: LFBB1: leal 4(%esp), %ecx ;stack alignment andl $-16, %esp ; pushl -4(%ecx) ; pushl %ebp ;frame setup movl %esp, %ebp ; pushl %ebx ;register saves pushl %ecx ; movl $16416, %eax ;local space call __alloca ; movl %ecx, %ebx .stabn 68,0,8,LM1-LFBB1 LM1: call ___main ;__main call .stabn 68,0,11,LM2-LFBB1 LM2: gcc 4.3.0 20070824 -O1 _main: .stabd 46,0,0 .stabn 68,0,8,LM0-LFBB1 LM0: LFBB1: leal 4(%esp), %ecx ;stack alignment andl $-16, %esp ; pushl -4(%ecx) ; pushl %ebp ;frame setup movl %esp, %ebp ; pushl %esi ;register saves pushl %ebx ;register saves pushl %ecx ;register saves subl $12, %esp ;local space movl (%ecx), %esi movl 4(%ecx), %ebx .stabn 68,0,8,LM1-LFBB1 LM1: call ___main ;main call .stabn 68,0,11,LM2-LFBB1 gcc 4.3.0 20070824 -O2 _main: .stabd 46,0,0 .stabn 68,0,8,LM0-LFBB1 LM0: LFBB1: leal 4(%esp), %ecx ;stack alignment andl $-16, %esp ; pushl -4(%ecx) ; pushl %ebp ;frame setup movl %esp, %ebp ; pushl %esi ;register saves pushl %ebx ;register saves pushl %ecx ;register saves subl $12, %esp ;local space .stabn 68,0,8,LM1-LFBB1 LM1: movl (%ecx), %esi movl 4(%ecx), %ebx call ___main ;main call .stabn 68,0,11,LM2-LFBB1 LM2: Note that the standard compiler on Cygwin is still gcc3 based, and it is unknown when it will switch to a newer one. The patch teaches gdb about the -O0 level good behaved prologues, and where easy makes it understand optimized ones. The __main call is only expected on targets that gdb knows it should be there. A new gdbarch callback is introduced for it, and cygwin registers it. The patch intruduces a few minsyms lookups, which I'm not sure we can do without. It looks like the risk is high to get it wrong otherwise. If left a few things to clean up, as it would make the patch harder to read. With this patch, all the run_to_main related failures and timeouts are gone, both with stock cygwin gcc, and with 4.3 trunk (*), and we start to see the real failures that are masked currently. (*) - In the mean time, cygming switched to dwarf debug info by default in 4.3. MinGW land has a gcc 4.2 based compiler in testing with the prospect of becoming the officially supported compiler. With nosignals on the board file, I get the FAIL rate down to < 150, and no new problems. Much better. It will need a lot more testing and tweaking, but I'd like to get comments before I spend more time in this. If this looks too much, the gcc3 patterns support could be dropped, as if the reader stops mid-line, the rest of the line is skipped, and that at -O0 lands us in the __main call. For gcc4, we need to read the prologue, due to the need to know where the args are on the stack - but gcc4 prologues are much more consistent. So... Comments? Cheers, Pedro Alves --------------050901060709020901000901 Content-Type: text/x-diff; name="skip_main.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="skip_main.diff" Content-length: 19401 2007-10-13 Pedro Alves * gdbarch.sh (gdbarch_skip___main_call): New. * gdbarch.h, gdbarch.c: Regenerate. * i386-tdep.h (i386_skip___main_call): Declare. * i386-tdep.c (i386_skip_alloca_call, i386_analyze_alloca2) (i386_analyze_alloca): New functions. (i386_analyze_frame_setup): Account for register saves before stack adjustment, for stack adjustment with _alloca and for stack adjustment with andl. Relax the insns requence. (i386___main_skip_insns): New. (i386_skip___main_call): New. (i386_analyze_prologue): Call i386_analyze_alloca. (i386_skip_prologue): Skip calls to __main on targets where gcc emits that call. (i386_frame_cache): If needed, extract %ecx from the stack. (i386_frame_args_address): New. (i386_frame_base): Set i386_frame_args_address as args method. * i386-cygwin-tdep.c (i386_cygwin_init_abi): Register i386_skip___main_call as gdbarch_skip___main_call gdbarch callback. --- gdb/gdbarch.c | 33 ++++ gdb/gdbarch.h | 6 gdb/gdbarch.sh | 1 gdb/i386-cygwin-tdep.c | 2 gdb/i386-tdep.c | 341 ++++++++++++++++++++++++++++++++++++++++++++++--- gdb/i386-tdep.h | 3 6 files changed, 368 insertions(+), 18 deletions(-) Index: src/gdb/i386-tdep.c =================================================================== --- src.orig/gdb/i386-tdep.c 2007-10-13 01:51:08.000000000 +0100 +++ src/gdb/i386-tdep.c 2007-10-13 20:32:54.000000000 +0100 @@ -579,6 +579,185 @@ i386_match_insn (CORE_ADDR pc, struct i3 return NULL; } +/* Check that the code pointed to by PC corresponds to a call to + __chkstk/_alloca and skip it if so. Return PC otherwise. */ + +static CORE_ADDR +i386_skip_alloca_call (CORE_ADDR pc, CORE_ADDR limit) +{ + gdb_byte op; + + /* If we don't have enough code for a call, return now. */ + if (pc + 5 > limit) + return pc; + + read_memory_nobpt (pc, &op, 1); + if (op == 0xe8) + { + gdb_byte buf[4]; + if (target_read_memory (pc + 1, buf, sizeof buf) == 0) + { + CORE_ADDR call_dest = pc + 5 + extract_unsigned_integer (buf, 4); + + struct minimal_symbol *s = + lookup_minimal_symbol_by_pc (call_dest); + if (s != NULL + && SYMBOL_LINKAGE_NAME (s) != NULL + && (strcmp (SYMBOL_LINKAGE_NAME (s), "__chkstk") == 0 + || strcmp (SYMBOL_LINKAGE_NAME (s), "_alloca") == 0)) + pc += 5; + } + } + + return pc; +} + +/* Check that the code pointed to by PC corresponds to a call to + __chkstk/_alloca and skip it if so. Return PC otherwise. */ + +static CORE_ADDR +i386_analyze_alloca2 (CORE_ADDR pc, CORE_ADDR limit, + struct i386_frame_cache *cache) +{ + /* On gcc3 ,and at -O0, the usual sequence in main is given by + setting %eax, storing/retrieving it (this is unoptimized code), + and then an _alloca/__chkstk call, which takes it's parameter in + %eax: + + eg: + mov $0x0,%eax + add $0xf,%eax + add $0xf,%eax + shr $0x4,%eax + shl $0x4,%eax + mov %eax,xxx(%ebp) + mov xxx(%ebp),%eax + call __alloca + + Also, if local variables take more than a page (4k), the stack + adjustment will be done using _alloca, because of the need to + touch the guard page on NT. The sequence will be: + + mov $xxx,%eax + call __alloca + + That's valid for main, and for every other function. At -O1, + long sequence above turns into the second sequence (mov,call). + + On gcc3, at -O2 and above, the `mov $xxx,%eax' is often migrated + into the frame setup, but we don't support that currently. Eg: + + push %ebp + mov $0x10,%eax + mov %esp,%ebp + sub $0x8,%esp + and $0xfffffff0,%esp + call __alloca + call ___main + + */ + + gdb_byte op; + + const gdb_byte insns[] = { + 0xb8, 0x00, 0x00, 0x00, 0x00, /* mov $0x0,%eax */ + 0x83, 0xc0, 0x0f, /* add $0xf,%eax */ + 0x83, 0xc0, 0x0f, /* add $0xf,%eax */ + 0xc1, 0xe8, 0x04, /* shr $0x4,%eax */ + 0xc1, 0xe0, 0x04, /* shl $0x4,%eax */ + }; + gdb_byte buf[sizeof insns]; + + if (target_read_memory (pc, buf, sizeof buf) == 0 + && memcmp (buf, insns, sizeof insns) == 0) + { + CORE_ADDR pc2 = pc + sizeof insns; + CORE_ADDR pos; + + /* mov %eax,xxx(%ebp) */ + read_memory_nobpt (pc2, &op, 1); + if (op == 0x89) + { + read_memory_nobpt (pc2 + 1, &op, 1); + switch (op) + { + case 0x45: + pc2 += 3; + break; + case 0x85: + pc2 += 6; + break; + default: + goto other; + } + } + else + goto other; + + /* mov xxx(%ebp),%eax */ + read_memory_nobpt (pc2, &op, 1); + if (op == 0x8b) + { + read_memory_nobpt (pc2 + 1, &op, 1); + switch (op) + { + case 0x45: + pc2 += 3; + break; + case 0x85: + pc2 += 6; + break; + default: + goto other; + } + } + + pos = i386_skip_alloca_call (pc2, limit); + if (pos != pc2) + { + cache->locals += 0x10; + pc = pos; + + if (limit <= pc) + return limit; + } + } + + other: + /* mov $xxx,%eax */ + read_memory_nobpt (pc, &op, 1); + if (op == 0xb8) + { + CORE_ADDR pos = i386_skip_alloca_call (pc + 5, limit); + if (pos != pc + 5) + { + ULONGEST eax = read_memory_unsigned_integer (pc + 1, 4); + cache->locals += eax; + pc = pos; + + if (limit <= pc) + return limit; + } + } + + return pc; +} + +/* Check that the code pointed to by PC corresponds to a call to + __chkstk/_alloca and skip it if so. Return PC otherwise. */ + +static CORE_ADDR +i386_analyze_alloca (CORE_ADDR pc, CORE_ADDR limit, + struct i386_frame_cache *cache) +{ + CORE_ADDR next_pc; + + while ((next_pc = i386_analyze_alloca2 (pc, limit, cache)) != pc) + pc = next_pc; + + return pc; +} + /* Some special instructions that might be migrated by GCC into the part of the prologue that sets up the new stack frame. Because the stack frame hasn't been setup yet, no registers have been saved @@ -634,6 +813,10 @@ struct i386_insn i386_frame_setup_skip_i { 0 } }; +static CORE_ADDR +i386_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc, + struct i386_frame_cache *cache); + /* Check whether PC points at a code that sets up a new stack frame. If so, it updates CACHE and returns the address of the first instruction after the sequence that sets up the frame or LIMIT, @@ -713,7 +896,11 @@ i386_analyze_frame_setup (CORE_ADDR pc, if (limit <= pc) return limit; - /* Check for stack adjustment + /* Check for registers saves seen before stack adjustment. Seen + on targets that emit a call to __main. */ + pc = i386_analyze_register_saves (pc, limit, cache); + + /* Check for stack adjustment subl $XXX, %esp @@ -730,7 +917,7 @@ i386_analyze_frame_setup (CORE_ADDR pc, /* `subl' with signed 8-bit immediate (though it wouldn't make sense to be negative). */ cache->locals = read_memory_integer (pc + 2, 1); - return pc + 3; + pc += 3; } else if (op == 0x81) { @@ -741,13 +928,26 @@ i386_analyze_frame_setup (CORE_ADDR pc, /* It is `subl' with a 32-bit immediate. */ cache->locals = read_memory_integer (pc + 2, 4); - return pc + 6; - } - else - { - /* Some instruction other than `subl'. */ - return pc; + pc += 6; } + + /* _alloca call */ + pc = i386_analyze_alloca (pc, limit, cache); + + /* and $-16,%esp */ + { + const gdb_byte insns[] = { + 0x83, 0xe4, 0xf0 /* and $0xfffffff0,%esp */ + }; + gdb_byte buf[sizeof insns]; + + if (target_read_memory (pc, buf, sizeof buf) == 0 + && memcmp (buf, insns, sizeof insns) == 0) + { + cache->locals &= -16L; + return pc + 3; + } + } } else if (op == 0xc8) /* enter */ { @@ -758,6 +958,73 @@ i386_analyze_frame_setup (CORE_ADDR pc, return pc; } +/* Some instructions that might be migrated by GCC into after the + prologue and just before the __main call. */ + +struct i386_insn i386___main_skip_insns[] = +{ + /* `mov %ecx,%ebx' */ + { 2, { 0x89, 0xcb }, { 0xff, 0xff } }, + + /* `mov (%ecx),%esi' */ + { 2, { 0x8b, 0x31 }, { 0xff, 0xff } }, + + /* `mov xxx(%ecx),%ebx' */ + { 3, { 0x8b, 0x59 }, { 0xff, 0xff } }, + + { 0 } +}; + + +/* Check that the code pointed to by PC corresponds to a call to + __main, skip it if so. Return PC otherwise. */ + +CORE_ADDR +i386_skip___main_call (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + gdb_byte op; + int skip = 0; + CORE_ADDR limit = pc + 20; + + /* Check for some instructions that might be migrated by + GCC into before the __main call and skip them. + + Make sure we only skip these instructions if we later see the + `call ___main'. */ + while (pc + skip < limit) + { + struct i386_insn *insn; + insn = i386_match_insn (pc + skip, i386___main_skip_insns); + if (insn == NULL) + break; + + skip += insn->len; + } + + /* If that's all, return now. */ + if (limit <= pc) + return limit; + + read_memory_nobpt (pc + skip, &op, 1); + if (op == 0xe8) + { + gdb_byte buf[4]; + if (target_read_memory (pc + skip + 1, buf, sizeof buf) == 0) + { + CORE_ADDR call_dest = pc + skip + 5 + extract_unsigned_integer (buf, 4); + + struct minimal_symbol *s = + lookup_minimal_symbol_by_pc (call_dest); + if (s != NULL + && SYMBOL_LINKAGE_NAME (s) != NULL + && strcmp (SYMBOL_LINKAGE_NAME (s), "__main") == 0) + pc += skip + 5; + } + } + + return pc; +} + /* Check whether PC points at code that saves registers on the stack. If so, it updates CACHE and returns the address of the first instruction after the register saves or CURRENT_PC, whichever is @@ -802,16 +1069,18 @@ i386_analyze_register_saves (CORE_ADDR p once used in the System V compiler). Local space is allocated just below the saved %ebp by either the - 'enter' instruction, or by "subl $, %esp". 'enter' has a - 16-bit unsigned argument for space to allocate, and the 'addl' - instruction could have either a signed byte, or 32-bit immediate. + 'enter' instruction, or by "subl $, %esp", or by a call to + _alloca (libgcc/Cygwin). 'enter' has a 16-bit unsigned argument + for space to allocate; the 'addl' instruction could have either a + signed byte, or 32-bit immediate; the _alloca call is passed the + stack space to allocate in %eax. Next, the registers used by this function are pushed. With the System V compiler they will always be in the order: %edi, %esi, %ebx (and sometimes a harmless bug causes it to also save but not restore %eax); however, the code below is willing to see the pushes in any order, and will handle up to 8 of them. - + If the setup sequence is at the end of the function, then the next instruction will be a branch back to the start. */ @@ -824,7 +1093,10 @@ i386_analyze_prologue (CORE_ADDR pc, COR 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); + pc = i386_analyze_register_saves (pc, current_pc, cache); + pc = i386_analyze_alloca (pc, current_pc, cache); + + return pc; } /* Return PC of first real instruction. */ @@ -902,6 +1174,17 @@ i386_skip_prologue (CORE_ADDR start_pc) if (i386_follow_jump (start_pc) != start_pc) pc = i386_follow_jump (pc); + /* Skip __main calls in main. */ + if (gdbarch_skip___main_call_p (current_gdbarch)) + { + struct minimal_symbol *mainf = lookup_minimal_symbol_by_pc (start_pc); + + if (mainf != NULL + && SYMBOL_LINKAGE_NAME (mainf) + && strcmp (SYMBOL_LINKAGE_NAME (mainf), "main") == 0) + pc = gdbarch_skip___main_call (current_gdbarch, pc); + } + return pc; } @@ -956,8 +1239,19 @@ i386_frame_cache (struct frame_info *nex 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 we are analysing a `main', and this target emits __main + calls, %ecx will be clobbered by __main, and possibly pushed + on the stack. */ + if (cache->saved_regs[I386_ECX_REGNUM] != -1) + { + CORE_ADDR ecx = cache->base + cache->saved_regs[I386_ECX_REGNUM]; + read_memory (ecx, buf, 4); + } + else + frame_unwind_register (next_frame, I386_ECX_REGNUM, buf); + + cache->saved_sp = extract_unsigned_integer (buf, 4); } if (cache->locals < 0) @@ -1233,12 +1527,23 @@ i386_frame_base_address (struct frame_in return cache->base; } +static CORE_ADDR +i386_frame_args_address (struct frame_info *next_frame, void **this_cache) +{ + struct i386_frame_cache *cache = i386_frame_cache (next_frame, this_cache); + + if (cache->stack_align) + return cache->saved_sp; + + return cache->base; +} + static const struct frame_base i386_frame_base = { &i386_frame_unwind, - i386_frame_base_address, - i386_frame_base_address, - i386_frame_base_address + i386_frame_base_address, /* base */ + i386_frame_base_address, /* locals */ + i386_frame_args_address /* args */ }; static struct frame_id Index: src/gdb/gdbarch.c =================================================================== --- src.orig/gdb/gdbarch.c 2007-10-12 20:25:22.000000000 +0100 +++ src/gdb/gdbarch.c 2007-10-13 03:52:14.000000000 +0100 @@ -186,6 +186,7 @@ struct gdbarch gdbarch_store_return_value_ftype *store_return_value; gdbarch_deprecated_use_struct_convention_ftype *deprecated_use_struct_convention; gdbarch_skip_prologue_ftype *skip_prologue; + gdbarch_skip___main_call_ftype *skip___main_call; gdbarch_inner_than_ftype *inner_than; gdbarch_breakpoint_from_pc_ftype *breakpoint_from_pc; gdbarch_adjust_breakpoint_address_ftype *adjust_breakpoint_address; @@ -308,6 +309,7 @@ struct gdbarch startup_gdbarch = 0, /* store_return_value */ 0, /* deprecated_use_struct_convention */ 0, /* skip_prologue */ + 0, /* skip___main_call */ 0, /* inner_than */ 0, /* breakpoint_from_pc */ 0, /* adjust_breakpoint_address */ @@ -553,6 +555,7 @@ verify_gdbarch (struct gdbarch *current_ /* Skip verify of deprecated_use_struct_convention, invalid_p == 0 */ if (current_gdbarch->skip_prologue == 0) fprintf_unfiltered (log, "\n\tskip_prologue"); + /* Skip verify of skip___main_call, has predicate */ if (current_gdbarch->inner_than == 0) fprintf_unfiltered (log, "\n\tinner_than"); if (current_gdbarch->breakpoint_from_pc == 0) @@ -966,6 +969,12 @@ gdbarch_dump (struct gdbarch *current_gd "gdbarch_dump: single_step_through_delay = <0x%lx>\n", (long) current_gdbarch->single_step_through_delay); fprintf_unfiltered (file, + "gdbarch_dump: gdbarch_skip___main_call_p() = %d\n", + gdbarch_skip___main_call_p (current_gdbarch)); + fprintf_unfiltered (file, + "gdbarch_dump: skip___main_call = <0x%lx>\n", + (long) current_gdbarch->skip___main_call); + fprintf_unfiltered (file, "gdbarch_dump: gdbarch_skip_permanent_breakpoint_p() = %d\n", gdbarch_skip_permanent_breakpoint_p (current_gdbarch)); fprintf_unfiltered (file, @@ -2136,6 +2145,30 @@ set_gdbarch_skip_prologue (struct gdbarc } int +gdbarch_skip___main_call_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->skip___main_call != NULL; +} + +CORE_ADDR +gdbarch_skip___main_call (struct gdbarch *gdbarch, CORE_ADDR ip) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->skip___main_call != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_skip___main_call called\n"); + return gdbarch->skip___main_call (gdbarch, ip); +} + +void +set_gdbarch_skip___main_call (struct gdbarch *gdbarch, + gdbarch_skip___main_call_ftype skip___main_call) +{ + gdbarch->skip___main_call = skip___main_call; +} + +int gdbarch_inner_than (struct gdbarch *gdbarch, CORE_ADDR lhs, CORE_ADDR rhs) { gdb_assert (gdbarch != NULL); Index: src/gdb/gdbarch.h =================================================================== --- src.orig/gdb/gdbarch.h 2007-10-12 20:25:22.000000000 +0100 +++ src/gdb/gdbarch.h 2007-10-13 03:45:06.000000000 +0100 @@ -388,6 +388,12 @@ typedef CORE_ADDR (gdbarch_skip_prologue extern CORE_ADDR gdbarch_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR ip); extern void set_gdbarch_skip_prologue (struct gdbarch *gdbarch, gdbarch_skip_prologue_ftype *skip_prologue); +extern int gdbarch_skip___main_call_p (struct gdbarch *gdbarch); + +typedef CORE_ADDR (gdbarch_skip___main_call_ftype) (struct gdbarch *gdbarch, CORE_ADDR ip); +extern CORE_ADDR gdbarch_skip___main_call (struct gdbarch *gdbarch, CORE_ADDR ip); +extern void set_gdbarch_skip___main_call (struct gdbarch *gdbarch, gdbarch_skip___main_call_ftype *skip___main_call); + typedef int (gdbarch_inner_than_ftype) (CORE_ADDR lhs, CORE_ADDR rhs); extern int gdbarch_inner_than (struct gdbarch *gdbarch, CORE_ADDR lhs, CORE_ADDR rhs); extern void set_gdbarch_inner_than (struct gdbarch *gdbarch, gdbarch_inner_than_ftype *inner_than); Index: src/gdb/gdbarch.sh =================================================================== --- src.orig/gdb/gdbarch.sh 2007-10-12 20:25:22.000000000 +0100 +++ src/gdb/gdbarch.sh 2007-10-13 03:42:14.000000000 +0100 @@ -514,6 +514,7 @@ f::void:store_return_value:struct type * f::int:deprecated_use_struct_convention:int gcc_p, struct type *value_type:gcc_p, value_type::generic_use_struct_convention::0 f::CORE_ADDR:skip_prologue:CORE_ADDR ip:ip:0:0 +M::CORE_ADDR:skip___main_call:CORE_ADDR ip:ip f::int:inner_than:CORE_ADDR lhs, CORE_ADDR rhs:lhs, rhs:0:0 f::const gdb_byte *:breakpoint_from_pc:CORE_ADDR *pcptr, int *lenptr:pcptr, lenptr::0: M::CORE_ADDR:adjust_breakpoint_address:CORE_ADDR bpaddr:bpaddr Index: src/gdb/i386-cygwin-tdep.c =================================================================== --- src.orig/gdb/i386-cygwin-tdep.c 2007-09-22 17:08:46.000000000 +0100 +++ src/gdb/i386-cygwin-tdep.c 2007-10-13 03:22:58.000000000 +0100 @@ -225,6 +225,8 @@ i386_cygwin_init_abi (struct gdbarch_inf set_gdbarch_skip_trampoline_code (gdbarch, i386_cygwin_skip_trampoline_code); + set_gdbarch_skip___main_call (gdbarch, i386_skip___main_call); + tdep->struct_return = reg_struct_return; tdep->gregset_reg_offset = i386_win32_gregset_reg_offset; Index: src/gdb/i386-tdep.h =================================================================== --- src.orig/gdb/i386-tdep.h 2007-09-22 17:08:46.000000000 +0100 +++ src/gdb/i386-tdep.h 2007-10-13 03:29:48.000000000 +0100 @@ -167,6 +167,9 @@ extern struct type *i386_sse_type (struc /* Functions exported from i386-tdep.c. */ extern CORE_ADDR i386_pe_skip_trampoline_code (CORE_ADDR pc, char *name); +extern CORE_ADDR i386_skip___main_call (struct gdbarch *gdbarch, CORE_ADDR pc); + + /* Return the name of register REGNUM. */ extern char const *i386_register_name (int regnum); --------------050901060709020901000901--