New INSERT linker script command
Alan Modra
amodra@bigpond.net.au
Sun Jan 27 00:36:00 GMT 2008
This implements a new INSERT linker command for those who want to
tweak the default linker script a little but can't lay their hands on
an editor, or for whatever reason don't find it convenient to modify
the default linker script. More than that actually. It also provides
a way to specify output sections that are placed later in the binary
whose input section patterns match earlier.
* 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.
Index: ld/ld.texinfo
===================================================================
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.205
diff -u -p -r1.205 ld.texinfo
--- ld/ld.texinfo 11 Jan 2008 09:11:17 -0000 1.205
+++ ld/ld.texinfo 25 Jan 2008 03:01:09 -0000
@@ -297,10 +297,11 @@ augments the main linker script used for
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
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: ld/ldgram.y
===================================================================
RCS file: /cvs/src/src/ld/ldgram.y,v
retrieving revision 1.56
diff -u -p -r1.56 ldgram.y
--- ld/ldgram.y 6 Jul 2007 14:09:41 -0000 1.56
+++ ld/ldgram.y 24 Jan 2008 01:54:53 -0000
@@ -49,11 +49,6 @@
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: ld/ldmain.c
===================================================================
RCS file: /cvs/src/src/ld/ldmain.c,v
retrieving revision 1.126
diff -u -p -r1.126 ldmain.c
--- ld/ldmain.c 11 Jan 2008 09:11:17 -0000 1.126
+++ ld/ldmain.c 24 Jan 2008 01:54:58 -0000
@@ -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: ld/ldmain.h
===================================================================
RCS file: /cvs/src/src/ld/ldmain.h,v
retrieving revision 1.13
diff -u -p -r1.13 ldmain.h
--- ld/ldmain.h 6 Jul 2007 14:09:41 -0000 1.13
+++ ld/ldmain.h 24 Jan 2008 01:54:58 -0000
@@ -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: ld/ldlex.l
===================================================================
RCS file: /cvs/src/src/ld/ldlex.l,v
retrieving revision 1.39
diff -u -p -r1.39 ldlex.l
--- ld/ldlex.l 6 Jul 2007 14:09:41 -0000 1.39
+++ ld/ldlex.l 24 Jan 2008 01:54:58 -0000
@@ -274,6 +274,9 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([
<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: ld/lexsup.c
===================================================================
RCS file: /cvs/src/src/ld/lexsup.c,v
retrieving revision 1.102
diff -u -p -r1.102 lexsup.c
--- ld/lexsup.c 17 Aug 2007 13:23:08 -0000 1.102
+++ ld/lexsup.c 24 Jan 2008 01:54:59 -0000
@@ -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: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.278
diff -u -p -r1.278 ldlang.c
--- ld/ldlang.c 16 Jan 2008 01:28:21 -0000 1.278
+++ ld/ldlang.c 24 Jan 2008 01:54:56 -0000
@@ -845,6 +845,7 @@ lang_for_each_statement_worker (void (*f
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_sectio
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_ty
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_un
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 *form
}
}
+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: ld/ldlang.h
===================================================================
RCS file: /cvs/src/src/ld/ldlang.h,v
retrieving revision 1.76
diff -u -p -r1.76 ldlang.h
--- ld/ldlang.h 16 Jan 2008 01:29:42 -0000 1.76
+++ ld/ldlang.h 24 Jan 2008 01:54:57 -0000
@@ -79,6 +79,7 @@ typedef struct lang_statement_header_str
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: ld/testsuite/ld-spu/ovl.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-spu/ovl.d,v
retrieving revision 1.4
diff -u -p -r1.4 ovl.d
--- ld/testsuite/ld-spu/ovl.d 25 Sep 2007 08:27:39 -0000 1.4
+++ ld/testsuite/ld-spu/ovl.d 24 Jan 2008 01:55:03 -0000
@@ -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: ld/testsuite/ld-spu/ovl.lnk
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-spu/ovl.lnk,v
retrieving revision 1.2
diff -u -p -r1.2 ovl.lnk
--- ld/testsuite/ld-spu/ovl.lnk 18 Apr 2007 03:55:10 -0000 1.2
+++ ld/testsuite/ld-spu/ovl.lnk 24 Jan 2008 01:55:03 -0000
@@ -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) }
}
Index: ld/testsuite/ld-spu/ovl2.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-spu/ovl2.d,v
retrieving revision 1.4
diff -u -p -r1.4 ovl2.d
--- ld/testsuite/ld-spu/ovl2.d 25 Sep 2007 08:27:39 -0000 1.4
+++ ld/testsuite/ld-spu/ovl2.d 24 Jan 2008 01:55:03 -0000
@@ -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
Index: ld/testsuite/ld-spu/ovl1.lnk
===================================================================
RCS file: ld/testsuite/ld-spu/ovl1.lnk
diff -N ld/testsuite/ld-spu/ovl1.lnk
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-spu/ovl1.lnk 24 Jan 2008 06:27:41 -0000
@@ -0,0 +1,9 @@
+SECTIONS
+{
+ OVERLAY 0x400 :
+ {
+ .ov_a1 { *(.ov_a1) }
+ .ov_a2 { *(.ov_a2) }
+ }
+}
+INSERT AFTER .text;
Index: ld/testsuite/ld-spu/ovl2.lnk
===================================================================
RCS file: ld/testsuite/ld-spu/ovl2.lnk
diff -N ld/testsuite/ld-spu/ovl2.lnk
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-spu/ovl2.lnk 24 Jan 2008 06:27:41 -0000
@@ -0,0 +1,10 @@
+SECTIONS
+{
+ OVERLAY 0x400 :
+ {
+ .ov_a1 { *(.ov_a1) }
+ .ov_a2 { *(.ov_a2) }
+ .empty { empty.o?(.text) }
+ }
+}
+INSERT BEFORE .data;
--
Alan Modra
Australia Development Lab, IBM
More information about the Binutils
mailing list