ld/
authorAlan Modra <amodra@gmail.com>
Fri, 25 Jan 2008 12:03:37 +0000 (12:03 +0000)
committerAlan Modra <amodra@gmail.com>
Fri, 25 Jan 2008 12:03:37 +0000 (12:03 +0000)
* ld.texinfo (INSERT): Describe.
* ldgram.y (ldgram_in_script, ldgram_had_equals): Delete.
(INSERT_K, AFTER, BEFORE): Add as tokens.
(ifile_p1): Handle INSERT statements.
(saved_script_handle, force_make_executable): Move to..
* ldmain.c: ..here.
(previous_script_handle): New global var.
* ldmain.h (saved_script_handle, force_make_executable): Declare.
(previous_script_handle): Likewise.
* ldlex.l (INSERT_K, AFTER, BEFORE): Add tokens.
* lexsup.c (parge_args <-T>): Set previous_script_handle.
* ldlang.c (lang_for_each_statement_worker): Handle insert statement.
(map_input_to_output_sections, print_statement): Likewise.
(lang_size_sections_1, lang_do_assignments_1): Likewise.
(insert_os_after): New function, extracted from..
(lang_insert_orphan): ..here.
(process_insert_statements): New function.
(lang_process): Call it.
(lang_add_insert): New function.
* ldlang.h (lang_insert_statement_enum): New.
(lang_insert_statement_type): New.
(lang_statement_union_type): Add insert_statement.
(lang_add_insert): Declare.
ld/testsuite/
* ld-spu/ovl.lnk: Delete overlay.
* ld-spu/ovl1.lnk: New file.
* ld-spu/ovl2.lnk: New file.
* ld-spu/ovl.d: Update.
* ld-spu/ovl2.d: Update.

15 files changed:
ld/ChangeLog
ld/ld.texinfo
ld/ldgram.y
ld/ldlang.c
ld/ldlang.h
ld/ldlex.l
ld/ldmain.c
ld/ldmain.h
ld/lexsup.c
ld/testsuite/ChangeLog
ld/testsuite/ld-spu/ovl.d
ld/testsuite/ld-spu/ovl.lnk
ld/testsuite/ld-spu/ovl1.lnk [new file with mode: 0644]
ld/testsuite/ld-spu/ovl2.d
ld/testsuite/ld-spu/ovl2.lnk [new file with mode: 0644]

index c8e6b5baab31eae84418bdaa9cb6dcb6c30ccffb..ec540adc7a409ab00425d7283d5b618f80cd4d79 100644 (file)
@@ -1,3 +1,29 @@
+2008-01-25  Alan Modra  <amodra@bigpond.net.au>
+
+       * ld.texinfo (INSERT): Describe.
+       * ldgram.y (ldgram_in_script, ldgram_had_equals): Delete.
+       (INSERT_K, AFTER, BEFORE): Add as tokens.
+       (ifile_p1): Handle INSERT statements.
+       (saved_script_handle, force_make_executable): Move to..
+       * ldmain.c: ..here.
+       (previous_script_handle): New global var.
+       * ldmain.h (saved_script_handle, force_make_executable): Declare.
+       (previous_script_handle): Likewise.
+       * ldlex.l (INSERT_K, AFTER, BEFORE): Add tokens.
+       * lexsup.c (parge_args <-T>): Set previous_script_handle.
+       * ldlang.c (lang_for_each_statement_worker): Handle insert statement.
+       (map_input_to_output_sections, print_statement): Likewise.
+       (lang_size_sections_1, lang_do_assignments_1): Likewise.
+       (insert_os_after): New function, extracted from..
+       (lang_insert_orphan): ..here.
+       (process_insert_statements): New function.
+       (lang_process): Call it.
+       (lang_add_insert): New function.
+       * ldlang.h (lang_insert_statement_enum): New.
+       (lang_insert_statement_type): New.
+       (lang_statement_union_type): Add insert_statement.
+       (lang_add_insert): Declare.
+
 2008-01-18  Bob Wilson  <bob.wilson@acm.org>
 
        * scripttempl/elfxtensa.sc: Merge ENTRY and .note.gnu.build-id
