bfd/
* elf-nacl.c (nacl_modify_segment_map): Fix logic reordering the elf_segment_map list. If an executable segment is page-aligned but does not end with a full page, then append a fake section into the segment map entry that pads out the page. (nacl_final_write_processing): New function. Write the code fill laid out in nacl_modify_segment_map. * elf-nacl.h: Declare it. * elf32-arm.c (elf32_arm_nacl_final_write_processing): New function. (elf_backend_final_write_processing): Define it for NaCl backend. * elf32-i386.c (elf_backend_final_write_processing): Likewise. * elf64-x86-64.c (elf_backend_final_write_processing): Likewise. * elf-nacl.c (segment_eligible_for_headers): Rename MAXPAGESIZE parameter to MINPAGESIZE. (nacl_modify_segment_map): Use minpagesize instead of maxpagesize. * elf32-arm.c (ELF_MINPAGESIZE, ELF_COMMONPAGESIZE): Set to 0x10000 for NaCl targets. ld/testsuite/ * ld-x86-64/ilp32-4-nacl.d: Loosen .shstrtab line regexp to match any file offset. * ld-x86-64/tlsbin-nacl.rd: Update expected code segment PT_LOAD. * ld-x86-64/tlsbindesc-nacl.rd: Likewise. * ld-scripts/rgn-at3.d: XFAIL for *-*-nacl* targets. * ld-scripts/rgn-over8-ok.d: Likewise.
This commit is contained in:
parent
779bd27081
commit
887badb310
@ -1,3 +1,23 @@
|
||||
2013-08-26 Roland McGrath <mcgrathr@google.com>
|
||||
|
||||
* elf-nacl.c (nacl_modify_segment_map): Fix logic reordering the
|
||||
elf_segment_map list. If an executable segment is page-aligned
|
||||
but does not end with a full page, then append a fake section into
|
||||
the segment map entry that pads out the page.
|
||||
(nacl_final_write_processing): New function. Write the code fill
|
||||
laid out in nacl_modify_segment_map.
|
||||
* elf-nacl.h: Declare it.
|
||||
* elf32-arm.c (elf32_arm_nacl_final_write_processing): New function.
|
||||
(elf_backend_final_write_processing): Define it for NaCl backend.
|
||||
* elf32-i386.c (elf_backend_final_write_processing): Likewise.
|
||||
* elf64-x86-64.c (elf_backend_final_write_processing): Likewise.
|
||||
|
||||
* elf-nacl.c (segment_eligible_for_headers): Rename MAXPAGESIZE
|
||||
parameter to MINPAGESIZE.
|
||||
(nacl_modify_segment_map): Use minpagesize instead of maxpagesize.
|
||||
|
||||
* elf32-arm.c (ELF_MINPAGESIZE, ELF_COMMONPAGESIZE): #undef for NaCl.
|
||||
|
||||
2013-08-24 Maciej W. Rozycki <macro@linux-mips.org>
|
||||
|
||||
* elf32-tilepro.c (tilepro_elf_finish_dynamic_sections): Don't
|
||||
|
141
bfd/elf-nacl.c
141
bfd/elf-nacl.c
@ -1,5 +1,5 @@
|
||||
/* Native Client support for ELF
|
||||
Copyright 2012 Free Software Foundation, Inc.
|
||||
Copyright 2012, 2013 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of BFD, the Binary File Descriptor library.
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
|
||||
#include "sysdep.h"
|
||||
#include "bfd.h"
|
||||
#include "libbfd.h"
|
||||
#include "elf-bfd.h"
|
||||
#include "elf-nacl.h"
|
||||
#include "elf/common.h"
|
||||
@ -48,11 +49,11 @@ segment_executable (struct elf_segment_map *seg)
|
||||
allow space for the headers. */
|
||||
static bfd_boolean
|
||||
segment_eligible_for_headers (struct elf_segment_map *seg,
|
||||
bfd_vma maxpagesize, bfd_vma sizeof_headers)
|
||||
bfd_vma minpagesize, bfd_vma sizeof_headers)
|
||||
{
|
||||
bfd_boolean any_contents = FALSE;
|
||||
unsigned int i;
|
||||
if (seg->count == 0 || seg->sections[0]->lma % maxpagesize < sizeof_headers)
|
||||
if (seg->count == 0 || seg->sections[0]->lma % minpagesize < sizeof_headers)
|
||||
return FALSE;
|
||||
for (i = 0; i < seg->count; ++i)
|
||||
{
|
||||
@ -76,7 +77,7 @@ nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
|
||||
struct elf_segment_map **last_load = NULL;
|
||||
bfd_boolean moved_headers = FALSE;
|
||||
int sizeof_headers = info == NULL ? 0 : bfd_sizeof_headers (abfd, info);
|
||||
bfd_vma maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
|
||||
bfd_vma minpagesize = get_elf_backend_data (abfd)->minpagesize;
|
||||
|
||||
if (info != NULL && info->user_phdrs)
|
||||
/* The linker script used PHDRS explicitly, so don't change what the
|
||||
@ -89,20 +90,91 @@ nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
|
||||
|
||||
if (seg->p_type == PT_LOAD)
|
||||
{
|
||||
bfd_boolean executable = segment_executable (seg);
|
||||
|
||||
if (executable
|
||||
&& seg->count > 0
|
||||
&& seg->sections[0]->vma % minpagesize == 0)
|
||||
{
|
||||
asection *lastsec = seg->sections[seg->count - 1];
|
||||
bfd_vma end = lastsec->vma + lastsec->size;
|
||||
if (end % minpagesize != 0)
|
||||
{
|
||||
/* This is an executable segment that starts on a page
|
||||
boundary but does not end on a page boundary. Fill
|
||||
it out to a whole page with code fill (the tail of
|
||||
the segment will not be within any section). Thus
|
||||
the entire code segment can be mapped from the file
|
||||
as whole pages and that mapping will contain only
|
||||
valid instructions.
|
||||
|
||||
To accomplish this, we must fake out the code in
|
||||
assign_file_positions_for_load_sections (elf.c) so
|
||||
that it advances past the rest of the final page,
|
||||
rather than trying to put the next (unaligned, or
|
||||
unallocated) section. We do this by appending a
|
||||
dummy section record to this element in the segment
|
||||
map. No such output section ever actually exists,
|
||||
but this gets the layout logic to advance the file
|
||||
positions past this partial page. Since we are
|
||||
lying to BFD like this, nothing will ever know to
|
||||
write the section contents. So we do that by hand
|
||||
after the fact, in nacl_final_write_processing, below. */
|
||||
|
||||
struct elf_segment_map *newseg;
|
||||
asection *sec;
|
||||
struct bfd_elf_section_data *secdata;
|
||||
|
||||
BFD_ASSERT (!seg->p_size_valid);
|
||||
|
||||
secdata = bfd_zalloc (abfd, sizeof *secdata);
|
||||
if (secdata == NULL)
|
||||
return FALSE;
|
||||
|
||||
sec = bfd_zalloc (abfd, sizeof *sec);
|
||||
if (sec == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* Fill in only the fields that actually affect the logic
|
||||
in assign_file_positions_for_load_sections. */
|
||||
sec->vma = end;
|
||||
sec->lma = lastsec->lma + lastsec->size;
|
||||
sec->size = minpagesize - (end % minpagesize);
|
||||
sec->flags = (SEC_ALLOC | SEC_LOAD
|
||||
| SEC_READONLY | SEC_CODE | SEC_LINKER_CREATED);
|
||||
sec->used_by_bfd = secdata;
|
||||
|
||||
secdata->this_hdr.sh_type = SHT_PROGBITS;
|
||||
secdata->this_hdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
|
||||
secdata->this_hdr.sh_addr = sec->vma;
|
||||
secdata->this_hdr.sh_size = sec->size;
|
||||
|
||||
newseg = bfd_alloc (abfd,
|
||||
sizeof *newseg + ((seg->count + 1)
|
||||
* sizeof (asection *)));
|
||||
if (newseg == NULL)
|
||||
return FALSE;
|
||||
memcpy (newseg, seg,
|
||||
sizeof *newseg + (seg->count * sizeof (asection *)));
|
||||
newseg->sections[newseg->count++] = sec;
|
||||
*m = seg = newseg;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
if (first_load == NULL)
|
||||
{
|
||||
if (!segment_executable (*m))
|
||||
return TRUE;
|
||||
if (!executable)
|
||||
goto next;
|
||||
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
|
||||
&& segment_eligible_for_headers (seg, maxpagesize,
|
||||
&& segment_eligible_for_headers (seg, minpagesize,
|
||||
sizeof_headers))
|
||||
{
|
||||
/* This is the one we were looking for!
|
||||
@ -127,6 +199,7 @@ nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
|
||||
}
|
||||
}
|
||||
|
||||
next:
|
||||
m = &seg->next;
|
||||
}
|
||||
|
||||
@ -183,7 +256,7 @@ nacl_modify_program_headers (bfd *abfd, struct bfd_link_info *info)
|
||||
m = &(*m)->next;
|
||||
++p;
|
||||
|
||||
while ((*m) != NULL)
|
||||
while (*m != NULL)
|
||||
{
|
||||
if (p->p_type == PT_LOAD && p->p_vaddr < first_load_phdr->p_vaddr)
|
||||
{
|
||||
@ -207,12 +280,24 @@ nacl_modify_program_headers (bfd *abfd, struct bfd_link_info *info)
|
||||
struct elf_segment_map *first_next = first_seg->next;
|
||||
struct elf_segment_map *next_next = next_seg->next;
|
||||
|
||||
first_seg->next = next_next;
|
||||
if (next_load_seg == &first_seg->next)
|
||||
{
|
||||
*first_load_seg = next_seg;
|
||||
next_seg->next = first_seg;
|
||||
first_seg->next = next_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
*first_load_seg = first_next;
|
||||
*next_load_seg = next_next;
|
||||
|
||||
next_seg->next = first_next;
|
||||
first_seg->next = *next_load_seg;
|
||||
*next_load_seg = first_seg;
|
||||
|
||||
next_seg->next = *first_load_seg;
|
||||
*first_load_seg = next_seg;
|
||||
}
|
||||
|
||||
move_phdr = *next_load_phdr;
|
||||
memmove (first_load_phdr + 1, first_load_phdr,
|
||||
(next_load_phdr - first_load_phdr) * sizeof move_phdr);
|
||||
@ -222,3 +307,39 @@ nacl_modify_program_headers (bfd *abfd, struct bfd_link_info *info)
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nacl_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED)
|
||||
{
|
||||
struct elf_segment_map *seg;
|
||||
for (seg = elf_seg_map (abfd); seg != NULL; seg = seg->next)
|
||||
if (seg->p_type == PT_LOAD
|
||||
&& seg->count > 1
|
||||
&& seg->sections[seg->count - 1]->owner == NULL)
|
||||
{
|
||||
/* This is a fake section added in nacl_modify_segment_map, above.
|
||||
It's not a real BFD section, so nothing wrote its contents.
|
||||
Now write out its contents. */
|
||||
|
||||
asection *sec = seg->sections[seg->count - 1];
|
||||
char *fill;
|
||||
|
||||
BFD_ASSERT (sec->flags & SEC_LINKER_CREATED);
|
||||
BFD_ASSERT (sec->flags & SEC_CODE);
|
||||
BFD_ASSERT (sec->size > 0);
|
||||
|
||||
fill = abfd->arch_info->fill (sec->size, bfd_big_endian (abfd), TRUE);
|
||||
|
||||
if (fill == NULL
|
||||
|| bfd_seek (abfd, sec->filepos, SEEK_SET) != 0
|
||||
|| bfd_bwrite (fill, sec->size, abfd) != sec->size)
|
||||
{
|
||||
/* We don't have a proper way to report an error here. So
|
||||
instead fudge things so that elf_write_shdrs_and_ehdr will
|
||||
fail. */
|
||||
elf_elfheader (abfd)->e_shoff = (file_ptr) -1;
|
||||
}
|
||||
|
||||
free (fill);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Native Client support for ELF
|
||||
Copyright 2012 Free Software Foundation, Inc.
|
||||
Copyright 2012, 2013 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of BFD, the Binary File Descriptor library.
|
||||
|
||||
@ -22,3 +22,4 @@
|
||||
|
||||
bfd_boolean nacl_modify_segment_map (bfd *, struct bfd_link_info *);
|
||||
bfd_boolean nacl_modify_program_headers (bfd *, struct bfd_link_info *);
|
||||
void nacl_final_write_processing (bfd *, bfd_boolean linker);
|
||||
|
@ -15860,6 +15860,14 @@ elf32_arm_nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
|
||||
&& nacl_modify_segment_map (abfd, info));
|
||||
}
|
||||
|
||||
static void
|
||||
elf32_arm_nacl_final_write_processing (bfd *abfd, bfd_boolean linker)
|
||||
{
|
||||
elf32_arm_final_write_processing (abfd, linker);
|
||||
nacl_final_write_processing (abfd, linker);
|
||||
}
|
||||
|
||||
|
||||
#undef elf32_bed
|
||||
#define elf32_bed elf32_arm_nacl_bed
|
||||
#undef bfd_elf32_bfd_link_hash_table_create
|
||||
@ -15871,9 +15879,14 @@ elf32_arm_nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
|
||||
#define elf_backend_modify_segment_map elf32_arm_nacl_modify_segment_map
|
||||
#undef elf_backend_modify_program_headers
|
||||
#define elf_backend_modify_program_headers nacl_modify_program_headers
|
||||
#undef elf_backend_final_write_processing
|
||||
#define elf_backend_final_write_processing elf32_arm_nacl_final_write_processing
|
||||
|
||||
#undef ELF_MAXPAGESIZE
|
||||
#define ELF_MAXPAGESIZE 0x10000
|
||||
#undef ELF_MINPAGESIZE
|
||||
#undef ELF_COMMONPAGESIZE
|
||||
|
||||
|
||||
#include "elf32-target.h"
|
||||
|
||||
@ -15882,6 +15895,13 @@ elf32_arm_nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
|
||||
#undef elf_backend_modify_segment_map
|
||||
#define elf_backend_modify_segment_map elf32_arm_modify_segment_map
|
||||
#undef elf_backend_modify_program_headers
|
||||
#undef elf_backend_final_write_processing
|
||||
#define elf_backend_final_write_processing elf32_arm_final_write_processing
|
||||
#undef ELF_MINPAGESIZE
|
||||
#define ELF_MINPAGESIZE 0x1000
|
||||
#undef ELF_COMMONPAGESIZE
|
||||
#define ELF_COMMONPAGESIZE 0x1000
|
||||
|
||||
|
||||
/* VxWorks Targets. */
|
||||
|
||||
|
@ -5302,12 +5302,15 @@ static const struct elf_i386_backend_data elf_i386_nacl_arch_bed =
|
||||
#define elf_backend_modify_segment_map nacl_modify_segment_map
|
||||
#undef elf_backend_modify_program_headers
|
||||
#define elf_backend_modify_program_headers nacl_modify_program_headers
|
||||
#undef elf_backend_final_write_processing
|
||||
#define elf_backend_final_write_processing nacl_final_write_processing
|
||||
|
||||
#include "elf32-target.h"
|
||||
|
||||
/* Restore defaults. */
|
||||
#undef elf_backend_modify_segment_map
|
||||
#undef elf_backend_modify_program_headers
|
||||
#undef elf_backend_final_write_processing
|
||||
|
||||
/* VxWorks support. */
|
||||
|
||||
|
@ -5399,6 +5399,8 @@ static const struct elf_x86_64_backend_data elf_x86_64_nacl_arch_bed =
|
||||
#define elf_backend_modify_segment_map nacl_modify_segment_map
|
||||
#undef elf_backend_modify_program_headers
|
||||
#define elf_backend_modify_program_headers nacl_modify_program_headers
|
||||
#undef elf_backend_final_write_processing
|
||||
#define elf_backend_final_write_processing nacl_final_write_processing
|
||||
|
||||
#include "elf64-target.h"
|
||||
|
||||
@ -5443,6 +5445,7 @@ static const struct elf_x86_64_backend_data elf_x86_64_nacl_arch_bed =
|
||||
#undef elf_backend_size_info
|
||||
#undef elf_backend_modify_segment_map
|
||||
#undef elf_backend_modify_program_headers
|
||||
#undef elf_backend_final_write_processing
|
||||
|
||||
/* Intel L1OM support. */
|
||||
|
||||
|
@ -1,3 +1,12 @@
|
||||
2013-08-26 Roland McGrath <mcgrathr@google.com>
|
||||
|
||||
* ld-x86-64/ilp32-4-nacl.d: Loosen .shstrtab line regexp to match
|
||||
any file offset.
|
||||
* ld-x86-64/tlsbin-nacl.rd: Update expected code segment PT_LOAD.
|
||||
* ld-x86-64/tlsbindesc-nacl.rd: Likewise.
|
||||
* ld-scripts/rgn-at3.d: XFAIL for *-*-nacl* targets.
|
||||
* ld-scripts/rgn-over8-ok.d: Likewise.
|
||||
|
||||
2013-08-24 Maciej W. Rozycki <macro@linux-mips.org>
|
||||
|
||||
* ld-elf/comm-data.exp: Use check_shared_lib_support rather than
|
||||
|
@ -2,9 +2,13 @@
|
||||
# source: rgn-at.s
|
||||
# ld: -T rgn-at3.t
|
||||
# objdump: -w -h
|
||||
# xfail: rx-*-*
|
||||
# xfail: rx-*-* *-*-nacl*
|
||||
# FAILS on the RX because the linker has to set LMA == VMA for the
|
||||
# Renesas loader.
|
||||
# FAILs on NaCl targets because the linker extends the first segment
|
||||
# to fill out the page, making its p_vaddr+p_memsz cover the sh_addr
|
||||
# of .bss too, which makes BFD compute its LMA from the p_paddr of the
|
||||
# text segment.
|
||||
|
||||
.*: file format .*
|
||||
|
||||
|
@ -2,9 +2,13 @@
|
||||
# source: rgn-over8.s
|
||||
# ld: -T rgn-over8.t
|
||||
# objdump: -w -h
|
||||
# xfail: rx-*-*
|
||||
# xfail: rx-*-* *-*-nacl*
|
||||
# FAILS on the RX because the linker has to set LMA == VMA for the
|
||||
# Renesas loader.
|
||||
# FAILs on NaCl targets because the linker extends the first segment
|
||||
# to fill out the page, making its p_vaddr+p_memsz cover the sh_addr
|
||||
# of .bss too, which makes BFD compute its LMA from the p_paddr of the
|
||||
# text segment.
|
||||
|
||||
.*: file format .*
|
||||
|
||||
|
@ -14,7 +14,7 @@ Section Headers:
|
||||
+\[ 3\] \.dynsym +DYNSYM +100000e0 +0+e0 +0+60 +10 +A +4 +2 +4
|
||||
+\[ 4\] \.dynstr +STRTAB +10000140 +0+140 +0+19 +00 +A +0 +0 +1
|
||||
+\[ 5\] \.dynamic +DYNAMIC +1001015c +0+15c +0+58 +08 +WA +4 +0 +4
|
||||
+\[ 6\] \.shstrtab +STRTAB +0+ +0+10001 +0+40 +00 +0 +0 +1
|
||||
+\[ 6\] \.shstrtab +STRTAB +0+ +[0-9a-f]+ +0+40 +00 +0 +0 +1
|
||||
+\[ 7\] \.symtab +SYMTAB +0+0 +[0-9a-f]+ +[0-9a-f]+ +10 +8 +[0-9] +4
|
||||
+\[ 8\] \.strtab +STRTAB +0+ +[0-9a-f]+ +[0-9a-f]+ +00 +0 +0 +1
|
||||
Key to Flags:
|
||||
|
@ -40,7 +40,7 @@ Program Headers:
|
||||
+PHDR.*
|
||||
+INTERP.*
|
||||
.*Requesting program interpreter.*
|
||||
+LOAD +0x0+10000 0x0+20000 0x0+20000 0x0+1231 0x0+1231 R E +0x10000
|
||||
+LOAD +0x0+10000 0x0+20000 0x0+20000 0x0+10000 0x0+10000 R E +0x10000
|
||||
+LOAD +0x0+ 0x0+10020000 0x0+10020000 0x0+3b0 0x0+3b0 R +0x10000
|
||||
+LOAD +0x0+3b0 0x0+100303b0 0x0+100303b0 0x0+1e0 0x0+1e0 RW +0x10000
|
||||
+DYNAMIC +0x0+410 0x0+10030410 0x0+10030410 0x0+140 0x0+140 RW +0x8
|
||||
|
@ -38,7 +38,7 @@ Program Headers:
|
||||
+PHDR.*
|
||||
+INTERP.*
|
||||
.*Requesting program interpreter.*
|
||||
+LOAD +0x0+10000 0x0+20000 0x0+20000 0x0+1fd 0x0+1fd R E 0x10000
|
||||
+LOAD +0x0+10000 0x0+20000 0x0+20000 0x0+10000 0x0+10000 R E 0x10000
|
||||
+LOAD +0x0+ 0x0+10020000 0x0+10020000 0x0+370 0x0+370 R +0x10000
|
||||
+LOAD +0x0+370 0x0+10030370 0x0+10030370 0x0+198 0x0+198 RW +0x10000
|
||||
+DYNAMIC +0x0+3d0 0x0+100303d0 0x0+100303d0 0x0+100 0x0+100 RW +0x8
|
||||
|
Loading…
Reference in New Issue
Block a user