diff options
author | Alan Modra <amodra@gmail.com> | 2018-10-05 11:40:54 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2018-10-08 20:26:08 +1030 |
commit | 64029e93683a266c38d19789e780f3748bd6a188 (patch) | |
tree | 9984a3e982904e0132021869f097249ccdc99759 /bfd/elf-nacl.c | |
parent | 7358942661ccb0ea1e819fd2f5d47914cebf0aa2 (diff) | |
download | gdb-64029e93683a266c38d19789e780f3748bd6a188.zip gdb-64029e93683a266c38d19789e780f3748bd6a188.tar.gz gdb-64029e93683a266c38d19789e780f3748bd6a188.tar.bz2 |
Separate header PT_LOAD for -z separate-code
This patch, along with previous patches in the series, supports
putting the ELF file header and program headers in a PT_LOAD without
sections.
Logic governing whether headers a loaded has changed a little: The
primary reason to include headers is now the presence of
SIZEOF_HEADERS in a linker script. However, to support scripts that
may have reserved space for headers by hand, we continue to add
headers whenever the first section address is past the end of headers
modulo page size.
include/
* bfdlink.h (struct bfd_link_info): Add load_phdrs field.
bfd/
* elf-nacl.c (nacl_modify_segment_map): Cope with header PT_LOAD
lacking sections.
* elf.c (_bfd_elf_map_sections_to_segments): Assume file and
program headers are required when info->load_phdrs. Reorganize
code handling program headers. Generate a mapping without
sections just for file and program headers when -z separate-code
would indicate they should be on a different page to the first
section.
ld/
* ldexp.c (fold_name <SIZEOF_HEADERS>): Set link_info.load_phdrs.
* testsuite/ld-elf/loadaddr1.d: Pass -z noseparate-code.
* testsuite/ld-elf/loadaddr2.d: Likewise.
* testsuite/ld-i386/vxworks2.sd: Adjust expected output.
* testsuite/ld-powerpc/vxworks2.sd: Likewise.
* testsuite/ld-elf/overlay.d: Remove spu xfail.
* testsuite/ld-spu/ovl.lnk: Don't use SIZEOF_HEADERS.
* testsuite/ld-tic6x/dsbt-be.ld: Likewise.
* testsuite/ld-tic6x/dsbt-inrange.ld: Likewise.
* testsuite/ld-tic6x/dsbt-overflow.ld: Likewise.
* testsuite/ld-tic6x/dsbt.ld: Likewise.
Diffstat (limited to 'bfd/elf-nacl.c')
-rw-r--r-- | bfd/elf-nacl.c | 88 |
1 files changed, 46 insertions, 42 deletions
diff --git a/bfd/elf-nacl.c b/bfd/elf-nacl.c index 5f446b4..71b2ad8 100644 --- a/bfd/elf-nacl.c +++ b/bfd/elf-nacl.c @@ -70,8 +70,7 @@ nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info) const struct elf_backend_data *const bed = get_elf_backend_data (abfd); struct elf_segment_map **m = &elf_seg_map (abfd); struct elf_segment_map **first_load = NULL; - struct elf_segment_map **last_load = NULL; - bfd_boolean moved_headers = FALSE; + struct elf_segment_map **headers = NULL; int sizeof_headers; if (info != NULL && info->user_phdrs) @@ -170,56 +169,61 @@ nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info) } /* First, we're just finding the earliest PT_LOAD. - By the normal rules, this will be the lowest-addressed one. - We only have anything interesting to do if it's executable. */ - last_load = m; + By the normal rules, this will be the lowest-addressed one. */ if (first_load == NULL) - { - if (!executable) - goto next; - first_load = m; - } + first_load = m; + /* Now that we've noted the first PT_LOAD, we're looking for the first non-executable PT_LOAD with a nonempty p_filesz. */ - else if (!moved_headers + else if (headers == NULL && segment_eligible_for_headers (seg, bed->minpagesize, sizeof_headers)) - { - /* This is the one we were looking for! - - First, clear the flags on previous segments that - say they include the file header and phdrs. */ - struct elf_segment_map *prevseg; - for (prevseg = *first_load; - prevseg != seg; - prevseg = prevseg->next) - if (prevseg->p_type == PT_LOAD) - { - prevseg->includes_filehdr = 0; - prevseg->includes_phdrs = 0; - } - - /* This segment will include those headers instead. */ - seg->includes_filehdr = 1; - seg->includes_phdrs = 1; - - moved_headers = TRUE; - } + headers = m; } - - next: m = &seg->next; } - if (first_load != last_load && moved_headers) + if (headers != NULL) { - /* Now swap the first and last PT_LOAD segments' - positions in segment_map. */ - struct elf_segment_map *first = *first_load; - struct elf_segment_map *last = *last_load; - *first_load = first->next; - first->next = last->next; - last->next = first; + struct elf_segment_map **last_load = NULL; + struct elf_segment_map *seg; + + m = first_load; + while ((seg = *m) != NULL) + { + if (seg->p_type == PT_LOAD) + { + /* Clear the flags on any previous segment that + included the file header and phdrs. */ + seg->includes_filehdr = 0; + seg->includes_phdrs = 0; + /* Also strip out empty segments. */ + if (seg->count == 0) + { + if (headers == &seg->next) + headers = m; + *m = seg->next; + continue; + } + last_load = m; + } + m = &seg->next; + } + + /* This segment will include those headers instead. */ + seg = *headers; + seg->includes_filehdr = 1; + seg->includes_phdrs = 1; + + if (last_load != NULL && first_load != last_load && first_load != headers) + { + /* Put the first PT_LOAD header last. */ + struct elf_segment_map *first = *first_load; + struct elf_segment_map *last = *last_load; + *first_load = first->next; + first->next = last->next; + last->next = first; + } } return TRUE; |