index 7d77d1c7d1d8505dc33cf84487edc772ea1180de..00081da9479668e434712b768a5b9eab02db85cf 100644 (file)
@@ -297,10 +297,11 @@ augments the main linker script used for the link (either the default
 linker script or the one specified by using @samp{-T}).  This feature
 permits the linker to link against a file which appears to be an object
 or an archive, but actually merely defines some symbol values, or uses
-@code{INPUT} or @code{GROUP} to load other objects.  Note that
-specifying a script in this way merely augments the main linker script;
-use the @samp{-T} option to replace the default linker script entirely.
-@xref{Scripts}.
+@code{INPUT} or @code{GROUP} to load other objects.  Specifying a
+script in this way merely augments the main linker script, with the
+extra commands placed after the main script; use the @samp{-T} option
+to replace the default linker script entirely, but note the effect of
+the @code{INSERT} command.  @xref{Scripts}.
 
 For options whose names are a single letter,
 option arguments must either follow the option letter without intervening
@@ -2903,6 +2904,35 @@ This command has the same effect as the @samp{--no-define-common}
 command-line option: to make @code{ld} omit the assignment of addresses
 to common symbols even for a non-relocatable output file.
 
+@item INSERT [ AFTER | BEFORE ] @var{output_section}
+@kindex INSERT
+@cindex insert user script into default script
+This command is typically used in a script specified by @samp{-T} to
+augment the default @code{SECTIONS} with, for example, overlays.  It
+inserts all prior linker script statements after (or before)
+@var{output_section}, and also causes @samp{-T} to not override the
+default linker script.  The exact insertion point is as for orphan
+sections.  @xref{Location Counter}.  The insertion happens after the
+linker has mapped input sections to output sections.  Prior to the
+insertion, since @samp{-T} scripts are parsed before the default
+linker script, statements in the @samp{-T} script occur before the
+default linker script statements in the internal linker representation
+of the script.  In particular, input section assignments will be made
+to @samp{-T} output sections before those in the default script.  Here
+is an example of how a @samp{-T} script using @code{INSERT} might look:
+
+@smallexample
+SECTIONS
+@{
+  OVERLAY :
+  @{
+    .ov1 @{ ov1*(.text) @}
+    .ov2 @{ ov2*(.text) @}
+  @}
+@}
+INSERT AFTER .text;
+@end smallexample
+
 @item NOCROSSREFS(@var{section} @var{section} @dots{})
 @kindex NOCROSSREFS(@var{sections})
 @cindex cross references
index 5b68b6be5637ca7587e5d89deb8b59abe43ca82d..f481f54c7d4fa8d7a9f4f0dcce5fc4f7c66ce4d4 100644 (file)
 static enum section_type sectype;
 static lang_memory_region_type *region;
 
-FILE *saved_script_handle = NULL;
-bfd_boolean force_make_executable = FALSE;
-
-bfd_boolean ldgram_in_script = FALSE;
-bfd_boolean ldgram_had_equals = FALSE;
 bfd_boolean ldgram_had_keep = FALSE;
 char *ldgram_vers_current_lang = NULL;
 
@@ -127,7 +122,8 @@ static int error_index;
 %token END
 %left <token> '('
 %token <token> ALIGN_K BLOCK BIND QUAD SQUAD LONG SHORT BYTE
-%token SECTIONS PHDRS DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END DATA_SEGMENT_END
+%token SECTIONS PHDRS INSERT_K AFTER BEFORE
+%token DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END DATA_SEGMENT_END
 %token SORT_BY_NAME SORT_BY_ALIGNMENT
 %token '{' '}'
 %token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH
@@ -352,6 +348,10 @@ ifile_p1:
                  lang_add_nocrossref ($3);
                }
        |       EXTERN '(' extern_name_list ')'
