+/* Return non-zero if the function starting at START_PC has a prologue + that sets up a standard frame. */ + +static int +i386_function_has_frame (CORE_ADDR start_pc) +{ + struct i386_frame_cache cache; + + cache.locals = -1; + i386_analyze_prologue (start_pc, 0xffffffff, &cache); + + return (cache.locals >= 0); +} + +/* Return non-zero if PC is inside one of the inferior's DLLs. */ + +static int +i386_in_dll (CORE_ADDR pc) +{ + char *so_name = solib_address (pc); + int len; + + if (so_name == NULL) + return 0; + + len = strlen (so_name); + if (len < 5) + return 0; + + return ((so_name[len - 1] == 'l' || so_name[len - 1] == 'L') + && (so_name[len - 2] == 'l' || so_name[len - 2] == 'L') + && (so_name[len - 3] == 'd' || so_name[len - 3] == 'D') + && so_name[len - 4] == '.'); +} + /* Normal frames. */ static struct i386_frame_cache * @@ -954,20 +1159,49 @@ i386_frame_cache (struct frame_info *nex frame by looking at the stack pointer. For truly "frameless" functions this might work too. */ - 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; + if (i386_in_dll (cache->pc) + && !i386_function_has_frame (cache->pc)) + { + /* Functions in DLL for which do not seem to create a standard + frame are unwound using %ebp. This is actually the caller's + frame base instead of our own, but there are some functions + such as WaitForSingleObjectEx in one of the Windows system + DLLs for which the frame base cannot possibly be determined + from the stack pointer. As a consequence, our caller will be + missing from the backtrace, but this is better than having + an aborted backtrace due to a bogus frame base. + + We use this approach only for functions in DLLs because + this is the only place where we have seen the type of + highly optimized code that cause us trouble. In other + cases, we expect the code to come with frame debugging + information, making prologue scanning unnecessary. + + We also avoid blindly following %ebp if we are midway through + setting up a standard frame. In that case, we know how to + determine the frame base using the stack pointer. */ - /* This will be added back below. */ - cache->saved_regs[I386_EIP_REGNUM] -= cache->base; - } + cache->saved_regs[I386_EBP_REGNUM] = 0; + } else - { - 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