This is the mail archive of the
mailing list for the binutils project.
cleanup PT_GNU_STACK size handling
- From: Nathan Sidwell <nathan_sidwell at mentor dot com>
- To: binutils <binutils at sourceware dot org>
- Date: Tue, 16 Oct 2012 15:45:37 +0100
- Subject: cleanup PT_GNU_STACK size handling
In working on a uclinux port, I came across the hacks that are in the current 5
uclinux backends of bfd (bfin, frv, lm32, sh, tic6x).
The kernel relies on a non-zero memsz in a PT_GNU_STACK segment to know how much
stack to allocate.
They all have the same set of overrides
* modify_program_headers, munge the hdrs, updating a PT_GNU_STACK segment.
* always_size_sections, looking for __stacksize variable and defaulting or
setting it, if it is unset.
* copy_private_data, propagating a PT_GNU_STACK segment size
That's quite a bunch of duplicated code, and I find the way of overriding the
default via '--defsym __stacksize=VALUE' rather unpleasant. Actually, it
doesn't work, because such a defsym gets a type NOTYPE and the check in
always_size_sections for 'h->type == STT_OBJECT' fails. One ends up with a
duplicate symbol error. I have no idea how long that's been broken.
Anyway, this patch removes all that duplicate code and adds a new way of setting
the stack size. I found the handling of the EXEC flag on PT_GNU_STACK somewhat
random too, and have tried to clean that up and contain it in one place.
*) a new elf linker option '-z stack-size=VALUE'. This is available to all elf
backends. This is passed via a new field in link_info. We distinguish between
'user said zero' and 'use the default', by using the value -1 for the former and
zero for the latter. This is a little ugly, but seemed to be the best way to
ensure default initialize to zero did the right thing.
*) a new elf backend default, elf_backend_stack_align, to set the default
alignment. I defaulted this to 16.
*) In bfd_elf_map_sections_to_segments, when creating the PT_GNU_STACK segment,
we copy the backends alignment, and the link info's stack size.
*) In assign_file_positions_for_non_load_sections, we set the p_memsz value for
a PT_GNU_STACK segment.
*) In copy_elf_program_header we propagate the memsz field likewise. This and
the previous 3 changes allow removal of the uclinux backend's overriding of
modify_program_headers and copy_private_data.
*) Add a new function 'bfd_elf_stack_segment_size' to elflink.c. This sets the
linkinfo size from __stacksize or default, unless it was specified by the user
already. It'd be nice to get rid of the __stacksize handling (given it doesn't
apparently work), but I thought that might be a change too far. Rather than
unconditionally set __stacksize, we only set it if it is undefined (i.e. it's
referenced from somewhere). It is an error to define __stacksize and use '-z
*) Modify bfd_elf_size_dynamic_sections. First, move the handling of
PT_GNU_STACK segment flags to after the backend's size_sections hook has been
called. The logic there's been rewritten to avoid things like creating a
PT_GNU_STACK for -z noexecstack with no size specified. We set the segment
flags if it needs to be executable, or the size is non-zero.
Then I changed all the uclinux backends to remove the now unneeded hooks, and
have the always_size_sections hook call the new bfd_elf_stack_segment_size helper.
I tested this on i686-pc-linux-gnu and all the above mentioned uclinux backends.
There was one progression (ld-sh/fdpic-stack-size, the above-mentioned problem
with '--defsym __stacksize') The new tests pass. I manually checked that
objcopy et all preserved PT_GNU_STACK memsz, but my dejagnu-fu was insufficient
to automate that.
Description: Text document