+       |       INSERT_K AFTER NAME
+               { lang_add_insert ($3, 0); }
+       |       INSERT_K BEFORE NAME
+               { lang_add_insert ($3, 1); }
        ;
 
 input_list:
index c5ad76d7c114957606e3f15e4b10258028b2f3fa..de3f64b7fb08e2dd888cbec909223435db689d5b 100644 (file)
@@ -845,6 +845,7 @@ lang_for_each_statement_worker (void (*func) (lang_statement_union_type *),
        case lang_padding_statement_enum:
        case lang_address_statement_enum:
        case lang_fill_statement_enum:
+       case lang_insert_statement_enum:
          break;
        default:
          FAIL ();
@@ -1451,6 +1452,73 @@ output_prev_sec_find (lang_output_section_statement_type *os)
   return NULL;
 }
 
+/* Look for a suitable place for a new output section statement.  The
+   idea is to skip over anything that might be inside a SECTIONS {}
+   statement in a script, before we find another output section
+   statement.  Assignments to "dot" before an output section statement
+   are assumed to belong to it.  An exception to this rule is made for
+   the first assignment to dot, otherwise we might put an orphan
+   before . = . + SIZEOF_HEADERS or similar assignments that set the
+   initial address.  */
+
+static lang_statement_union_type **
+insert_os_after (lang_output_section_statement_type *after)
+{
+  lang_statement_union_type **where;
+  lang_statement_union_type **assign = NULL;
+  bfd_boolean ignore_first;
+
+  ignore_first
+    = after == &lang_output_section_statement.head->output_section_statement;
+
+  for (where = &after->header.next;
+       *where != NULL;
+       where = &(*where)->header.next)
+    {
+      switch ((*where)->header.type)
+       {
+       case lang_assignment_statement_enum:
+         if (assign == NULL)
+           {
+             lang_assignment_statement_type *ass;
+
+             ass = &(*where)->assignment_statement;
+             if (ass->exp->type.node_class != etree_assert
+                 && ass->exp->assign.dst[0] == '.'
+                 && ass->exp->assign.dst[1] == 0
+                 && !ignore_first)
+               assign = where;
+           }
+         ignore_first = FALSE;
+         continue;
+       case lang_wild_statement_enum:
+       case lang_input_section_enum:
+       case lang_object_symbols_statement_enum:
+       case lang_fill_statement_enum:
+       case lang_data_statement_enum:
+       case lang_reloc_statement_enum:
+       case lang_padding_statement_enum:
+       case lang_constructors_statement_enum:
+         assign = NULL;
+         continue;
+       case lang_output_section_statement_enum:
+         if (assign != NULL)
+           where = assign;
+         break;
+       case lang_input_statement_enum:
+       case lang_address_statement_enum:
+       case lang_target_statement_enum:
+       case lang_output_statement_enum:
+       case lang_group_statement_enum:
+       case lang_insert_statement_enum:
+         continue;
+       }
+      break;
+    }
+
+  return where;
+}
+
 lang_output_section_statement_type *
 lang_insert_orphan (asection *s,
                    const char *secname,
@@ -1606,64 +1674,7 @@ lang_insert_orphan (asection *s,
 
          if (place->stmt == NULL)
            {
-             lang_statement_union_type **where;
-             lang_statement_union_type **assign = NULL;
-             bfd_boolean ignore_first;
-
-             /* Look for a suitable place for the new statement list.
-                The idea is to skip over anything that might be inside
-                a SECTIONS {} statement in a script, before we find
-                another output_section_statement.  Assignments to "dot"
-                before an output section statement are assumed to
-                belong to it.  An exception to this rule is made for
-                the first assignment to dot, otherwise we might put an
-                orphan before . = . + SIZEOF_HEADERS or similar
-                assignments that set the initial address.  */
-
-             ignore_first = after == (&lang_output_section_statement.head
-                                      ->output_section_statement);
-             for (where = &after->header.next;
-                  *where != NULL;
-                  where = &(*where)->header.next)
-               {
-                 switch ((*where)->header.type)
-                   {
-                   case lang_assignment_statement_enum:
-                     if (assign == NULL)
-                       {
-                         lang_assignment_statement_type *ass;
-                         ass = &(*where)->assignment_statement;
-                         if (ass->exp->type.node_class != etree_assert
-                             && ass->exp->assign.dst[0] == '.'
-                             && ass->exp->assign.dst[1] == 0
-                             && !ignore_first)
-                           assign = where;
-                       }
-                     ignore_first = FALSE;
-                     continue;
-                   case lang_wild_statement_enum:
-                   case lang_input_section_enum:
-                   case lang_object_symbols_statement_enum:
-                   case lang_fill_statement_enum:
-                   case lang_data_statement_enum:
-                   case lang_reloc_statement_enum:
-                   case lang_padding_statement_enum:
-                   case lang_constructors_statement_enum:
-                     assign = NULL;
-                     continue;
-                   case lang_output_section_statement_enum:
-                     if (assign != NULL)
-                       where = assign;
-                     break;
-                   case lang_input_statement_enum:
-                   case lang_address_statement_enum:
-                   case lang_target_statement_enum:
-                   case lang_output_statement_enum:
-                   case lang_group_statement_enum:
-                     continue;
-                   }
-                 break;
-               }
+             lang_statement_union_type **where = insert_os_after (after);
 
              *add.tail = *where;
              *where = add.head;
@@ -3312,6 +3323,154 @@ map_input_to_output_sections
              aos->addr_tree = s->address_statement.address;
            }
          break;
+       case lang_insert_statement_enum:
+         break;
+       }
+    }
+}
+
+/* An insert statement snips out all the linker statements from the
+   start of the list and places them after the output section
+   statement specified by the insert.  This operation is complicated
+   by the fact that we keep a doubly linked list of output section
+   statements as well as the singly linked list of all statements.  */
+
+static void
+process_insert_statements (void)
+{
+  lang_statement_union_type **s;
+  lang_output_section_statement_type *first_os = NULL;
+  lang_output_section_statement_type *last_os = NULL;
+
+  /* "start of list" is actually the statement immediately after
+     the special abs_section output statement, so that it isn't
+     reordered.  */
+  s = &lang_output_section_statement.head;
+  while (*(s = &(*s)->header.next) != NULL)
+    {
+      if ((*s)->header.type == lang_output_section_statement_enum)
+       {
+         /* Keep pointers to the first and last output section
+            statement in the sequence we may be about to move.  */
+         last_os = &(*s)->output_section_statement;
+         if (first_os == NULL)
+           first_os = last_os;
+       }
+      else if ((*s)->header.type == lang_insert_statement_enum)
+       {
+         lang_insert_statement_type *i = &(*s)->insert_statement;
+         lang_output_section_statement_type *where;
+         lang_output_section_statement_type *os;
+         lang_statement_union_type **ptr;
+         lang_statement_union_type *first;
+
+         where = lang_output_section_find (i->where);
+         if (where != NULL && i->is_before)
+           {
+             do 
+               where = where->prev;
+             while (where != NULL && where->constraint == -1);
+           }
+         if (where == NULL)
+           {
+             einfo (_("%X%P: %s not found for insert\n"), i->where);
+             continue;
+           }
+         /* You can't insert into the list you are moving.  */
+         for (os = first_os; os != NULL; os = os->next)
+           if (os == where || os == last_os)
+             break;
+         if (os == where)
+           {
+             einfo (_("%X%P: %s not found for insert\n"), i->where);
+             continue;
+           }
+
+         /* Deal with reordering the output section statement list.  */
+         if (last_os != NULL)
+           {
+             asection *first_sec, *last_sec;
+
+             /* Snip out the output sections we are moving.  */
+             first_os->prev->next = last_os->next;
+             if (last_os->next == NULL)
+               lang_output_section_statement.tail
+                 = (union lang_statement_union **) &first_os->prev->next;
+             else
+               last_os->next->prev = first_os->prev;
+             /* Add them in at the new position.  */
+             last_os->next = where->next;
+             if (where->next == NULL)
+               lang_output_section_statement.tail
+                 = (union lang_statement_union **) &last_os->next;
+             else
+               where->next->prev = last_os;
+             first_os->prev = where;
+             where->next = first_os;
+
+             /* Move the bfd sections in the same way.  */
+             first_sec = NULL;
+             last_sec = NULL;
+             for (os = first_os; os != NULL; os = os->next)
+               {
+                 if (os->bfd_section != NULL
+                     && os->bfd_section->owner != NULL)
+                   {
+                     last_sec = os->bfd_section;
+                     if (first_sec == NULL)
+                       first_sec = last_sec;
+                   }
+                 if (os == last_os)
+                   break;
+               }
+             if (last_sec != NULL)
+               {
+                 asection *sec = where->bfd_section;
+                 if (sec == NULL)
+                   sec = output_prev_sec_find (where);
+
+                 /* The place we want to insert must come after the
+                    sections we are moving.  So if we find no
+                    section or if the section is the same as our
+                    last section, then no move is needed.  */
+                 if (sec != NULL && sec != last_sec)
+                   {
+                     /* Trim them off.  */
+                     if (first_sec->prev != NULL)
+                       first_sec->prev->next = last_sec->next;
+                     else
+                       output_bfd->sections = last_sec->next;
+                     if (last_sec->next != NULL)
+                       last_sec->next->prev = first_sec->prev;
+                     else
+                       output_bfd->section_last = first_sec->prev;
+                     /* Add back.  */
+                     last_sec->next = sec->next;
+                     if (sec->next != NULL)
+                       sec->next->prev = last_sec;
+                     else
+                       output_bfd->section_last = last_sec;
+                     first_sec->prev = sec;
+                     sec->next = first_sec;
+                   }
+               }
+
+             first_os = NULL;
+             last_os = NULL;
+           }
+
+         ptr = insert_os_after (where);
+         /* Snip everything after the abs_section output statement we
+            know is at the start of the list, up to and including
+            the insert statement we are currently processing.  */
+         first = lang_output_section_statement.head->header.next;
+         lang_output_section_statement.head->header.next = (*s)->header.next;
+         /* Add them back where they belong.  */
+         *s = *ptr;
+         if (*s == NULL)
+           statement_list.tail = s;
+         *ptr = first;
+         s = &lang_output_section_statement.head;
        }
     }
 }
