* ld.h (ld_config_type): New flag member separate_code.
	* emultempl/elf32.em
	(gld${EMULATION_NAME}_before_parse): Set it based on $SEPARATE_CODE.
	* ldlang.c (ldlang_override_segment_assignment): If it's set, then
	always return TRUE when SEC_CODE differs between the sections.
This commit is contained in:
Roland McGrath 2012-11-21 19:56:38 +00:00
parent e0799d78b1
commit 4724d37ec2
4 changed files with 58 additions and 40 deletions

@ -1,3 +1,11 @@
2012-11-21 Roland McGrath <mcgrathr@google.com>
* ld.h (ld_config_type): New flag member separate_code.
* emultempl/elf32.em
(gld${EMULATION_NAME}_before_parse): Set it based on $SEPARATE_CODE.
* ldlang.c (ldlang_override_segment_assignment): If it's set, then
always return TRUE when SEC_CODE differs between the sections.
2012-11-20 H.J. Lu <hongjiu.lu@intel.com> 2012-11-20 H.J. Lu <hongjiu.lu@intel.com>
* ld.texinfo: Document "-z global". * ld.texinfo: Document "-z global".

@ -104,6 +104,7 @@ gld${EMULATION_NAME}_before_parse (void)
ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`); ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
input_flags.dynamic = ${DYNAMIC_LINK-TRUE}; input_flags.dynamic = ${DYNAMIC_LINK-TRUE};
config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`; config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;
} }
EOF EOF
@ -140,7 +141,7 @@ gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *entry)
return FALSE; return FALSE;
bfd_elf_set_dyn_lib_class (entry->the_bfd, bfd_elf_set_dyn_lib_class (entry->the_bfd,
(enum dynamic_lib_link_class) link_class); (enum dynamic_lib_link_class) link_class);
/* Continue on with normal load_symbols processing. */ /* Continue on with normal load_symbols processing. */
return FALSE; return FALSE;
@ -1104,7 +1105,7 @@ gld${EMULATION_NAME}_after_open (void)
{ {
struct elf_obj_tdata *t = elf_tdata (link_info.output_bfd); struct elf_obj_tdata *t = elf_tdata (link_info.output_bfd);
struct build_id_info *b = struct build_id_info *b =
(struct build_id_info *) xmalloc (sizeof *b); (struct build_id_info *) xmalloc (sizeof *b);
b->style = link_info.emit_note_gnu_build_id; b->style = link_info.emit_note_gnu_build_id;
b->sec = s; b->sec = s;
@ -1439,7 +1440,7 @@ if test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation;
fragment <<EOF fragment <<EOF
/* used by before_allocation and handle_option. */ /* used by before_allocation and handle_option. */
static void static void
gld${EMULATION_NAME}_append_to_separated_string (char **to, char *op_arg) gld${EMULATION_NAME}_append_to_separated_string (char **to, char *op_arg)
{ {
if (*to == NULL) if (*to == NULL)
@ -1507,7 +1508,7 @@ gld${EMULATION_NAME}_before_allocation (void)
{ {
const char *audit_libs = elf_dt_audit (abfd); const char *audit_libs = elf_dt_audit (abfd);
/* If the input bfd contains an audit entry, we need to add it as /* If the input bfd contains an audit entry, we need to add it as
a dep audit entry. */ a dep audit entry. */
if (audit_libs && *audit_libs != '\0') if (audit_libs && *audit_libs != '\0')
{ {
@ -2204,7 +2205,7 @@ EOF
if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
fragment <<EOF fragment <<EOF
case OPTION_AUDIT: case OPTION_AUDIT:
gld${EMULATION_NAME}_append_to_separated_string (&audit, optarg); gld${EMULATION_NAME}_append_to_separated_string (&audit, optarg);
break; break;
case 'P': case 'P':
@ -2393,7 +2394,7 @@ if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
fragment <<EOF fragment <<EOF
fprintf (file, _("\ fprintf (file, _("\
-P AUDITLIB, --depaudit=AUDITLIB\n" "\ -P AUDITLIB, --depaudit=AUDITLIB\n" "\
Specify a library to use for auditing dependencies\n")); Specify a library to use for auditing dependencies\n"));
fprintf (file, _("\ fprintf (file, _("\
--disable-new-dtags Disable new dynamic tags\n")); --disable-new-dtags Disable new dynamic tags\n"));
fprintf (file, _("\ fprintf (file, _("\
@ -2422,7 +2423,7 @@ if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
fragment <<EOF fragment <<EOF
fprintf (file, _("\ fprintf (file, _("\
-z global Make symbols in DSO available for subsequently\n\ -z global Make symbols in DSO available for subsequently\n\
loaded objects\n")); loaded objects\n"));
fprintf (file, _("\ fprintf (file, _("\
-z initfirst Mark DSO to be initialized first at runtime\n")); -z initfirst Mark DSO to be initialized first at runtime\n"));
fprintf (file, _("\ fprintf (file, _("\
@ -2469,7 +2470,7 @@ fragment <<EOF
-z now Mark object non-lazy runtime binding\n")); -z now Mark object non-lazy runtime binding\n"));
fprintf (file, _("\ fprintf (file, _("\
-z origin Mark object requiring immediate \$ORIGIN\n\ -z origin Mark object requiring immediate \$ORIGIN\n\
processing at runtime\n")); processing at runtime\n"));
fprintf (file, _("\ fprintf (file, _("\
-z relro Create RELRO program header\n")); -z relro Create RELRO program header\n"));
fprintf (file, _("\ fprintf (file, _("\

@ -82,7 +82,7 @@ typedef struct name_list {
name_list; name_list;
typedef enum {sort_none, sort_ascending, sort_descending} sort_order; typedef enum {sort_none, sort_ascending, sort_descending} sort_order;
/* A wildcard specification. */ /* A wildcard specification. */
typedef enum { typedef enum {
@ -274,6 +274,9 @@ typedef struct {
numbers everywhere. */ numbers everywhere. */
bfd_boolean sane_expr; bfd_boolean sane_expr;
/* If set, code and non-code sections should never be in one segment. */
bfd_boolean separate_code;
/* The rpath separation character. Usually ':'. */ /* The rpath separation character. Usually ':'. */
char rpath_separator; char rpath_separator;

@ -878,8 +878,8 @@ walk_wild_file (lang_wild_statement_type *s,
if (member->usrdata != NULL) if (member->usrdata != NULL)
{ {
walk_wild_section (s, walk_wild_section (s,
(lang_input_statement_type *) member->usrdata, (lang_input_statement_type *) member->usrdata,
callback, data); callback, data);
} }
member = bfd_openr_next_archived_file (f->the_bfd, member); member = bfd_openr_next_archived_file (f->the_bfd, member);
@ -1050,7 +1050,7 @@ new_afile (const char *name,
else else
{ {
p = (lang_input_statement_type *) p = (lang_input_statement_type *)
stat_alloc (sizeof (lang_input_statement_type)); stat_alloc (sizeof (lang_input_statement_type));
p->header.type = lang_input_statement_enum; p->header.type = lang_input_statement_enum;
p->header.next = NULL; p->header.next = NULL;
} }
@ -1148,7 +1148,7 @@ output_section_statement_newfunc (struct bfd_hash_entry *entry,
if (entry == NULL) if (entry == NULL)
{ {
entry = (struct bfd_hash_entry *) bfd_hash_allocate (table, entry = (struct bfd_hash_entry *) bfd_hash_allocate (table,
sizeof (*ret)); sizeof (*ret));
if (entry == NULL) if (entry == NULL)
return entry; return entry;
} }
@ -1283,12 +1283,12 @@ lang_memory_region_lookup (const char *const name, bfd_boolean create)
for (r = lang_memory_region_list; r != NULL; r = r->next) for (r = lang_memory_region_list; r != NULL; r = r->next)
for (n = &r->name_list; n != NULL; n = n->next) for (n = &r->name_list; n != NULL; n = n->next)
if (strcmp (n->name, name) == 0) if (strcmp (n->name, name) == 0)
{ {
if (create) if (create)
einfo (_("%P:%S: warning: redeclaration of memory region `%s'\n"), einfo (_("%P:%S: warning: redeclaration of memory region `%s'\n"),
NULL, name); NULL, name);
return r; return r;
} }
if (!create && strcmp (name, DEFAULT_MEMORY_REGION)) if (!create && strcmp (name, DEFAULT_MEMORY_REGION))
einfo (_("%P:%S: warning: memory region `%s' not declared\n"), einfo (_("%P:%S: warning: memory region `%s' not declared\n"),
@ -1334,19 +1334,19 @@ lang_memory_region_alias (const char * alias, const char * region_name)
for (r = lang_memory_region_list; r != NULL; r = r->next) for (r = lang_memory_region_list; r != NULL; r = r->next)
for (n = &r->name_list; n != NULL; n = n->next) for (n = &r->name_list; n != NULL; n = n->next)
{ {
if (region == NULL && strcmp (n->name, region_name) == 0) if (region == NULL && strcmp (n->name, region_name) == 0)
region = r; region = r;
if (strcmp (n->name, alias) == 0) if (strcmp (n->name, alias) == 0)
einfo (_("%F%P:%S: error: redefinition of memory region " einfo (_("%F%P:%S: error: redefinition of memory region "
"alias `%s'\n"), "alias `%s'\n"),
NULL, alias); NULL, alias);
} }
/* Check if the target region exists. */ /* Check if the target region exists. */
if (region == NULL) if (region == NULL)
einfo (_("%F%P:%S: error: memory region `%s' " einfo (_("%F%P:%S: error: memory region `%s' "
"for alias `%s' does not exist\n"), "for alias `%s' does not exist\n"),
NULL, region_name, alias); NULL, region_name, alias);
/* Add alias to region name list. */ /* Add alias to region name list. */
n = (lang_memory_region_name *) stat_alloc (sizeof (lang_memory_region_name)); n = (lang_memory_region_name *) stat_alloc (sizeof (lang_memory_region_name));
@ -1777,7 +1777,7 @@ lang_insert_orphan (asection *s,
os_tail = ((lang_output_section_statement_type **) os_tail = ((lang_output_section_statement_type **)
lang_output_section_statement.tail); lang_output_section_statement.tail);
os = lang_enter_output_section_statement (secname, address, normal_section, os = lang_enter_output_section_statement (secname, address, normal_section,
NULL, NULL, NULL, constraint); NULL, NULL, NULL, constraint);
ps = NULL; ps = NULL;
if (config.build_constructors && *os_tail == os) if (config.build_constructors && *os_tail == os)
@ -2080,14 +2080,14 @@ sort_def_symbol (struct bfd_link_hash_entry *hash_entry,
struct map_symbol_def *def; struct map_symbol_def *def;
ud = (struct fat_user_section_struct *) ud = (struct fat_user_section_struct *)
get_userdata (hash_entry->u.def.section); get_userdata (hash_entry->u.def.section);
if (! ud) if (! ud)
{ {
/* ??? What do we have to do to initialize this beforehand? */ /* ??? What do we have to do to initialize this beforehand? */
/* The first time we get here is bfd_abs_section... */ /* The first time we get here is bfd_abs_section... */
init_map_userdata (0, hash_entry->u.def.section, 0); init_map_userdata (0, hash_entry->u.def.section, 0);
ud = (struct fat_user_section_struct *) ud = (struct fat_user_section_struct *)
get_userdata (hash_entry->u.def.section); get_userdata (hash_entry->u.def.section);
} }
else if (!ud->map_symbol_def_tail) else if (!ud->map_symbol_def_tail)
ud->map_symbol_def_tail = &ud->map_symbol_def_head; ud->map_symbol_def_tail = &ud->map_symbol_def_head;
@ -2125,7 +2125,7 @@ init_os (lang_output_section_statement_type *s, flagword flags)
if (!link_info.reduce_memory_overheads) if (!link_info.reduce_memory_overheads)
{ {
fat_section_userdata_type *new_userdata = (fat_section_userdata_type *) fat_section_userdata_type *new_userdata = (fat_section_userdata_type *)
stat_alloc (sizeof (fat_section_userdata_type)); stat_alloc (sizeof (fat_section_userdata_type));
memset (new_userdata, 0, sizeof (fat_section_userdata_type)); memset (new_userdata, 0, sizeof (fat_section_userdata_type));
get_userdata (s->bfd_section) = new_userdata; get_userdata (s->bfd_section) = new_userdata;
} }
@ -2264,7 +2264,7 @@ lang_add_section (lang_statement_list_type *ptr,
keep = bfd_lookup_section_flags (&link_info, sflag_info, section); keep = bfd_lookup_section_flags (&link_info, sflag_info, section);
if (!keep) if (!keep)
return; return;
} }
if (section->output_section != NULL) if (section->output_section != NULL)
@ -4151,7 +4151,7 @@ print_all_symbols (asection *sec)
entries[i] = def->entry; entries[i] = def->entry;
qsort (entries, ud->map_symbol_def_count, sizeof (*entries), qsort (entries, ud->map_symbol_def_count, sizeof (*entries),
hash_entry_addr_cmp); hash_entry_addr_cmp);
/* Print the symbols. */ /* Print the symbols. */
for (i = 0; i < ud->map_symbol_def_count; i++) for (i = 0; i < ud->map_symbol_def_count; i++)
@ -4583,7 +4583,7 @@ insert_pad (lang_statement_union_type **ptr,
{ {
/* Make a new padding statement, linked into existing chain. */ /* Make a new padding statement, linked into existing chain. */
pad = (lang_statement_union_type *) pad = (lang_statement_union_type *)
stat_alloc (sizeof (lang_padding_statement_type)); stat_alloc (sizeof (lang_padding_statement_type));
pad->header.next = *ptr; pad->header.next = *ptr;
*ptr = pad; *ptr = pad;
pad->header.type = lang_padding_statement_enum; pad->header.type = lang_padding_statement_enum;
@ -5361,6 +5361,12 @@ ldlang_override_segment_assignment (struct bfd_link_info * info ATTRIBUTE_UNUSED
if (current_section == NULL || previous_section == NULL) if (current_section == NULL || previous_section == NULL)
return new_segment; return new_segment;
/* If this flag is set, the target never wants code and non-code
sections comingled in the same segment. */
if (config.separate_code
&& ((current_section->flags ^ previous_section->flags) & SEC_CODE))
return TRUE;
/* Find the memory regions associated with the two sections. /* Find the memory regions associated with the two sections.
We call lang_output_section_find() here rather than scanning the list We call lang_output_section_find() here rather than scanning the list
of output sections looking for a matching section pointer because if of output sections looking for a matching section pointer because if
@ -7237,7 +7243,7 @@ lang_record_phdrs (void)
{ {
alc *= 2; alc *= 2;
secs = (asection **) xrealloc (secs, secs = (asection **) xrealloc (secs,
alc * sizeof (asection *)); alc * sizeof (asection *));
} }
secs[c] = os->bfd_section; secs[c] = os->bfd_section;
++c; ++c;
@ -7539,7 +7545,7 @@ lang_vers_match (struct bfd_elf_version_expr_head *head,
{ {
e.pattern = c_sym; e.pattern = c_sym;
expr = (struct bfd_elf_version_expr *) expr = (struct bfd_elf_version_expr *)
htab_find ((htab_t) head->htab, &e); htab_find ((htab_t) head->htab, &e);
while (expr && strcmp (expr->pattern, c_sym) == 0) while (expr && strcmp (expr->pattern, c_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_C_TYPE) if (expr->mask == BFD_ELF_VERSION_C_TYPE)
goto out_ret; goto out_ret;
@ -7552,7 +7558,7 @@ lang_vers_match (struct bfd_elf_version_expr_head *head,
{ {
e.pattern = cxx_sym; e.pattern = cxx_sym;
expr = (struct bfd_elf_version_expr *) expr = (struct bfd_elf_version_expr *)
htab_find ((htab_t) head->htab, &e); htab_find ((htab_t) head->htab, &e);
while (expr && strcmp (expr->pattern, cxx_sym) == 0) while (expr && strcmp (expr->pattern, cxx_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_CXX_TYPE) if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
goto out_ret; goto out_ret;
@ -7565,7 +7571,7 @@ lang_vers_match (struct bfd_elf_version_expr_head *head,
{ {
e.pattern = java_sym; e.pattern = java_sym;
expr = (struct bfd_elf_version_expr *) expr = (struct bfd_elf_version_expr *)
htab_find ((htab_t) head->htab, &e); htab_find ((htab_t) head->htab, &e);
while (expr && strcmp (expr->pattern, java_sym) == 0) while (expr && strcmp (expr->pattern, java_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE) if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
goto out_ret; goto out_ret;
@ -7862,7 +7868,7 @@ lang_register_vers_node (const char *name,
if (t->locals.htab && e1->literal) if (t->locals.htab && e1->literal)
{ {
e2 = (struct bfd_elf_version_expr *) e2 = (struct bfd_elf_version_expr *)
htab_find ((htab_t) t->locals.htab, e1); htab_find ((htab_t) t->locals.htab, e1);
while (e2 && strcmp (e1->pattern, e2->pattern) == 0) while (e2 && strcmp (e1->pattern, e2->pattern) == 0)
{ {
if (e1->mask == e2->mask) if (e1->mask == e2->mask)
@ -7889,7 +7895,7 @@ lang_register_vers_node (const char *name,
if (t->globals.htab && e1->literal) if (t->globals.htab && e1->literal)
{ {
e2 = (struct bfd_elf_version_expr *) e2 = (struct bfd_elf_version_expr *)
htab_find ((htab_t) t->globals.htab, e1); htab_find ((htab_t) t->globals.htab, e1);
while (e2 && strcmp (e1->pattern, e2->pattern) == 0) while (e2 && strcmp (e1->pattern, e2->pattern) == 0)
{ {
if (e1->mask == e2->mask) if (e1->mask == e2->mask)