|
|
|
@ -61,8 +61,7 @@ static void gld${EMULATION_NAME}_find_statement_assignment |
|
|
|
static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *)); |
|
|
|
static boolean gld${EMULATION_NAME}_place_orphan |
|
|
|
PARAMS ((lang_input_statement_type *, asection *)); |
|
|
|
static void gld${EMULATION_NAME}_place_section |
|
|
|
PARAMS ((lang_statement_union_type *)); |
|
|
|
static lang_output_section_statement_type *output_rel_find PARAMS ((void)); |
|
|
|
static void gld${EMULATION_NAME}_before_parse PARAMS ((void)); |
|
|
|
static void gld${EMULATION_NAME}_before_allocation PARAMS ((void)); |
|
|
|
static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile)); |
|
|
|
@ -783,21 +782,12 @@ gld${EMULATION_NAME}_vercheck (s) |
|
|
|
/* Place an orphan section. We use this to put random SHF_ALLOC |
|
|
|
sections in the right segment. */ |
|
|
|
|
|
|
|
static asection *hold_section; |
|
|
|
static lang_output_section_statement_type *hold_use; |
|
|
|
|
|
|
|
struct orphan_save |
|
|
|
{ |
|
|
|
lang_output_section_statement_type *os; |
|
|
|
asection **section; |
|
|
|
lang_statement_union_type **stmt; |
|
|
|
}; |
|
|
|
static struct orphan_save hold_text; |
|
|
|
static struct orphan_save hold_rodata; |
|
|
|
static struct orphan_save hold_data; |
|
|
|
static struct orphan_save hold_bss; |
|
|
|
static struct orphan_save hold_rel; |
|
|
|
static struct orphan_save hold_interp; |
|
|
|
|
|
|
|
/*ARGSUSED*/ |
|
|
|
static boolean |
|
|
|
@ -805,6 +795,12 @@ gld${EMULATION_NAME}_place_orphan (file, s) |
|
|
|
lang_input_statement_type *file; |
|
|
|
asection *s; |
|
|
|
{ |
|
|
|
static struct orphan_save hold_text; |
|
|
|
static struct orphan_save hold_rodata; |
|
|
|
static struct orphan_save hold_data; |
|
|
|
static struct orphan_save hold_bss; |
|
|
|
static struct orphan_save hold_rel; |
|
|
|
static struct orphan_save hold_interp; |
|
|
|
struct orphan_save *place; |
|
|
|
lang_statement_list_type *old; |
|
|
|
lang_statement_list_type add; |
|
|
|
@ -813,19 +809,22 @@ gld${EMULATION_NAME}_place_orphan (file, s) |
|
|
|
const char *outsecname; |
|
|
|
lang_output_section_statement_type *os; |
|
|
|
|
|
|
|
secname = bfd_get_section_name (s->owner, s); |
|
|
|
|
|
|
|
/* Look through the script to see where to place this section. */ |
|
|
|
hold_section = s; |
|
|
|
hold_use = NULL; |
|
|
|
lang_for_each_statement (gld${EMULATION_NAME}_place_section); |
|
|
|
os = lang_output_section_find (secname); |
|
|
|
|
|
|
|
if (hold_use != NULL) |
|
|
|
if (os != NULL |
|
|
|
&& os->bfd_section != NULL |
|
|
|
&& ((s->flags ^ os->bfd_section->flags) & (SEC_LOAD | SEC_ALLOC)) == 0) |
|
|
|
{ |
|
|
|
/* We have already placed a section with this name. */ |
|
|
|
wild_doit (&hold_use->children, s, hold_use, file); |
|
|
|
wild_doit (&os->children, s, os, file); |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
secname = bfd_get_section_name (s->owner, s); |
|
|
|
if (hold_text.os == NULL) |
|
|
|
hold_text.os = lang_output_section_find (".text"); |
|
|
|
|
|
|
|
/* If this is a final link, then always put .gnu.warning.SYMBOL |
|
|
|
sections into the .text section to get them out of the way. */ |
|
|
|
@ -843,26 +842,30 @@ gld${EMULATION_NAME}_place_orphan (file, s) |
|
|
|
right after the .interp section, so that the PT_NOTE segment is |
|
|
|
stored right after the program headers where the OS can read it |
|
|
|
in the first page. */ |
|
|
|
#define HAVE_SECTION(hold, name) \ |
|
|
|
(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL) |
|
|
|
|
|
|
|
if (s->flags & SEC_EXCLUDE) |
|
|
|
return false; |
|
|
|
else if ((s->flags & SEC_ALLOC) == 0) |
|
|
|
place = NULL; |
|
|
|
else if ((s->flags & SEC_LOAD) != 0 |
|
|
|
&& strncmp (secname, ".note", 4) == 0 |
|
|
|
&& hold_interp.os != NULL) |
|
|
|
&& HAVE_SECTION (hold_interp, ".interp")) |
|
|
|
place = &hold_interp; |
|
|
|
else if ((s->flags & SEC_HAS_CONTENTS) == 0 |
|
|
|
&& hold_bss.os != NULL) |
|
|
|
&& HAVE_SECTION (hold_bss, ".bss")) |
|
|
|
place = &hold_bss; |
|
|
|
else if ((s->flags & SEC_READONLY) == 0 |
|
|
|
&& hold_data.os != NULL) |
|
|
|
&& HAVE_SECTION (hold_data, ".data")) |
|
|
|
place = &hold_data; |
|
|
|
else if (strncmp (secname, ".rel", 4) == 0 |
|
|
|
&& hold_rel.os != NULL) |
|
|
|
&& (hold_rel.os != NULL |
|
|
|
|| (hold_rel.os = output_rel_find ()) != NULL)) |
|
|
|
place = &hold_rel; |
|
|
|
else if ((s->flags & SEC_CODE) == 0 |
|
|
|
&& (s->flags & SEC_READONLY) != 0 |
|
|
|
&& hold_rodata.os != NULL) |
|
|
|
&& HAVE_SECTION (hold_rodata, ".rodata")) |
|
|
|
place = &hold_rodata; |
|
|
|
else if ((s->flags & SEC_READONLY) != 0 |
|
|
|
&& hold_text.os != NULL) |
|
|
|
@ -870,6 +873,8 @@ gld${EMULATION_NAME}_place_orphan (file, s) |
|
|
|
else |
|
|
|
place = NULL; |
|
|
|
|
|
|
|
#undef HAVE_SECTION |
|
|
|
|
|
|
|
/* Choose a unique name for the section. This will be needed if the |
|
|
|
same section name appears in the input file with different |
|
|
|
loadable or allocateable characteristics. */ |
|
|
|
@ -924,13 +929,12 @@ gld${EMULATION_NAME}_place_orphan (file, s) |
|
|
|
else |
|
|
|
address = NULL; |
|
|
|
|
|
|
|
lang_enter_output_section_statement (outsecname, address, 0, |
|
|
|
(bfd_vma) 0, |
|
|
|
(etree_type *) NULL, |
|
|
|
(etree_type *) NULL, |
|
|
|
(etree_type *) NULL); |
|
|
|
os = lang_enter_output_section_statement (outsecname, address, 0, |
|
|
|
(bfd_vma) 0, |
|
|
|
(etree_type *) NULL, |
|
|
|
(etree_type *) NULL, |
|
|
|
(etree_type *) NULL); |
|
|
|
|
|
|
|
os = lang_output_section_statement_lookup (outsecname); |
|
|
|
wild_doit (&os->children, s, os, file); |
|
|
|
|
|
|
|
lang_leave_output_section_statement |
|
|
|
@ -1004,38 +1008,26 @@ gld${EMULATION_NAME}_place_orphan (file, s) |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
gld${EMULATION_NAME}_place_section (s) |
|
|
|
lang_statement_union_type *s; |
|
|
|
/* A variant of lang_output_section_find. */ |
|
|
|
static lang_output_section_statement_type * |
|
|
|
output_rel_find () |
|
|
|
{ |
|
|
|
lang_output_section_statement_type *os; |
|
|
|
|
|
|
|
if (s->header.type != lang_output_section_statement_enum) |
|
|
|
return; |
|
|
|
lang_statement_union_type *u; |
|
|
|
lang_output_section_statement_type *lookup; |
|
|
|
|
|
|
|
os = &s->output_section_statement; |
|
|
|
|
|
|
|
if (strcmp (os->name, hold_section->name) == 0 |
|
|
|
&& os->bfd_section != NULL |
|
|
|
&& ((hold_section->flags & (SEC_LOAD | SEC_ALLOC)) |
|
|
|
== (os->bfd_section->flags & (SEC_LOAD | SEC_ALLOC)))) |
|
|
|
hold_use = os; |
|
|
|
|
|
|
|
if (strcmp (os->name, ".text") == 0) |
|
|
|
hold_text.os = os; |
|
|
|
else if (strcmp (os->name, ".rodata") == 0) |
|
|
|
hold_rodata.os = os; |
|
|
|
else if (strcmp (os->name, ".data") == 0) |
|
|
|
hold_data.os = os; |
|
|
|
else if (strcmp (os->name, ".bss") == 0) |
|
|
|
hold_bss.os = os; |
|
|
|
else if (hold_rel.os == NULL |
|
|
|
&& os->bfd_section != NULL |
|
|
|
&& (os->bfd_section->flags & SEC_ALLOC) != 0 |
|
|
|
&& strncmp (os->name, ".rel", 4) == 0) |
|
|
|
hold_rel.os = os; |
|
|
|
else if (strcmp (os->name, ".interp") == 0) |
|
|
|
hold_interp.os = os; |
|
|
|
for (u = lang_output_section_statement.head; |
|
|
|
u != (lang_statement_union_type *) NULL; |
|
|
|
u = lookup->next) |
|
|
|
{ |
|
|
|
lookup = &u->output_section_statement; |
|
|
|
if (strncmp (".rel", lookup->name, 4) == 0 |
|
|
|
&& lookup->bfd_section != NULL |
|
|
|
&& (lookup->bfd_section->flags & SEC_ALLOC) != 0) |
|
|
|
{ |
|
|
|
return lookup; |
|
|
|
} |
|
|
|
} |
|
|
|
return (lang_output_section_statement_type *) NULL; |
|
|
|
} |
|
|
|
|
|
|
|
/* Look through an expression for an assignment statement. */ |
|
|
|
|