@@ -3954,6 +4113,11 @@ print_statement (lang_statement_union_type *s,
     case lang_group_statement_enum:
       print_group (&s->group_statement, os);
       break;
+    case lang_insert_statement_enum:
+      minfo ("INSERT %s %s\n",
+            s->insert_statement.is_before ? "BEFORE" : "AFTER",
+            s->insert_statement.where);
+      break;
     }
 }
 
@@ -4734,13 +4898,16 @@ lang_size_sections_1
                                      fill, dot, relax, check_regions);
          break;
 
-       default:
-         FAIL ();
+       case lang_insert_statement_enum:
          break;
 
          /* We can only get here when relaxing is turned on.  */
        case lang_address_statement_enum:
          break;
+
+       default:
+         FAIL ();
+         break;
        }
       prev = &s->header.next;
     }
@@ -4999,12 +5166,15 @@ lang_do_assignments_1 (lang_statement_union_type *s,
                                       current_os, fill, dot);
          break;
 
-       default:
-         FAIL ();
+       case lang_insert_statement_enum:
          break;
 
        case lang_address_statement_enum:
          break;
+
+       default:
+         FAIL ();
+         break;
        }
     }
   return dot;
@@ -5853,6 +6023,8 @@ lang_process (void)
      to the correct output sections.  */
   map_input_to_output_sections (statement_list.head, NULL, NULL);
 
