* ldlang.h (lang_output_section_find): Define.
(lang_output_section_statement_lookup): Update prototype. * ldlang.c (lang_output_section_find, lang_output_section_statement_lookup_1): Merge into.. (lang_output_section_statement_lookup): ..here. Update all callers. (process_insert_statements): Set constraint negative for output section statements we might be inserting. Make error fatal on not finding insertion section. (lang_output_section_find): Rather than comparing output_section_statement.constraint against -1, test whether it is postive. (lang_output_section_statement_lookup_1): Likewise. (output_prev_sec_find, strip_excluded_output_sections): Likewise. (lang_record_phdrs): Likewise. * emultempl/elf32.em (output_rel_find): Likewise. * NEWS: Mention INSERT.
This commit is contained in:
parent
61aed60ab9
commit
66c103b772
19
ld/ChangeLog
19
ld/ChangeLog
@ -1,3 +1,22 @@
|
|||||||
|
2008-09-07 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
|
* ldlang.h (lang_output_section_find): Define.
|
||||||
|
(lang_output_section_statement_lookup): Update prototype.
|
||||||
|
* ldlang.c (lang_output_section_find,
|
||||||
|
lang_output_section_statement_lookup_1): Merge into..
|
||||||
|
(lang_output_section_statement_lookup): ..here. Update all callers.
|
||||||
|
(process_insert_statements): Set constraint negative
|
||||||
|
for output section statements we might be inserting. Make error
|
||||||
|
fatal on not finding insertion section.
|
||||||
|
(lang_output_section_find): Rather than comparing
|
||||||
|
output_section_statement.constraint against -1, test whether
|
||||||
|
it is postive.
|
||||||
|
(lang_output_section_statement_lookup_1): Likewise.
|
||||||
|
(output_prev_sec_find, strip_excluded_output_sections): Likewise.
|
||||||
|
(lang_record_phdrs): Likewise.
|
||||||
|
* emultempl/elf32.em (output_rel_find): Likewise.
|
||||||
|
* NEWS: Mention INSERT.
|
||||||
|
|
||||||
2008-08-26 Nick Clifton <nickc@redhat.com>
|
2008-08-26 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
PR 6727
|
PR 6727
|
||||||
|
9
ld/NEWS
9
ld/NEWS
@ -1,4 +1,7 @@
|
|||||||
-*- text -*-
|
-*- text -*-
|
||||||
|
* Linker scripts support a new INSERT command that makes it easier to
|
||||||
|
augment the default script.
|
||||||
|
|
||||||
* Linker script input section filespecs may now specify a file within an
|
* Linker script input section filespecs may now specify a file within an
|
||||||
archive by writing "archive:file".
|
archive by writing "archive:file".
|
||||||
|
|
||||||
@ -8,9 +11,9 @@
|
|||||||
* The M68K linker now supports multiple GOT generation schemes controlled via
|
* The M68K linker now supports multiple GOT generation schemes controlled via
|
||||||
the --got=<type> command line option.
|
the --got=<type> command line option.
|
||||||
|
|
||||||
* The ARM EABI linker will now generate stubs for function calls to symbols that
|
* The ARM EABI linker will now generate stubs for function calls to symbols
|
||||||
are too far away. The placement of the stubs is controlled by a new linker
|
that are too far away. The placement of the stubs is controlled by a new
|
||||||
command line option: --stub-group-size=N.
|
linker command line option: --stub-group-size=N.
|
||||||
|
|
||||||
Changes in 2.18:
|
Changes in 2.18:
|
||||||
|
|
||||||
|
@ -1583,7 +1583,7 @@ output_rel_find (asection *sec, int isdyn)
|
|||||||
lookup != NULL;
|
lookup != NULL;
|
||||||
lookup = lookup->next)
|
lookup = lookup->next)
|
||||||
{
|
{
|
||||||
if (lookup->constraint != -1
|
if (lookup->constraint >= 0
|
||||||
&& CONST_STRNEQ (lookup->name, ".rel"))
|
&& CONST_STRNEQ (lookup->name, ".rel"))
|
||||||
{
|
{
|
||||||
int lookrela = lookup->name[4] == 'a';
|
int lookrela = lookup->name[4] == 'a';
|
||||||
|
112
ld/ldlang.c
112
ld/ldlang.c
@ -1149,7 +1149,7 @@ lang_init (void)
|
|||||||
first_file = lang_add_input_file (NULL, lang_input_file_is_marker_enum,
|
first_file = lang_add_input_file (NULL, lang_input_file_is_marker_enum,
|
||||||
NULL);
|
NULL);
|
||||||
abs_output_section =
|
abs_output_section =
|
||||||
lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME);
|
lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME, 0, TRUE);
|
||||||
|
|
||||||
abs_output_section->bfd_section = bfd_abs_section_ptr;
|
abs_output_section->bfd_section = bfd_abs_section_ptr;
|
||||||
|
|
||||||
@ -1255,43 +1255,18 @@ lang_memory_default (asection *section)
|
|||||||
}
|
}
|
||||||
|
|
||||||
lang_output_section_statement_type *
|
lang_output_section_statement_type *
|
||||||
lang_output_section_find (const char *const name)
|
lang_output_section_statement_lookup (const char *const name,
|
||||||
|
int constraint,
|
||||||
|
bfd_boolean create)
|
||||||
{
|
{
|
||||||
struct out_section_hash_entry *entry;
|
struct out_section_hash_entry *entry;
|
||||||
unsigned long hash;
|
|
||||||
|
|
||||||
entry = ((struct out_section_hash_entry *)
|
entry = ((struct out_section_hash_entry *)
|
||||||
bfd_hash_lookup (&output_section_statement_table, name,
|
bfd_hash_lookup (&output_section_statement_table, name,
|
||||||
FALSE, FALSE));
|
create, FALSE));
|
||||||
if (entry == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
hash = entry->root.hash;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (entry->s.output_section_statement.constraint != -1)
|
|
||||||
return &entry->s.output_section_statement;
|
|
||||||
entry = (struct out_section_hash_entry *) entry->root.next;
|
|
||||||
}
|
|
||||||
while (entry != NULL
|
|
||||||
&& entry->root.hash == hash
|
|
||||||
&& strcmp (name, entry->s.output_section_statement.name) == 0);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static lang_output_section_statement_type *
|
|
||||||
lang_output_section_statement_lookup_1 (const char *const name, int constraint)
|
|
||||||
{
|
|
||||||
struct out_section_hash_entry *entry;
|
|
||||||
struct out_section_hash_entry *last_ent;
|
|
||||||
unsigned long hash;
|
|
||||||
|
|
||||||
entry = ((struct out_section_hash_entry *)
|
|
||||||
bfd_hash_lookup (&output_section_statement_table, name,
|
|
||||||
TRUE, FALSE));
|
|
||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
{
|
{
|
||||||
|
if (create)
|
||||||
einfo (_("%P%F: failed creating section `%s': %E\n"), name);
|
einfo (_("%P%F: failed creating section `%s': %E\n"), name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1300,10 +1275,12 @@ lang_output_section_statement_lookup_1 (const char *const name, int constraint)
|
|||||||
{
|
{
|
||||||
/* We have a section of this name, but it might not have the correct
|
/* We have a section of this name, but it might not have the correct
|
||||||
constraint. */
|
constraint. */
|
||||||
hash = entry->root.hash;
|
struct out_section_hash_entry *last_ent;
|
||||||
|
unsigned long hash = entry->root.hash;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (entry->s.output_section_statement.constraint != -1
|
if (entry->s.output_section_statement.constraint >= 0
|
||||||
&& (constraint == 0
|
&& (constraint == 0
|
||||||
|| (constraint == entry->s.output_section_statement.constraint
|
|| (constraint == entry->s.output_section_statement.constraint
|
||||||
&& constraint != SPECIAL)))
|
&& constraint != SPECIAL)))
|
||||||
@ -1315,6 +1292,9 @@ lang_output_section_statement_lookup_1 (const char *const name, int constraint)
|
|||||||
&& entry->root.hash == hash
|
&& entry->root.hash == hash
|
||||||
&& strcmp (name, entry->s.output_section_statement.name) == 0);
|
&& strcmp (name, entry->s.output_section_statement.name) == 0);
|
||||||
|
|
||||||
|
if (!create)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
entry
|
entry
|
||||||
= ((struct out_section_hash_entry *)
|
= ((struct out_section_hash_entry *)
|
||||||
output_section_statement_newfunc (NULL,
|
output_section_statement_newfunc (NULL,
|
||||||
@ -1334,12 +1314,6 @@ lang_output_section_statement_lookup_1 (const char *const name, int constraint)
|
|||||||
return &entry->s.output_section_statement;
|
return &entry->s.output_section_statement;
|
||||||
}
|
}
|
||||||
|
|
||||||
lang_output_section_statement_type *
|
|
||||||
lang_output_section_statement_lookup (const char *const name)
|
|
||||||
{
|
|
||||||
return lang_output_section_statement_lookup_1 (name, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A variant of lang_output_section_find used by place_orphan.
|
/* A variant of lang_output_section_find used by place_orphan.
|
||||||
Returns the output statement that should precede a new output
|
Returns the output statement that should precede a new output
|
||||||
statement for SEC. If an exact match is found on certain flags,
|
statement for SEC. If an exact match is found on certain flags,
|
||||||
@ -1502,7 +1476,7 @@ output_prev_sec_find (lang_output_section_statement_type *os)
|
|||||||
|
|
||||||
for (lookup = os->prev; lookup != NULL; lookup = lookup->prev)
|
for (lookup = os->prev; lookup != NULL; lookup = lookup->prev)
|
||||||
{
|
{
|
||||||
if (lookup->constraint == -1)
|
if (lookup->constraint < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
|
if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
|
||||||
@ -3378,7 +3352,7 @@ map_input_to_output_sections
|
|||||||
{
|
{
|
||||||
lang_output_section_statement_type *aos
|
lang_output_section_statement_type *aos
|
||||||
= (lang_output_section_statement_lookup
|
= (lang_output_section_statement_lookup
|
||||||
(s->address_statement.section_name));
|
(s->address_statement.section_name, 0, TRUE));
|
||||||
|
|
||||||
if (aos->bfd_section == NULL)
|
if (aos->bfd_section == NULL)
|
||||||
init_os (aos, NULL, 0);
|
init_os (aos, NULL, 0);
|
||||||
@ -3403,6 +3377,7 @@ process_insert_statements (void)
|
|||||||
lang_statement_union_type **s;
|
lang_statement_union_type **s;
|
||||||
lang_output_section_statement_type *first_os = NULL;
|
lang_output_section_statement_type *first_os = NULL;
|
||||||
lang_output_section_statement_type *last_os = NULL;
|
lang_output_section_statement_type *last_os = NULL;
|
||||||
|
lang_output_section_statement_type *os;
|
||||||
|
|
||||||
/* "start of list" is actually the statement immediately after
|
/* "start of list" is actually the statement immediately after
|
||||||
the special abs_section output statement, so that it isn't
|
the special abs_section output statement, so that it isn't
|
||||||
@ -3415,6 +3390,12 @@ process_insert_statements (void)
|
|||||||
/* Keep pointers to the first and last output section
|
/* Keep pointers to the first and last output section
|
||||||
statement in the sequence we may be about to move. */
|
statement in the sequence we may be about to move. */
|
||||||
last_os = &(*s)->output_section_statement;
|
last_os = &(*s)->output_section_statement;
|
||||||
|
|
||||||
|
/* Set constraint negative so that lang_output_section_find
|
||||||
|
won't match this output section statement. At this
|
||||||
|
stage in linking constraint has values in the range
|
||||||
|
[-1, ONLY_IN_RW]. */
|
||||||
|
last_os->constraint = -2 - last_os->constraint;
|
||||||
if (first_os == NULL)
|
if (first_os == NULL)
|
||||||
first_os = last_os;
|
first_os = last_os;
|
||||||
}
|
}
|
||||||
@ -3422,7 +3403,6 @@ process_insert_statements (void)
|
|||||||
{
|
{
|
||||||
lang_insert_statement_type *i = &(*s)->insert_statement;
|
lang_insert_statement_type *i = &(*s)->insert_statement;
|
||||||
lang_output_section_statement_type *where;
|
lang_output_section_statement_type *where;
|
||||||
lang_output_section_statement_type *os;
|
|
||||||
lang_statement_union_type **ptr;
|
lang_statement_union_type **ptr;
|
||||||
lang_statement_union_type *first;
|
lang_statement_union_type *first;
|
||||||
|
|
||||||
@ -3431,21 +3411,12 @@ process_insert_statements (void)
|
|||||||
{
|
{
|
||||||
do
|
do
|
||||||
where = where->prev;
|
where = where->prev;
|
||||||
while (where != NULL && where->constraint == -1);
|
while (where != NULL && where->constraint < 0);
|
||||||
}
|
}
|
||||||
if (where == NULL)
|
if (where == NULL)
|
||||||
{
|
{
|
||||||
einfo (_("%X%P: %s not found for insert\n"), i->where);
|
einfo (_("%F%P: %s not found for insert\n"), i->where);
|
||||||
continue;
|
return;
|
||||||
}
|
|
||||||
/* 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. */
|
/* Deal with reordering the output section statement list. */
|
||||||
@ -3482,6 +3453,7 @@ process_insert_statements (void)
|
|||||||
last_sec = NULL;
|
last_sec = NULL;
|
||||||
for (os = first_os; os != NULL; os = os->next)
|
for (os = first_os; os != NULL; os = os->next)
|
||||||
{
|
{
|
||||||
|
os->constraint = -2 - os->constraint;
|
||||||
if (os->bfd_section != NULL
|
if (os->bfd_section != NULL
|
||||||
&& os->bfd_section->owner != NULL)
|
&& os->bfd_section->owner != NULL)
|
||||||
{
|
{
|
||||||
@ -3542,6 +3514,14 @@ process_insert_statements (void)
|
|||||||
s = &lang_output_section_statement.head;
|
s = &lang_output_section_statement.head;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Undo constraint twiddling. */
|
||||||
|
for (os = first_os; os != NULL; os = os->next)
|
||||||
|
{
|
||||||
|
os->constraint = -2 - os->constraint;
|
||||||
|
if (os == last_os)
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* An output section might have been removed after its statement was
|
/* An output section might have been removed after its statement was
|
||||||
@ -3569,7 +3549,7 @@ strip_excluded_output_sections (void)
|
|||||||
asection *output_section;
|
asection *output_section;
|
||||||
bfd_boolean exclude;
|
bfd_boolean exclude;
|
||||||
|
|
||||||
if (os->constraint == -1)
|
if (os->constraint < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
output_section = os->bfd_section;
|
output_section = os->bfd_section;
|
||||||
@ -5665,11 +5645,9 @@ lang_place_orphans (void)
|
|||||||
|| command_line.force_common_definition)
|
|| command_line.force_common_definition)
|
||||||
{
|
{
|
||||||
if (default_common_section == NULL)
|
if (default_common_section == NULL)
|
||||||
{
|
default_common_section
|
||||||
default_common_section =
|
= lang_output_section_statement_lookup (".bss", 0,
|
||||||
lang_output_section_statement_lookup (".bss");
|
TRUE);
|
||||||
|
|
||||||
}
|
|
||||||
lang_add_section (&default_common_section->children, s,
|
lang_add_section (&default_common_section->children, s,
|
||||||
default_common_section);
|
default_common_section);
|
||||||
}
|
}
|
||||||
@ -5680,7 +5658,7 @@ lang_place_orphans (void)
|
|||||||
{
|
{
|
||||||
lang_output_section_statement_type *os;
|
lang_output_section_statement_type *os;
|
||||||
|
|
||||||
os = lang_output_section_statement_lookup (s->name);
|
os = lang_output_section_statement_lookup (s->name, 0, TRUE);
|
||||||
lang_add_section (&os->children, s, os);
|
lang_add_section (&os->children, s, os);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5827,12 +5805,10 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
|
|||||||
{
|
{
|
||||||
lang_output_section_statement_type *os;
|
lang_output_section_statement_type *os;
|
||||||
|
|
||||||
os = lang_output_section_statement_lookup_1 (output_section_statement_name,
|
os = lang_output_section_statement_lookup (output_section_statement_name,
|
||||||
constraint);
|
constraint, TRUE);
|
||||||
current_section = os;
|
current_section = os;
|
||||||
|
|
||||||
/* Make next things chain into subchain of this. */
|
|
||||||
|
|
||||||
if (os->addr_tree == NULL)
|
if (os->addr_tree == NULL)
|
||||||
{
|
{
|
||||||
os->addr_tree = address_exp;
|
os->addr_tree = address_exp;
|
||||||
@ -5843,6 +5819,8 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
|
|||||||
else
|
else
|
||||||
os->flags = SEC_NEVER_LOAD;
|
os->flags = SEC_NEVER_LOAD;
|
||||||
os->block_value = 1;
|
os->block_value = 1;
|
||||||
|
|
||||||
|
/* Make next things chain into subchain of this. */
|
||||||
stat_ptr = &os->children;
|
stat_ptr = &os->children;
|
||||||
|
|
||||||
os->subsection_alignment =
|
os->subsection_alignment =
|
||||||
@ -6639,7 +6617,7 @@ lang_record_phdrs (void)
|
|||||||
{
|
{
|
||||||
lang_output_section_phdr_list *pl;
|
lang_output_section_phdr_list *pl;
|
||||||
|
|
||||||
if (os->constraint == -1)
|
if (os->constraint < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pl = os->phdrs;
|
pl = os->phdrs;
|
||||||
@ -6720,7 +6698,7 @@ lang_record_phdrs (void)
|
|||||||
{
|
{
|
||||||
lang_output_section_phdr_list *pl;
|
lang_output_section_phdr_list *pl;
|
||||||
|
|
||||||
if (os->constraint == -1
|
if (os->constraint < 0
|
||||||
|| os->bfd_section == NULL)
|
|| os->bfd_section == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
10
ld/ldlang.h
10
ld/ldlang.h
@ -525,12 +525,13 @@ extern void lang_do_assignments
|
|||||||
statement != (lang_input_statement_type *) NULL; \
|
statement != (lang_input_statement_type *) NULL; \
|
||||||
statement = (lang_input_statement_type *) statement->next) \
|
statement = (lang_input_statement_type *) statement->next) \
|
||||||
|
|
||||||
|
#define lang_output_section_find(NAME) \
|
||||||
|
lang_output_section_statement_lookup (NAME, 0, FALSE)
|
||||||
|
|
||||||
extern void lang_process
|
extern void lang_process
|
||||||
(void);
|
(void);
|
||||||
extern void ldlang_add_file
|
extern void ldlang_add_file
|
||||||
(lang_input_statement_type *);
|
(lang_input_statement_type *);
|
||||||
extern lang_output_section_statement_type *lang_output_section_find
|
|
||||||
(const char * const);
|
|
||||||
extern lang_output_section_statement_type *lang_output_section_find_by_flags
|
extern lang_output_section_statement_type *lang_output_section_find_by_flags
|
||||||
(const asection *, lang_output_section_statement_type **,
|
(const asection *, lang_output_section_statement_type **,
|
||||||
lang_match_sec_type_func);
|
lang_match_sec_type_func);
|
||||||
@ -541,9 +542,8 @@ extern lang_input_statement_type *lang_add_input_file
|
|||||||
(const char *, lang_input_file_enum_type, const char *);
|
(const char *, lang_input_file_enum_type, const char *);
|
||||||
extern void lang_add_keepsyms_file
|
extern void lang_add_keepsyms_file
|
||||||
(const char *);
|
(const char *);
|
||||||
extern lang_output_section_statement_type *
|
extern lang_output_section_statement_type *lang_output_section_statement_lookup
|
||||||
lang_output_section_statement_lookup
|
(const char *const, int, bfd_boolean);
|
||||||
(const char *const);
|
|
||||||
extern void ldlang_add_undef
|
extern void ldlang_add_undef
|
||||||
(const char *const);
|
(const char *const);
|
||||||
extern void lang_add_output_format
|
extern void lang_add_output_format
|
||||||
|
Loading…
Reference in New Issue
Block a user