Take into account MEMORY regions when creating a segment map.
authorNick Clifton <nickc@redhat.com>
Wed, 21 Feb 2007 16:43:50 +0000 (16:43 +0000)
committerNick Clifton <nickc@redhat.com>
Wed, 21 Feb 2007 16:43:50 +0000 (16:43 +0000)
bfd/ChangeLog
bfd/elf.c
include/ChangeLog
include/bfdlink.h
ld/ChangeLog
ld/ldlang.c
ld/ldlang.h
ld/ldmain.c

index f1d2ed745289a708b1c3505edfcb1b9a25908d06..0bd67952294f42f0dc0947b15026155c984aaf41 100644 (file)
@@ -1,3 +1,8 @@
+2007-02-21  Nick Clifton  <nickc@redhat.com>
+
+       * elf.c (_bfd_elf_map_sections_to_segments): If the
+       override_segment_assignment callback is defined then call it.
+
 2007-02-21  Alan Modra  <amodra@bigpond.net.au>
 
        * elf32-spu.c (spu_elf_size_stubs): Correct order of warning args.
index 460502c2e49bd2659c306332294474c4d7531968..95f34010ac98cca8d7d632fc2e4b58c3750fb948 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -3953,6 +3953,10 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
              new_segment = FALSE;
            }
 
+         /* Allow interested parties a chance to override our decision.  */
+         if (last_hdr && info->callbacks->override_segment_assignment)
+           new_segment = info->callbacks->override_segment_assignment (info, abfd, hdr, last_hdr, new_segment);
+
          if (! new_segment)
            {
              if ((hdr->flags & SEC_READONLY) == 0)
index 6c25355f30e4eb1ded28cfa36dde790a252e4c1b..e5b7dba3245d7c6e2953b9d1fe10bf2fe6c29279 100644 (file)
@@ -1,3 +1,8 @@
+2007-02-21  Nick Clifton  <nickc@redhat.com>
+
+       * bfdlink.h (struct bfd_link_callbacks): Add
+       override_segment_assignment field.
+
 2007-02-17  Mark Mitchell  <mark@codesourcery.com>
             Nathan Sidwell  <nathan@codesourcery.com>
             Vladimir Prus  <vladimir@codesourcery.com
index 6842243d094dd47766cf18051fccf01360d08142..46e3cf5c54665b82cbc01cd8e454f751298aa82d 100644 (file)
@@ -566,6 +566,13 @@ struct bfd_link_callbacks
   /* General link info message.  */
   void (*einfo)
     (const char *fmt, ...);
+  /* This callback provides a chance for users of the BFD library to
+     override its decision about whether to place two adjacent sections
+     into the same segment.  */
+  bfd_boolean (*override_segment_assignment)
+    (struct bfd_link_info *, bfd * abfd,
+     asection * current_section, asection * previous_section,
+     bfd_boolean new_segment);
 };
 \f
 /* The linker builds link_order structures which tell the code how to
index cbe05449797d707bcf4bc66ced1fef985e55ea97..7c6506b04e082cd3fd46686b3ecc968d87c73ec3 100644 (file)
@@ -1,3 +1,10 @@
+2007-02-21  Nick Clifton  <nickc@redhat.com>
+
+       * ldlang.c (ldlang_override_segment_assignment): New function.
+       * ldlang.h (ldlang_override_segment_assignment): Prototype.
+       * ldmain.c (link_callbacks): Add
+       ldlang_override_segment_assignment.
+
 2007-02-20  Alan Modra  <amodra@bigpond.net.au>
 
        * ldexp.c (fold_name <LOADADDR>): Ensure result is always absolute.
index 8a69c7028ded822501cbce1da019115cc1f11088..fa597f3c057f8ae49c886a08455e96b6d50065fb 100644 (file)
@@ -4704,6 +4704,42 @@ lang_size_sections_1
   return dot;
 }
 
+/* Callback routine that is used in _bfd_elf_map_sections_to_segments.  */
+
+bfd_boolean
+ldlang_override_segment_assignment (struct bfd_link_info * info ATTRIBUTE_UNUSED,
+                                   bfd * abfd ATTRIBUTE_UNUSED,
+                                   asection * current_section,
+                                   asection * previous_section,
+                                   bfd_boolean new_segment)
+{
+  lang_output_section_statement_type * cur;
+  lang_output_section_statement_type * prev;
+  
+  if (new_segment)
+    return TRUE;
+
+  /* Paranoia checks.  */
+  if (current_section == NULL || previous_section == NULL)
+    return new_segment;
+
+  /* Find the memory regions associated with the two sections.
+     We call lang_output_section_find() here rather than scanning the list
+     of output sections looking for a matching section pointer because if
+     we have a large number of sections a hash lookup is faster.  */
+  cur  = lang_output_section_find (current_section->name);
+  prev = lang_output_section_find (previous_section->name);
+
+  if (cur == NULL || prev == NULL)
+    return new_segment;
+
+  /* If the regions are different then force the sections to live in
+     different segments.  See the email thread starting here for the
+     reasons why this is necessary:
+     http://sourceware.org/ml/binutils/2007-02/msg00216.html  */
+  return cur->region != prev->region;
+}
+
 void
 one_lang_size_sections_pass (bfd_boolean *relax, bfd_boolean check_regions)
 {
index 0074159fc9067e0a0c3029722909dcd21a17097e..d34ea6894d78950b1947057edfffbd2ca7e477d3 100644 (file)
@@ -623,4 +623,8 @@ extern void add_excluded_libs (const char *);
 extern bfd_boolean load_symbols
   (lang_input_statement_type *, lang_statement_list_type *);
 
+extern bfd_boolean
+ldlang_override_segment_assignment
+  (struct bfd_link_info *, bfd *, asection *, asection *, bfd_boolean);
+
 #endif
index 9e6a0c393d85c6af7613d682ecb9785573b07d0f..f47758ffed5930c3ceb9048cc5019a090d23e414 100644 (file)
@@ -161,7 +161,8 @@ static struct bfd_link_callbacks link_callbacks =
   reloc_dangerous,
   unattached_reloc,
   notice,
-  einfo
+  einfo,
+  ldlang_override_segment_assignment
 };
 
 struct bfd_link_info link_info;