+  process_insert_statements ();
+
   /* Find any sections not attached explicitly and handle them.  */
   lang_place_orphans ();
 
@@ -6269,6 +6441,17 @@ lang_add_output_format (const char *format,
     }
 }
 
+void
+lang_add_insert (const char *where, int is_before)
+{
+  lang_insert_statement_type *new;
+
+  new = new_stat (lang_insert_statement, stat_ptr);
+  new->where = where;
+  new->is_before = is_before;
+  saved_script_handle = previous_script_handle;
+}
+
 /* Enter a group.  This creates a new lang_group_statement, and sets
    stat_ptr to build new statements within the group.  */
 
index d0d2cf07f92803462ad418dd9330ffcc9991285e..6de4267e98d71337988739121edc059648c3bad8 100644 (file)
@@ -79,6 +79,7 @@ typedef struct lang_statement_header_struct
     lang_output_statement_enum,
     lang_padding_statement_enum,
     lang_group_statement_enum,
+    lang_insert_statement_enum,
     lang_constructors_statement_enum
   } type;
 } lang_statement_header_type;
@@ -352,6 +353,13 @@ typedef struct
   lang_statement_list_type children;
 } lang_group_statement_type;
 
+typedef struct
+{
+  lang_statement_header_type header;
+  const char *where;
+  bfd_boolean is_before;
+} lang_insert_statement_type;
+
 typedef union lang_statement_union
 {
   lang_statement_header_type header;
@@ -370,6 +378,7 @@ typedef union lang_statement_union
   lang_fill_statement_type fill_statement;
   lang_padding_statement_type padding_statement;
   lang_group_statement_type group_statement;
+  lang_insert_statement_type insert_statement;
 } lang_statement_union_type;
 
 /* This structure holds information about a program header, from the
@@ -565,6 +574,8 @@ extern void lang_size_sections
   (bfd_boolean *, bfd_boolean);
 extern void one_lang_size_sections_pass
   (bfd_boolean *, bfd_boolean);
+extern void lang_add_insert
+  (const char *, int);
 extern void lang_enter_group
   (void);
 extern void lang_leave_group
index c7b1cf91cc0dd6e8c7f3829ceaa227849ef6f3e6..62610cffed01df987097b0cc9ac13b7c8b60b06c 100644 (file)
@@ -274,6 +274,9 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 <BOTH,SCRIPT>"FORCE_COMMON_ALLOCATION" { RTOKEN(FORCE_COMMON_ALLOCATION);}
 <BOTH,SCRIPT>"INHIBIT_COMMON_ALLOCATION" { RTOKEN(INHIBIT_COMMON_ALLOCATION);}
 <BOTH,SCRIPT>"SECTIONS"                        { RTOKEN(SECTIONS);}
+<BOTH,SCRIPT>"INSERT"                  { RTOKEN(INSERT_K);}
+<BOTH,SCRIPT>"AFTER"                   { RTOKEN(AFTER);}
+<BOTH,SCRIPT>"BEFORE"                  { RTOKEN(BEFORE);}
 <BOTH,SCRIPT>"FILL"                    { RTOKEN(FILL);}
 <BOTH,SCRIPT>"STARTUP"                 { RTOKEN(STARTUP);}
 <BOTH,SCRIPT>"OUTPUT_FORMAT"           { RTOKEN(OUTPUT_FORMAT);}
index 29f00d621cd87816d434c0a5569075046c6f4412..a9af255a395c3dd713ee6a6fa8eb483015944b75 100644 (file)
@@ -60,6 +60,10 @@ extern void *sbrk ();
 
 /* EXPORTS */
 
