Section of code from bluez-gnome package: static int attached_adapters(void) { int count = 0; void do_count(gpointer data, gpointer user_data) { struct adapter_data *adapter = data; if (adapter->attached) count++; } g_printerr("Address of do_count is %p\n", do_count); g_list_foreach(adapter_list, do_count, NULL); return count; } Result... Address of do_count is 0xfc03f2f4 Program received signal SIGSEGV, Segmentation fault. [Switching to Thread -134309904 (LWP 31965)] 0xfc03f2f4 in ?? () (gdb) bt #0 0xfc03f2f4 in ?? () #1 0x0ee44454 in g_list_foreach () from /lib/libglib-2.0.so.0 #2 0x10004ae8 in attached_adapters () at main.c:647 #3 0x10005538 in main (argc=1, argv=0xfc03f5f4) at main.c:926 It seems that do_count() is on the stack.
hm, readelf -l shows the stack _is_ marked as executable: GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4 Reassigning to kernel.
I think this is a recent change -- this same binary was working this morning, before I upgraded the kernel and rebooted.
Allegedly happens on i386+NX too. We made non-exec-stack the default, and the code to handle PT_GNU_STACK doesn't seem to be working.
Should be fixed in 2.6.18-1.2734, building now. The option documented as 'default no-exec-stack' is in fact _force_ no-exec-stack, regardless of the PT_GNU_STACK of the binary. We'd turned it on. I've turned it off again and corrected the documentation immediately below it.
This is a repeat of bug 187853. Back to the GCC question though -- why couldn't we achieve the above without having to put code on the stack? A standalone test case... typedef int (*fn)(int *); void invoke_fn(fn foofn, int *x) { foofn(x); } int main(void) { int y = 0; int do_something(int *foo) { foo+=y; } invoke_fn(&do_something, &y); printf("%d\n", y); return 0; } Am I missing some reason (other than the scope and visibilty of 'y' and 'do_something()' which presumably it wouldn't be hard to get right) why the compiler can't treat that fairly much as it does if you apply the following patch (i.e. move both 'y' and 'do_something()' out of main()'s scope).: --- foo.c 2006-10-04 00:45:07.000000000 +0100 +++ foo2.c 2006-10-04 08:44:43.000000000 +0100 @@ -8,14 +8,16 @@ void invoke_fn(fn foofn, int *x) foofn(x); } -int main(void) +static int y = 0; + +static int do_something(int *foo) { - int y = 0; + foo+=y; +} - int do_something(int *foo) - { - foo+=y; - } +int main(void) +{ + y = 0; invoke_fn(&do_something, &y);
How can you turn an automatic variable into a static one? Even __thread doesn't help you, the function can be called recursively and you are supposed to have a new instance of the variable in every function invocation. Also, the nested function pointer can be passed throguh arbitrarily many functions in between, accross many translation units, so the function pointer really has to act as a function pointer. On architectures that have fat function pointers (ia64, ppc64, hppa) you don't need executable trampolines, as you can encode the static chain pointer into the second or third word in the fat pointer. But on the other arches, all you could do to avoid executable trampolines would be to have a pool of stubs compiled into the application (but that would in itself limit the total number of nested function pointers that can be live at one point) and do some garbage collection on them (which would be certainly non-trivial). The toolchain has PT_GNU_STACK for a reason, when the SELinux policy decides not to honor those and track them in yet another way is not toolchain's fault.
(In reply to comment #6) > How can you turn an automatic variable into a static one? Doh. Good point; thanks for pointing it out.