From: Bob Breuer <breuerr@mc.net>
To: Kai Tietz <ktietz70@googlemail.com>
Cc: "gcc@gcc.gnu.org" <gcc@gcc.gnu.org>,
	qemu-devel <qemu-devel@nongnu.org>,
	Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>,
	Richard Henderson <rth@twiddle.net>
Subject: Re: [Qemu-devel] gcc auto-omit-frame-pointer vs msvc longjmp
Date: Wed, 19 Oct 2011 16:05:56 -0500	[thread overview]
Message-ID: <4E9F3BB4.3050604@mc.net> (raw)
In-Reply-To: <CAEwic4aADQUtZOmjAYVVrS1cBU=uRNjwAV49f+GtPtro664JDw@mail.gmail.com>
Kai Tietz wrote:
> 2011/10/18 Bob Breuer <breuerr@mc.net>:
>> Kai Tietz wrote:
>>> 2011/10/17 Bob Breuer <breuerr@mc.net>:
>>>> Richard Henderson wrote:
>>>>> On 10/17/2011 07:09 AM, Bob Breuer wrote:
>>>>>> Google finds a mention of longjmp failing with -fomit-frame-pointer:
>>>>>> http://lua-users.org/lists/lua-l/2005-02/msg00158.html
>>>>>>
>>>>>> Looks like gcc 4.6 turns on -fomit-frame-pointer by default.
>>>>> Hmm.  This is the first I've heard of a longjmp implementation
>>>>> failing without a frame pointer.  Presumably this is with the
>>>>> mingw i.e. msvc libc?
>>>> Yeah, mingw from www.mingw.org which I believe uses msvcrt.dll, package
>>>> gcc-core-4.6.1-2-mingw32-bin.
>>>>
>>>>> This is something that could be worked around in gcc, I suppose.
>>>>> We recognize longjmp for some things, we could force the use of
>>>>> a frame pointer for msvc targets too.
>>>>>
>>>>> For now it might be best to simply force -fno-omit-frame-pointer
>>>>> for mingw host in the configure script.
>>>> Here's a testcase that crashes on the longjmp:
>>>>
>>>> #include <stdio.h>
>>>> #include <setjmp.h>
>>>>
>>>> jmp_buf env;
>>>>
>>>> int test(void)
>>>> {
>>>>  int i;
>>>>
>>>>  asm("xor %%ebp,%%ebp" ::: "ebp");
>>>>
>>>>  i = setjmp(env);
>>>>  printf("i = %d\n", i);
>>>>
>>>>  if (i == 0)
>>>>    longjmp(env, 2);
>>>>
>>>>  return i;
>>>> }
>>>>
>>>> int main(void)
>>>> {
>>>>  return test();
>>>> }
>>>>
>>>> Remove the asm statement to make it not crash.  Obviously with
>>>> omit-frame-pointer, gcc can shove anything into ebp.
>>>>
>>>> Bob
>>> This crash isn'r related to ebp existing, or not. The issue is the
>>> hidden argument of setjmp, which is missing.  If you can try the
>>> following at top of file after include section.
>>>
>>> #define setjmp(BUF) _setjmpex((BUF), NULL)
>>> int __cdecl __attribute__ ((__nothrow__,__returns_twice__))
>>> _setjmp3(jmp_buf _Buf, void *_Ctx);
>>> ...
>> Did you mean _setjmp3 instead of _setjmpex?  With _setjmp3, it works
>> without the asm, but still crashes if I zero out ebp before the setjmp.
>>  Aren't the function arguments on the stack anyway?
> 
> Yes, I mean _setjmp3 (pasto from headers and missed the second line
> prototyping _setjmp3).
> I repeat myself here.  setjmp() has an hidden arguement, which is
> passed on x86 on stack.  By not passing this required argument, setjmp
> will take a random-value from stack.  In your case 'i'.  btw if you
> would pre-initialize 'i' with zero, I would assume you won't see a
> crash, but anyway this is just by chance.
> For this I suggest to use here _setjmp3 instead, as here
> second-argument is documented as being present.
> 
> Btw I tested your code with i686-pc-mingw32 version 4.6.x and 4.7.x
> gcc version.  With my suggested pattern, I don't see a crash for your
> provide test-code with, or without zero-ing ebp.
We probably have a difference in build or run environment.  I've
double-checked with another machine and can get the same crash in
longjmp when running the test executable on both WinXP and Win2k, but
not on Win7.  So it looks like Microsoft may have changed this "feature"
somewhere between WinXP and Win7.
The msvcrt implementation of longjmp (or at least the one I'm looking
at) does a ebp based access using the saved value of ebp.  Here's the
relevant disassembly of longjmp:
0x7801e6f3 in longjmpex () from C:\WINNT\system32\msvcrt.dll
(gdb) disas
Dump of assembler code for function longjmpex:
   0x7801e6ef <+0>:     mov    0x4(%esp),%ebx
=> 0x7801e6f3 <+4>:     mov    (%ebx),%ebp
...
   0x7801e73d <+78>:    call   0x7800bd5e <abnormal_termination+56>
...
   0x7800bd5e <+56>:    push   %ebx
   0x7800bd5f <+57>:    push   %ecx
   0x7800bd60 <+58>:    mov    $0x7803dc64,%ebx
=> 0x7800bd65 <+63>:    mov    0x8(%ebp),%ecx
It crashes on the access of 0x8(%ebp).  Those are the only 2 places
where this version of longjmp touches ebp.  Is it possible to force a
stackframe by just adding a suitable attribute to either the setjmp
function prototype, or the function which calls setjmp?
Bob
next prev parent reply	other threads:[~2011-10-19 21:05 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-10-17  4:39 [Qemu-devel] qemu-system-sparc io-thread segfault on win32 Bob Breuer
     [not found] ` <4E9C0497.2000605@siriusit.co.uk>
2011-10-17 14:09   ` Bob Breuer
2011-10-17 17:22     ` [Qemu-devel] gcc auto-omit-frame-pointer vs msvc longjmp Richard Henderson
2011-10-17 19:14       ` Blue Swirl
2011-10-17 20:11         ` Richard Henderson
2011-10-17 21:20       ` Bob Breuer
2011-10-17 21:31         ` Kai Tietz
2011-10-17 22:23           ` Bob Breuer
2011-10-17 22:56             ` Kai Tietz
2011-10-19 21:05               ` Bob Breuer [this message]
2011-10-19 22:19                 ` Richard Henderson
2011-10-20  4:22                 ` xunxun
2011-10-20 14:48                   ` Kai Tietz
2011-10-20 15:34                     ` Kai Tietz
     [not found]                       ` <j7sgfi$i66$1@dough.gmane.org>
2011-10-22  5:13                         ` xunxun
2011-10-22  5:21                           ` xunxun
2011-10-22 11:19                             ` Kai Tietz
2011-10-22 14:23                       ` asmwarrior
2011-10-24 14:45                       ` Bob Breuer
2011-10-24 16:18                         ` Kai Tietz
2011-10-25 15:14                           ` Bob Breuer
2011-10-20 13:04                 ` jojelino
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox
  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):
  git send-email \
    --in-reply-to=4E9F3BB4.3050604@mc.net \
    --to=breuerr@mc.net \
    --cc=gcc@gcc.gnu.org \
    --cc=ktietz70@googlemail.com \
    --cc=mark.cave-ayland@siriusit.co.uk \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    /path/to/YOUR_REPLY
  https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
  Be sure your reply has a Subject: header at the top and a blank line
  before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).