+FILE *saved_script_handle = NULL;
+FILE *previous_script_handle = NULL;
+bfd_boolean force_make_executable = FALSE;
+
 char *default_target;
 const char *output_filename = "a.out";
 
index 549193924280dcc01c6b187a01aaa8b92c8dd296..d297e8a0d6830f39eeb27e2f9cbcd357c98b6a20 100644 (file)
@@ -26,6 +26,9 @@ extern char *program_name;
 extern const char *ld_sysroot;
 extern char *ld_canon_sysroot;
 extern int ld_canon_sysroot_len;
+extern FILE *saved_script_handle;
+extern FILE *previous_script_handle;
+extern bfd_boolean force_make_executable;
 extern bfd *output_bfd;
 extern char *default_target;
 extern bfd_boolean trace_files;
index cdbfbdf213398d45963d9f0a13bd1ad5e0344e62..1e133d9f9a51c747d4b9e38173fd6489aff7003d 100644 (file)
@@ -1166,9 +1166,11 @@ parse_args (unsigned argc, char **argv)
          trace_files = TRUE;
          break;
        case 'T':
+         previous_script_handle = saved_script_handle;
          ldfile_open_command_file (optarg);
          parser_input = input_script;
          yyparse ();
+         previous_script_handle = NULL;
          break;
        case OPTION_DEFAULT_SCRIPT:
          command_line.default_script = optarg;
