This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: random commentary on -fsplit-stack (and a bug report)

> > "Jay Freeman (saurik)" <> writes:
> "Ian Lance Taylor" <> wrote:

> > After getting more sleep, I realize that this problem is actually much
> > more endemic than I had even previously thought. Most any vaguely
> > object-oriented library is going to have tons of function pointers in
> > it, and you often interact solely with those function pointers (as in,
> > you have no actual symbol references anywhere). A simple example: in
> > the case of C++, any call to a non-split-stack virtual function will
> > fail.
> Certainly true in principle, but unlikely in practice.  Why would you
> compile part of your C++ program with split-stack and part without?
> Implementing child classes that define virtual methods for classes
> defined in a precompiled library seems like an unusual case to me.

That is actually incredible common, due to object-oriented GUI libraries such as Qt or MFC. Most development for systems like Symbian, or kernel drivers for Darwin (and I personally believe split stacks could be a great boon in kernel development) are also going to involve subclassing code compiled by someone else and overriding virtual methods. The Qt "Getting Started" one-pager actually does this.

That said, the specific situation I was describing was even simpler: just using a library compiled by someone else, not subclassing it. If you call a virtual method it will be a call via a function pointer without a symbol reference. Any and all C++ language bindings are thereby off-limits to code that has been compiled with -fsplit-stack until the function pointer issue is addressed.

> The abstraction break exists not because I thought it was a good idea,
> but because I couldn't see any other way to do it.  The split-stack
> system needs to work in a world with precompiled libraries and where
> people will not change their source code.  Any approach that requires
> people to rebuild the world, or to edit their source code, is a
> non-starter for me.  I don't mind if there is some more efficient
> mechanism which works if we require those steps, but I wanted a system
> that would work where we do not require them.  I'm willing to impose
> restrictions like "you must compile all your source code with
> -fsplit-stack;" I'm not willing to say "you must not use precompiled
> libraries."

I feel like there was some misunderstanding here, mostly because I agree with your constraints. ;P That said, I feel the current implementation does not quit provide this dream: the function-pointer restriction alone makes it impossible to use numerous standard precompiled libraries. FWIW, though: I certainly do not want to go in a direction that requires /more/ intervention than I feel like I am having to make currently, and I agree that it is possible with none and that should be the target.

> > Part of me (and I realize that this causes other tradeoffs, and I'm
> > therefore not even recommending it: more just musing) feels like the
> > notion of "supports split stack" is more of a calling convention. In
> > the same way that gcc currently supports regparm, stdcall, thiscall,
> > fastcall... it seems like it might simply be a new attribute (probably
> > orthogonal to the calling convention) a function can have (and would
> > not have by default): splitcall.
> I'm fine with that, but it requires a source code change, so I want the
> system to work without it.

Accepted. I believe that the extension of this idea can actually be pulled off with compiler flags and a feature I'm calling "fallback symbols" in the linker, which the linker may already support (although a long time ago I spent a lot of time looking at the linker and don't remember it), but I think would be easy to add and something a lot of other projects an interesting tool), but I will not mention this idea again unless I have a solid proposal that actually manages to accomplish that.

> > Actually, thinking about it more: it seems like 99% of these problems
> > could be solved by providing a second symbol definition for the
> > split-stack prologue and binding that as part of the type
> > signature. So, you could either call the "original implementation" of
> > a function using its normal symbol, or you could call the split-stack
> > prologue version of the same function using one that had been mangled
> > with some prefix.
> It's an interesting idea, but my immediate reaction is to ask how this
> helps us in the world where we do not require source code changes.

So, imagine a more general linker feature (again, one which may already exist) that allowed you to have a "low-priority symbol" in your object file. As in, one which if you find a copy elsewhere the linker will use that one, but if it doesn't then it will "fall back" to using the one defined locally in this object file. I think that this fairly general mechanism is easy to specify and can probably be used for all sorts of other tasks that people may come up with; it also is not architecture-dependent (as parsing the instructions for split-stacks is).

Then, when compiling an object file with -fsplit-stack, you A) generate both the original symbols and the ".split.*" symbols, as I described in my e-mail and B) make the lookup of /all/ function symbols be to the ".split.*" varieties. At this point, of course, using libraries compiled without -fsplit-stack would be impossible. However, then we then C) additionally throw a "fall back" ".split.*" stub for every function that we call from the library whose implementation is two instructions: call __morestack_non_split, and then branch to the original symbol.

So, to be clear/explicit: if you compiled a library without -fsplit-stack and a client with it, the client's version of ".split.*" would be used; but, if you compiled the library with -fsplit-stack, then the linker would prefer those exported symbols, and bind to them instead of the low-priority local-only "fallback symbols" we included in our object file.

This scheme also has the benefit that there would be almost no penalty (I say "almost", as technically having the extra few instructions in the file affects the CPU's code cache by bloating the code segments slightly) for distributing -fsplit-stack compiled versions of libraries, including libgcc and lib{std,sup}c++. People consuming those libraries from clients that are not compiled with -fsplit-stack, even if they are using a linker without this feature, would not notice any difference in behavior or any extra code executed: things would just work perfectly.

In the mean time I've faxed in the FSF copyright assignment and am waiting for a reply on that. I am going to be putting together some patches to the implementation for the __{more,split}stack{,_*} soon. I haven't disappeared, or been scared off (far from it, in fact ;P), although this is honestly a side-project for me, so I can't look at it every day (which I only say to be explicit on expectations, not because I thought you actually were bothered that I didn't respond to your e-mail for a few days, as I know you are also busy yourself with many projects ;P).

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]