* emultempl/ppc64elf.em (move_input_section, sort_toc_sections): New.
(ppc_before_allocation): Call sort_toc_sections. (no_toc_sort, OPTION_NO_TOC_SORT): New. (PARSE_AND_LIST_PROLOGUE, PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS): Handle --no-toc-sort.
This commit is contained in:
parent
1bbe090216
commit
d43d0b53f6
@ -1,3 +1,11 @@
|
||||
2010-03-15 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* emultempl/ppc64elf.em (move_input_section, sort_toc_sections): New.
|
||||
(ppc_before_allocation): Call sort_toc_sections.
|
||||
(no_toc_sort, OPTION_NO_TOC_SORT): New.
|
||||
(PARSE_AND_LIST_PROLOGUE, PARSE_AND_LIST_LONGOPTS,
|
||||
PARSE_AND_LIST_OPTIONS): Handle --no-toc-sort.
|
||||
|
||||
2010-03-14 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR ld/11378
|
||||
|
@ -58,6 +58,9 @@ static int no_toc_opt = 0;
|
||||
/* Whether to allow multiple toc sections. */
|
||||
static int no_multi_toc = 0;
|
||||
|
||||
/* Whether to sort input toc and got sections. */
|
||||
static int no_toc_sort = 0;
|
||||
|
||||
/* Whether to emit symbols for stubs. */
|
||||
static int emit_stub_syms = -1;
|
||||
|
||||
@ -97,6 +100,132 @@ ppc_create_output_section_statements (void)
|
||||
ppc64_elf_init_stub_bfd (stub_file->the_bfd, &link_info);
|
||||
}
|
||||
|
||||
/* Move the input section statement at *U which happens to be on LIST
|
||||
to be just before *TO. */
|
||||
|
||||
static void
|
||||
move_input_section (lang_statement_list_type *list,
|
||||
lang_statement_union_type **u,
|
||||
lang_statement_union_type **to)
|
||||
{
|
||||
lang_statement_union_type *s = *u;
|
||||
asection *i = s->input_section.section;
|
||||
asection *p, *n;
|
||||
|
||||
/* Snip the input section from the statement list. If it was the
|
||||
last statement, fix the list tail pointer. */
|
||||
*u = s->header.next;
|
||||
if (*u == NULL)
|
||||
list->tail = u;
|
||||
/* Add it back in the new position. */
|
||||
s->header.next = *to;
|
||||
*to = s;
|
||||
if (list->tail == to)
|
||||
list->tail = &s->header.next;
|
||||
|
||||
/* Trim I off the bfd map_head/map_tail doubly linked lists. */
|
||||
n = i->map_head.s;
|
||||
p = i->map_tail.s;
|
||||
(p != NULL ? p : i->output_section)->map_head.s = n;
|
||||
(n != NULL ? n : i->output_section)->map_tail.s = p;
|
||||
|
||||
/* Add I back on in its new position. */
|
||||
if (s->header.next->header.type == lang_input_section_enum)
|
||||
{
|
||||
n = s->header.next->input_section.section;
|
||||
p = n->map_tail.s;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the next statement is not an input section statement then
|
||||
TO must point at the previous input section statement
|
||||
header.next field. */
|
||||
lang_input_section_type *prev = (lang_input_section_type *)
|
||||
((char *) to - offsetof (lang_statement_union_type, header.next));
|
||||
|
||||
ASSERT (prev->header.type == lang_input_section_enum);
|
||||
p = prev->section;
|
||||
n = p->map_head.s;
|
||||
}
|
||||
i->map_head.s = n;
|
||||
i->map_tail.s = p;
|
||||
(p != NULL ? p : i->output_section)->map_head.s = i;
|
||||
(n != NULL ? n : i->output_section)->map_tail.s = i;
|
||||
}
|
||||
|
||||
/* Sort input section statements in the linker script tree rooted at
|
||||
LIST so that those whose owning bfd happens to have a section
|
||||
called .init or .fini are placed first. Place any TOC sections
|
||||
referenced by small TOC relocs next, with TOC sections referenced
|
||||
only by bigtoc relocs last. */
|
||||
|
||||
static void
|
||||
sort_toc_sections (lang_statement_list_type *list,
|
||||
lang_statement_union_type **ini,
|
||||
lang_statement_union_type **small)
|
||||
{
|
||||
lang_statement_union_type *s, **u;
|
||||
asection *i;
|
||||
|
||||
u = &list->head;
|
||||
while ((s = *u) != NULL)
|
||||
{
|
||||
switch (s->header.type)
|
||||
{
|
||||
case lang_wild_statement_enum:
|
||||
sort_toc_sections (&s->wild_statement.children, ini, small);
|
||||
break;
|
||||
|
||||
case lang_group_statement_enum:
|
||||
sort_toc_sections (&s->group_statement.children, ini, small);
|
||||
break;
|
||||
|
||||
case lang_input_section_enum:
|
||||
i = s->input_section.section;
|
||||
/* Leave the stub_file .got where it is. We put the .got
|
||||
header there. */
|
||||
if (i->owner == stub_file->the_bfd)
|
||||
break;
|
||||
if (bfd_get_section_by_name (i->owner, ".init") != NULL
|
||||
|| bfd_get_section_by_name (i->owner, ".fini") != NULL)
|
||||
{
|
||||
if (ini != NULL && *ini != s)
|
||||
{
|
||||
move_input_section (list, u, ini);
|
||||
if (small == ini)
|
||||
small = &s->header.next;
|
||||
ini = &s->header.next;
|
||||
continue;
|
||||
}
|
||||
if (small == ini)
|
||||
small = &s->header.next;
|
||||
ini = &s->header.next;
|
||||
break;
|
||||
}
|
||||
else if (ini == NULL)
|
||||
ini = u;
|
||||
|
||||
if (ppc64_elf_has_small_toc_reloc (i))
|
||||
{
|
||||
if (small != NULL && *small != s)
|
||||
{
|
||||
move_input_section (list, u, small);
|
||||
small = &s->header.next;
|
||||
continue;
|
||||
}
|
||||
small = &s->header.next;
|
||||
}
|
||||
else if (small == NULL)
|
||||
small = u;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
u = &s->header.next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ppc_before_allocation (void)
|
||||
{
|
||||
@ -126,6 +255,15 @@ ppc_before_allocation (void)
|
||||
&& !link_info.relocatable
|
||||
&& !ppc64_elf_edit_toc (&link_info))
|
||||
einfo ("%X%P: can not edit %s %E\n", "toc");
|
||||
|
||||
if (!no_toc_sort)
|
||||
{
|
||||
lang_output_section_statement_type *toc_os;
|
||||
|
||||
toc_os = lang_output_section_find (".got");
|
||||
if (toc_os != NULL)
|
||||
sort_toc_sections (&toc_os->children, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
gld${EMULATION_NAME}_before_allocation ();
|
||||
@ -507,7 +645,8 @@ PARSE_AND_LIST_PROLOGUE='
|
||||
#define OPTION_NO_OPD_OPT (OPTION_NO_TLS_GET_ADDR_OPT + 1)
|
||||
#define OPTION_NO_TOC_OPT (OPTION_NO_OPD_OPT + 1)
|
||||
#define OPTION_NO_MULTI_TOC (OPTION_NO_TOC_OPT + 1)
|
||||
#define OPTION_NON_OVERLAPPING_OPD (OPTION_NO_MULTI_TOC + 1)
|
||||
#define OPTION_NO_TOC_SORT (OPTION_NO_MULTI_TOC + 1)
|
||||
#define OPTION_NON_OVERLAPPING_OPD (OPTION_NO_TOC_SORT + 1)
|
||||
'
|
||||
|
||||
PARSE_AND_LIST_LONGOPTS='
|
||||
@ -521,6 +660,7 @@ PARSE_AND_LIST_LONGOPTS='
|
||||
{ "no-opd-optimize", no_argument, NULL, OPTION_NO_OPD_OPT },
|
||||
{ "no-toc-optimize", no_argument, NULL, OPTION_NO_TOC_OPT },
|
||||
{ "no-multi-toc", no_argument, NULL, OPTION_NO_MULTI_TOC },
|
||||
{ "no-toc-sort", no_argument, NULL, OPTION_NO_TOC_SORT },
|
||||
{ "non-overlapping-opd", no_argument, NULL, OPTION_NON_OVERLAPPING_OPD },
|
||||
'
|
||||
|
||||
@ -566,6 +706,9 @@ PARSE_AND_LIST_OPTIONS='
|
||||
--no-multi-toc Disallow automatic multiple toc sections.\n"
|
||||
));
|
||||
fprintf (file, _("\
|
||||
--no-toc-sort Don'\''t sort TOC and GOT sections.\n"
|
||||
));
|
||||
fprintf (file, _("\
|
||||
--non-overlapping-opd Canonicalize .opd, so that there are no\n\
|
||||
overlapping .opd entries.\n"
|
||||
));
|
||||
@ -617,6 +760,10 @@ PARSE_AND_LIST_ARGS_CASES='
|
||||
no_multi_toc = 1;
|
||||
break;
|
||||
|
||||
case OPTION_NO_TOC_SORT:
|
||||
no_toc_sort = 1;
|
||||
break;
|
||||
|
||||
case OPTION_NON_OVERLAPPING_OPD:
|
||||
non_overlapping_opd = 1;
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user