Boost logo

Boost :

Subject: Re: [boost] [context review] Windows ABI requirements
From: Oliver Kowalke (oliver.kowalke_at_[hidden])
Date: 2011-03-22 04:58:59


> Yes, that's sadly a bit of a pain. Documentation is pretty much
> nonexistent.
> There are a few Word documents in the compiler source tree, but the usual
> course of action was to "ask Kevin".
>
> There are a few bits on his blog somewhere
> http://blogs.msdn.com/b/freik/

I used http://msdn.microsoft.com/de-de/library/9b372w95.aspx 'Calling Convention'. At least which registers must be preserved between function calls and which are used for passing arguemnts to fucntions should be done correct - otherwise I would expect that the tests and the examples should crash.

> >> At least _exit can call into user code, IIRC (preterminators&
> >> terminator registered via .crt$x* sections) and that code may require
> >> a properly aligned stack.
> > why is it not properly aligned?
>
> The stack must be aligned on 16 byte boundary
> http://msdn.microsoft.com/en-us/library/ew5tede7(v=vs.80).aspx
>
> link_fcontext simply calls without adjusting RSP. Hence RSP in _exit is
> RSP-8. Both RSP and RSP-8 cannot be 16-byte aligned.

ok - I'll rework the code

> >> Is its state necessarily live when set_fcontext is called?
> >
> > ?
> Well what happens if there is a SEH exception in code called from the
> context' entrypoint? This usually means some badness, but some Windows
> code
> raises exceptions for compatibility reasons (these are handled by the OS
> after no stack/vectored barrier is found).
>
> The exception dispatcher will walk the stack till it finds a barrier.
> Walking the stack means looking up the RIP in the unwind context against
> various tables.
>
> So if an exception is raised and the unwinder will look at the RIP, find
> unwind info in the EXE/DLL's section. This continues up till the point
> where
> it arrives at the entrypoint specified in the make_fcontext call. But
> there
> is no reason for the unwinder to stop the process there. Instead it will
> find the unwind info for your entrypoint function and apply the
> instructions
> accordingly. However, since you switch stacks in its actual caller, I
> don't
> think these unwind instructions are correct.

I'll take a look into MSDN to check your statements. As you already know it is a pain to get the relevant informations regarding to SEH from the MSDN.
At least catching the C++ exceptions works.

> >> What guarantees are there that poking a few fields in the TIB is good
> >> enough to properly switch the context? At least FLS has more than one
> >> field in the TIB. There's also bookkeeping for whether registered
> >> callbacks have been called.
> >I can only follow the things which the MSDN describes - Windows is
> closed
> source.
> That's understood -- and I do tend to think that there are certain dangers
> with your approach, which should be kept in mind. I maintained the VC++
> CRT
> for quite some time and I had access to the source code, the hidden docs
> and
> all the right people and tend to think that especially the exception
> handling part is an incredibly hard thing to get perfectly correct.

probably you are not allowed to tell me the secrets :^)?
The only chance to get it rigth on Windows is to rely on the MSDN, test (try-and-error).

> > For fiber-local-storage the user is responsible to cleanup.
> I don't recall the specifics, but FLS allows you to register callbacks for
> when a fiber exit (see FlsAlloc). There's some book-keeping information
> somewhere near the end of the TIB for that.

TIB isn't well described in the MSDN (at least the end of the TIB).
AFAIK FLS can only be used if the thread was fibierized (ConvertThreadToFiber()). In the case of fcontext on x86 Windows this isn't done- so boost.context could require not to use FLS.

> >> How are you certain that kernel32/kernelbase/ntdll don't assume that
> >> there's a guard page (where guard page has the Windows defined meaning
> >> as in
> >> PAGE_GUARD) at the end of the stack?
> >
> > Windows 7/XP don't - because you create the stack you could manipulate
> it
> Well, I guess the question would be what happens when you write beyond the
> stack limits. A Win32 thread stack would be autogrown (if address space is
> available). I'm not sure how this works exactly. This may happen entirely
> in
> the kernel. It would seem that you have a PAGE_NOACCESS page below your
> own
> stack, which would look almost the same to the OS as its own stacks.

boost.context doesn't supports automatically growing stacks - I believe it isn't necessary. If I look at my X-server it uses a stack of 276 kB.
the class protected_stack appends a guard page at the end of the memory -generating a segfault/access violation if addresses of this page where accessed.

> >> Even if that all works today, how can you be sure it will on Win8, 9
> >> and beyond?
> > I can't - MS decides how further Windows version will work
> That makes it a bit dangerous. Security has become more of a religion at
> Microsoft...

I don't know what MS will do in its next versions of Windows. If MS decides to break some calling conventions then I've to fix the code. what could I do instead?

> >> BTW, glancing over the docs, an implicit conversion from size_t to
> >> protected_stack seems weird, but that might just be a glitch in the
> >> doc build.
> > could you tell where did you found it
>
> At
> http://ok73.ok.funpic.de/boost/libs/context/doc/html/
> it reads
>
> ...
> protected_stack( std::size_t stacksize)

contructor of class protected_stack takes size_t as argument - do you miss the 'explicit' keyword?

thanks for the hints,
Oliver

-- 
GMX DSL Doppel-Flat ab 19,99 Euro/mtl.! Jetzt mit 
gratis Handy-Flat! http://portal.gmx.net/de/go/dsl

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk