| From | Sent On | Attachments |
|---|---|---|
| Terry Lambert | Jun 29, 2002 3:13 pm | |
| Jake Burkholder | Jun 29, 2002 3:55 pm | |
| Alfred Perlstein | Jun 29, 2002 4:08 pm | |
| Julian Elischer | Jun 29, 2002 4:14 pm | |
| Jake Burkholder | Jun 29, 2002 4:24 pm | |
| Bill Huey | Jun 29, 2002 4:25 pm | |
| Terry Lambert | Jun 29, 2002 5:50 pm | |
| Bill Huey | Jun 29, 2002 6:18 pm | |
| David O'Brien | Jun 29, 2002 7:39 pm | |
| Bakul Shah | Jun 29, 2002 10:40 pm | |
| Arun Sharma | Jun 29, 2002 11:31 pm | |
| Peter Wemm | Jun 29, 2002 11:59 pm | |
| Igor Sysoev | Jun 30, 2002 2:49 am | |
| Terry Lambert | Jun 30, 2002 3:24 am | |
| Terry Lambert | Jun 30, 2002 3:38 am | |
| Eivind Eklund | Jun 30, 2002 3:44 am | |
| Terry Lambert | Jun 30, 2002 4:39 am | |
| Cedric Berger | Jun 30, 2002 5:14 am | |
| Terry Lambert | Jun 30, 2002 5:24 am | |
| Peter Wemm | Jun 30, 2002 1:42 pm |
| Subject: | Re: Time to make the stack non-executable? | |
|---|---|---|
| From: | Bakul Shah (bak...@bitblocks.com) | |
| Date: | Jun 29, 2002 10:40:01 pm | |
| List: | org.freebsd.freebsd-arch | |
GCC uses trampolines to handle addresses of nested functions. This is a method that allows you to avoid passing a static link of a nested function as a separate (but hidden) arg.
(For the benefit of people who don't know this technique) Consider: int f(int(*p)(int), int x) { return p(2*x); } int g(int a) { int b; int h(int c) { return b + c; } b = a*a; return f(&h, 2); } int i(int d) { return f(&g, 2); }
Here h is a function nested within g. When g is called, it calls h and passes it the address of h. When h is called from f, it must have access to locals in the containing g's frame. Normally you'd passed a hidden static link (address of g's frame). Alternately you can construct a trampoline function on the stack and pass its address (compile the above example and see for yourself). Since this function is created at runtime, it has the necessary information to provide the right static link before calling g. By putting it on the stack it is removed upon return from g (i.e. no need to garbage collect it).
For details please see gcc.info and http://master.debian.org/~karlheg/Usenix88-lexic.pdf
I don't know if other compilers use this technique. You should ask on comp.lang.{lisp,scheme,functional,ada,pascal,misc,...} before going ahead with this change.
In any case, IMHO you are patching the wrong thing. Any time you have more user mode threads than the kernel supplied ones, you can't say anything about where the actual stack is (since the stack switching must be done in user mode and the kernel can't play any stack segment switching games). Also, with threads there is not much point in having a stack segment that grows downward since threads may die in any order. As an example I have a simulation core where I can create as many threads as I want subject to memory limits (100K+ is no problem). I simply malloc() the stack for each thread. The point being, if you don't want an executable stack you must also not allow executable data segment since for a threaded program that is where a stack may be. This *will* contrain LISP + functional languages which create function closures on the fly or increase the cost of such function closure a lot.
-- bakul
To Unsubscribe: send mail to majo...@FreeBSD.org with "unsubscribe freebsd-arch" in the body of the message





