static boolean gld${EMULATION_NAME}_open_dynamic_archive
PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *));
static lang_output_section_statement_type *output_rel_find
- PARAMS ((void));
+ PARAMS ((asection *));
static asection *output_prev_sec_find
PARAMS ((lang_output_section_statement_type *));
static boolean gld${EMULATION_NAME}_place_orphan
soname = bfd_elf_get_dt_soname (s->the_bfd);
if (soname == NULL)
- soname = basename (bfd_get_filename (s->the_bfd));
+ soname = lbasename (bfd_get_filename (s->the_bfd));
for (l = global_vercheck_needed; l != NULL; l = l->next)
{
soname = bfd_elf_get_dt_soname (s->the_bfd);
if (soname == NULL)
- soname = basename (s->filename);
+ soname = lbasename (s->filename);
if (strncmp (soname, global_needed->name, suffix - global_needed->name) == 0)
einfo ("%P: warning: %s, needed by %B, may conflict with %s\n",
return false;
}
+ /* For DT_NEEDED, they have to match. */
+ if (abfd->xvec != output_bfd->xvec)
+ {
+ bfd_close (abfd);
+ return false;
+ }
+
/* Check whether this object would include any conflicting library
versions. If FORCE is set, then we skip this check; we use this
the second time around, if we couldn't find any compatible
einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd);
/* First strip off everything before the last '/'. */
- soname = basename (abfd->filename);
+ soname = lbasename (abfd->filename);
if (trace_file_tries)
info_msg (_("found %s at %s\n"), soname, name);
DT_NEEDED entry for this file. */
bfd_elf_set_dt_needed_name (abfd, "");
- /* Previos basename call was clobbered in lang_for_each_input_file. */
- soname = basename (abfd->filename);
-
/* Tell the ELF backend that the output file needs a DT_NEEDED
entry for this file if it is used to resolve the reference in
a regular object. */
/* Rather than duplicating the logic above. Just use the
filename we recorded earlier. */
- filename = xstrdup (basename (entry->filename));
+ filename = lbasename (entry->filename);
bfd_elf_set_dt_needed_name (entry->the_bfd, filename);
}
/* A variant of lang_output_section_find. Used by place_orphan. */
static lang_output_section_statement_type *
-output_rel_find ()
+output_rel_find (sec)
+ asection *sec;
{
lang_statement_union_type *u;
lang_output_section_statement_type *lookup;
+ lang_output_section_statement_type *last = NULL;
+ lang_output_section_statement_type *last_rel = NULL;
+ lang_output_section_statement_type *last_rel_alloc = NULL;
+ int rela = sec->name[4] == 'a';
- for (u = lang_output_section_statement.head;
- u != (lang_statement_union_type *) NULL;
- u = lookup->next)
+ for (u = lang_output_section_statement.head; u; 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)
+ if (strncmp (".rel", lookup->name, 4) == 0)
{
- return lookup;
+ /* Don't place after .rel.plt as doing so results in wrong
+ dynamic tags. Also, place allocated reloc sections before
+ non-allocated. */
+ int lookrela = lookup->name[4] == 'a';
+
+ if (strcmp (".plt", lookup->name + 4 + lookrela) == 0
+ || (lookup->bfd_section != NULL
+ && (lookup->bfd_section->flags & SEC_ALLOC) == 0))
+ break;
+ last = lookup;
+ if (rela == lookrela)
+ last_rel = lookup;
+ if (lookup->bfd_section != NULL
+ && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
+ last_rel_alloc = lookup;
}
}
- return (lang_output_section_statement_type *) NULL;
+
+ if (last_rel_alloc)
+ return last_rel_alloc;
+
+ if (last_rel)
+ return last_rel;
+
+ return last;
}
/* Find the last output section before given output statement.
lang_statement_list_type add;
etree_type *address;
const char *secname;
- const char *outsecname;
const char *ps = NULL;
lang_output_section_statement_type *os;
+ int isdyn = 0;
secname = bfd_get_section_name (s->owner, s);
+ if (! link_info.relocateable
+ && link_info.combreloc
+ && strncmp (secname, ".rel", 4) == 0)
+ {
+ if (secname[4] == 'a')
+ secname = ".rela.dyn";
+ else
+ secname = ".rel.dyn";
+ isdyn = 1;
+ }
- if (! config.unique_orphan_sections && ! unique_section_p (secname))
+ if (isdyn || (!config.unique_orphan_sections && !unique_section_p (secname)))
{
/* Look through the script to see where to place this section. */
os = lang_output_section_find (secname);
#define HAVE_SECTION(hold, name) \
(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
- if (s->flags & SEC_EXCLUDE)
+ if ((s->flags & SEC_EXCLUDE) != 0 && !link_info.relocateable)
{
if (s->output_section == NULL)
s->output_section = bfd_abs_section_ptr;
&& HAVE_SECTION (hold_data, ".data"))
place = &hold_data;
else if (strncmp (secname, ".rel", 4) == 0
+ && (s->flags & SEC_LOAD) != 0
&& (hold_rel.os != NULL
- || (hold_rel.os = output_rel_find ()) != NULL))
- {
- if (! link_info.relocateable && link_info.combreloc)
- {
- if (strncmp (secname, ".rela", 5) == 0)
- os = lang_output_section_find (".rela.dyn");
- else
- os = lang_output_section_find (".rel.dyn");
-
- if (os != NULL
- && os->bfd_section != NULL
- && ((s->flags ^ os->bfd_section->flags)
- & (SEC_LOAD | SEC_ALLOC)) == 0)
- {
- lang_add_section (&os->children, s, os, file);
- return true;
- }
- }
- place = &hold_rel;
- }
+ || (hold_rel.os = output_rel_find (s)) != NULL))
+ place = &hold_rel;
else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
&& HAVE_SECTION (hold_rodata, ".rodata"))
place = &hold_rodata;
/* 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 allocatable characteristics. */
- outsecname = secname;
- if (bfd_get_section_by_name (output_bfd, outsecname) != NULL)
+ if (bfd_get_section_by_name (output_bfd, secname) != NULL)
{
- outsecname = bfd_get_unique_section_name (output_bfd,
- outsecname,
- &count);
- if (outsecname == NULL)
+ secname = bfd_get_unique_section_name (output_bfd, secname, &count);
+ if (secname == NULL)
einfo ("%F%P: place_orphan failed: %E\n");
}
{
/* If the name of the section is representable in C, then create
symbols to mark the start and the end of the section. */
- for (ps = outsecname; *ps != '\0'; ps++)
+ for (ps = secname; *ps != '\0'; ps++)
if (! ISALNUM (*ps) && *ps != '_')
break;
if (*ps == '\0')
char *symname;
etree_type *e_align;
- symname = (char *) xmalloc (ps - outsecname + sizeof "__start_");
- sprintf (symname, "__start_%s", outsecname);
+ symname = (char *) xmalloc (ps - secname + sizeof "__start_");
+ sprintf (symname, "__start_%s", secname);
e_align = exp_unop (ALIGN_K,
exp_intop ((bfd_vma) 1 << s->alignment_power));
lang_add_assignment (exp_assop ('=', symname, e_align));
else
address = NULL;
- os = lang_enter_output_section_statement (outsecname, address, 0,
+ os = lang_enter_output_section_statement (secname, address, 0,
(bfd_vma) 0,
(etree_type *) NULL,
(etree_type *) NULL,
lang_leave_output_section_statement
((bfd_vma) 0, "*default*",
- (struct lang_output_section_phdr_list *) NULL, "*default*");
+ (struct lang_output_section_phdr_list *) NULL, NULL);
if (config.build_constructors && *ps == '\0')
{
if (place != NULL)
stat_ptr = &add;
- symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
- sprintf (symname, "__stop_%s", outsecname);
+ symname = (char *) xmalloc (ps - secname + sizeof "__stop_");
+ sprintf (symname, "__stop_%s", secname);
lang_add_assignment (exp_assop ('=', symname,
exp_nameop (NAME, ".")));
}
/* Restore the global list pointer. */
stat_ptr = old;
- if (place != NULL)
+ if (place != NULL && os->bfd_section != NULL)
{
asection *snew, **pps;
/* Do the assignments again. */
lang_do_assignments (stat_ptr->head, abs_output_section,
- (fill_type) 0, (bfd_vma) 0);
+ (fill_type *) 0, (bfd_vma) 0);
}
}
EOF
sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c
fi
if test -n "$GENERATE_SHLIB_SCRIPT" ; then
+if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
echo ' ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xsc >> e${EMULATION_NAME}.c
+fi
echo ' ; else if (link_info.shared) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xs >> e${EMULATION_NAME}.c
fi
+if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
echo ' ; else if (link_info.combreloc) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xc >> e${EMULATION_NAME}.c
+fi
echo ' ; else return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c
echo '; }' >> e${EMULATION_NAME}.c
}
else if (strcmp (optarg, "defs") == 0)
link_info.no_undefined = true;
+ else if (strcmp (optarg, "muldefs") == 0)
+ link_info.allow_multiple_definition = true;
else if (strcmp (optarg, "combreloc") == 0)
link_info.combreloc = true;
else if (strcmp (optarg, "nocombreloc") == 0)
fprintf (file, _(" -z initfirst\t\tMark DSO to be initialized first at runtime\n"));
fprintf (file, _(" -z interpose\t\tMark object to interpose all DSOs but executable\n"));
fprintf (file, _(" -z loadfltr\t\tMark object requiring immediate process\n"));
+ fprintf (file, _(" -z muldefs\t\tAllow multiple definitions\n"));
fprintf (file, _(" -z nocombreloc\tDon't merge dynamic relocs into one section\n"));
fprintf (file, _(" -z nocopyreloc\tDon't create copy relocs\n"));
fprintf (file, _(" -z nodefaultlib\tMark object not to use default search paths\n"));
${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options},
${LDEMUL_RECOGNIZED_FILE-NULL},
${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
+ ${LDEMUL_NEW_VERS_PATTERN-NULL}
};
EOF