daily update
[deliverable/binutils-gdb.git] / bfd / elf-nacl.c
index 3ba7f5582e41e13093147b77214c2ba6a4eff2c9..6753c7cfbf26314f8b19e57612dac301260d65b4 100644 (file)
@@ -42,14 +42,21 @@ segment_executable (struct elf_segment_map *seg)
   return FALSE;
 }
 
+/* Determine if this segment is eligible to receive the file and program
+   headers.  It must be read-only, non-executable, and have contents.
+   Its first section must start far enough past the page boundary to
+   allow space for the headers.  */
 static bfd_boolean
-segment_nonexecutable_and_has_contents (struct elf_segment_map *seg)
+segment_eligible_for_headers (struct elf_segment_map *seg,
+                              bfd_vma maxpagesize, bfd_vma sizeof_headers)
 {
   bfd_boolean any_contents = FALSE;
   unsigned int i;
+  if (seg->count == 0 || seg->sections[0]->lma % maxpagesize < sizeof_headers)
+    return FALSE;
   for (i = 0; i < seg->count; ++i)
     {
-      if (seg->sections[i]->flags & SEC_CODE)
+      if ((seg->sections[i]->flags & (SEC_CODE|SEC_READONLY)) != SEC_READONLY)
         return FALSE;
       if (seg->sections[i]->flags & SEC_HAS_CONTENTS)
         any_contents = TRUE;
@@ -62,12 +69,19 @@ segment_nonexecutable_and_has_contents (struct elf_segment_map *seg)
    The first non-executable PT_LOAD segment appears first in the file
    and contains the ELF file header and phdrs.  */
 bfd_boolean
-nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
+nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
 {
   struct elf_segment_map **m = &elf_tdata (abfd)->segment_map;
   struct elf_segment_map **first_load = NULL;
   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;
+
+  if (info != NULL && info->user_phdrs)
+    /* The linker script used PHDRS explicitly, so don't change what the
+       user asked for.  */
+    return TRUE;
 
   while (*m != NULL)
     {
@@ -88,7 +102,8 @@ nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
           /* 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_nonexecutable_and_has_contents (seg))
+                   && segment_eligible_for_headers (seg, maxpagesize,
+                                                    sizeof_headers))
             {
               /* This is the one we were looking for!
 
@@ -134,13 +149,17 @@ nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
    proper order for the ELF rule that they must appear in ascending address
    order.  So find the two segments we swapped before, and swap them back.  */
 bfd_boolean
-nacl_modify_program_headers (bfd *abfd,
-                             struct bfd_link_info *info ATTRIBUTE_UNUSED)
+nacl_modify_program_headers (bfd *abfd, struct bfd_link_info *info)
 {
   struct elf_segment_map **m = &elf_tdata (abfd)->segment_map;
   Elf_Internal_Phdr *phdr = elf_tdata (abfd)->phdr;
   Elf_Internal_Phdr *p = phdr;
 
+  if (info != NULL && info->user_phdrs)
+    /* The linker script used PHDRS explicitly, so don't change what the
+       user asked for.  */
+    return TRUE;
+
   /* Find the PT_LOAD that contains the headers (should be the first).  */
   while (*m != NULL)
     {
This page took 0.043638 seconds and 4 git commands to generate.