index f55e310a6a7e20df637942a4d4e633012c94c1cb..bda99a253ae466c1593558a467e3aa7a1169d578 100644 (file)
@@ -1,3 +1,11 @@
+2008-01-25  Alan Modra  <amodra@bigpond.net.au>
+
+       * ld-spu/ovl.lnk: Delete overlay.
+       * ld-spu/ovl1.lnk: New file.
+       * ld-spu/ovl2.lnk: New file.
+       * ld-spu/ovl.d: Update.
+       * ld-spu/ovl2.d: Update.
+
 2008-01-23  Andreas Schwab  <schwab@suse.de>
 
        * ld-gc/gc.c: Make sure used_func is not inlined.
index 0f3deb20af4ff4d1218702c995c28472e0633e69..c6246594ba80e983a3bcc9901e8ab11ca3bdf26c 100644 (file)
@@ -1,5 +1,5 @@
 #source: ovl.s
-#ld: -N -T ovl.lnk --emit-relocs
+#ld: -N -T ovl1.lnk -T ovl.lnk --emit-relocs
 #objdump: -D -r
 
 .*elf32-spu
index 408ed1ebd67c9371a2a5e024dd483c5a0ba51ebe..00156522c32838e07ce3fb51e94f7a6d220b6fd3 100644 (file)
@@ -2,13 +2,6 @@ SECTIONS
 {
   . = SIZEOF_HEADERS;
   .text : { *(.text) *(.stub) }
-
-  OVERLAY 0x400 :
-  {
-    .ov_a1 { *(.ov_a1) }
-    .ov_a2 { *(.ov_a2) }
-  }
-
   .data : { *(.data) *(.ovtab) }
   .bss : { *(.bss) }
 }
diff --git a/ld/testsuite/ld-spu/ovl1.lnk b/ld/testsuite/ld-spu/ovl1.lnk
new file mode 100644 (file)
index 0000000..5fd4844
--- /dev/null
@@ -0,0 +1,9 @@
+SECTIONS
+{
+  OVERLAY 0x400 :
+  {
+    .ov_a1 { *(.ov_a1) }
+    .ov_a2 { *(.ov_a2) }
+  }
+}
+INSERT AFTER .text;
index e4a47a62315144c9577cea83fe88c87e977af79d..bf62e0364f5da45a64e9c4a588dd77922818fc04 100644 (file)
@@ -1,5 +1,5 @@
 #source: ovl2.s
-#ld: -N -T ovl.lnk --emit-relocs
+#ld: -N -T ovl2.lnk -T ovl.lnk --emit-relocs
 #objdump: -D -r
 
 .*elf32-spu
diff --git a/ld/testsuite/ld-spu/ovl2.lnk b/ld/testsuite/ld-spu/ovl2.lnk
new file mode 100644 (file)
index 0000000..9916ab2
--- /dev/null
@@ -0,0 +1,10 @@
+SECTIONS
+{
+  OVERLAY 0x400 :
+  {
+    .ov_a1 { *(.ov_a1) }
+    .ov_a2 { *(.ov_a2) }
+    .empty { empty.o?(.text) }
+  }
+}
+INSERT BEFORE .data;