* emultempl/elf32.em (global_needed): New static variable.
(global_found): Likewise. (gld${EMULATION_NAME}_after_open): New static function. (gld${EMULATION_NAME}_search_needed): Likewise. (gld${EMULATION_NAME}_try_needed): Likewise. (gld${EMULATION_NAME}_check_needed): Likewise. (ld_${EMULATION_NAME}_emulation): Replace after_open_default with gld${EMULATION_NAME}_after_open. PR 7083.
This commit is contained in:
parent
b176e1e92a
commit
7523be3552
11
ld/ChangeLog
11
ld/ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
Tue Jul 4 12:55:48 1995 Ian Lance Taylor <ian@cygnus.com>
|
||||||
|
|
||||||
|
* emultempl/elf32.em (global_needed): New static variable.
|
||||||
|
(global_found): Likewise.
|
||||||
|
(gld${EMULATION_NAME}_after_open): New static function.
|
||||||
|
(gld${EMULATION_NAME}_search_needed): Likewise.
|
||||||
|
(gld${EMULATION_NAME}_try_needed): Likewise.
|
||||||
|
(gld${EMULATION_NAME}_check_needed): Likewise.
|
||||||
|
(ld_${EMULATION_NAME}_emulation): Replace after_open_default with
|
||||||
|
gld${EMULATION_NAME}_after_open.
|
||||||
|
|
||||||
Mon Jul 3 14:26:37 1995 Steve Chamberlain <sac@slash.cygnus.com>
|
Mon Jul 3 14:26:37 1995 Steve Chamberlain <sac@slash.cygnus.com>
|
||||||
|
|
||||||
* configure.in (i386-*-win32): New target.
|
* configure.in (i386-*-win32): New target.
|
||||||
|
|
|
@ -46,6 +46,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
|
static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
|
||||||
static boolean gld${EMULATION_NAME}_open_dynamic_archive
|
static boolean gld${EMULATION_NAME}_open_dynamic_archive
|
||||||
PARAMS ((const char *, lang_input_statement_type *));
|
PARAMS ((const char *, lang_input_statement_type *));
|
||||||
|
static void gld${EMULATION_NAME}_after_open PARAMS ((void));
|
||||||
|
static void gld${EMULATION_NAME}_check_needed
|
||||||
|
PARAMS ((lang_input_statement_type *));
|
||||||
|
static boolean gld${EMULATION_NAME}_search_needed
|
||||||
|
PARAMS ((const char *, const char *));
|
||||||
|
static boolean gld${EMULATION_NAME}_try_needed PARAMS ((const char *));
|
||||||
static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
|
static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
|
||||||
static void gld${EMULATION_NAME}_find_statement_assignment
|
static void gld${EMULATION_NAME}_find_statement_assignment
|
||||||
PARAMS ((lang_statement_union_type *));
|
PARAMS ((lang_statement_union_type *));
|
||||||
|
@ -107,6 +113,174 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, entry)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* These variables are required to pass information back and forth
|
||||||
|
between after_open and check_needed. */
|
||||||
|
|
||||||
|
static struct bfd_elf_link_needed_list *global_needed;
|
||||||
|
static boolean global_found;
|
||||||
|
|
||||||
|
/* This is called after all the input files have been opened. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
gld${EMULATION_NAME}_after_open ()
|
||||||
|
{
|
||||||
|
struct bfd_elf_link_needed_list *needed, *l;
|
||||||
|
|
||||||
|
/* Get the list of files which appear in DT_NEEDED entries in
|
||||||
|
dynamic objects included in the link (often there will be none).
|
||||||
|
For each such file, we want to track down the corresponding
|
||||||
|
library, and include the symbol table in the link. This is what
|
||||||
|
the runtime dynamic linker will do. Tracking the files down here
|
||||||
|
permits one dynamic object to include another without requiring
|
||||||
|
special action by the person doing the link. Note that the
|
||||||
|
needed list can actually grow while we are stepping through this
|
||||||
|
loop. */
|
||||||
|
needed = bfd_elf_get_needed_list (output_bfd, &link_info);
|
||||||
|
for (l = needed; l != NULL; l = l->next)
|
||||||
|
{
|
||||||
|
struct bfd_elf_link_needed_list *ll;
|
||||||
|
const char *lib_path;
|
||||||
|
size_t len;
|
||||||
|
search_dirs_type *search;
|
||||||
|
|
||||||
|
/* If we've already seen this file, skip it. */
|
||||||
|
for (ll = needed; ll != l; ll = ll->next)
|
||||||
|
if (strcmp (ll->name, l->name) == 0)
|
||||||
|
break;
|
||||||
|
if (ll != l)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* See if this file was included in the link explicitly. */
|
||||||
|
global_needed = l;
|
||||||
|
global_found = false;
|
||||||
|
lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
|
||||||
|
if (global_found)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* We need to find this file and include the symbol table. We
|
||||||
|
want to search for the file in the same way that the dynamic
|
||||||
|
linker will search. That means that we want to use rpath,
|
||||||
|
then the environment variable LD_LIBRARY_PATH, then the
|
||||||
|
linker script LIB_SEARCH_DIRS. We do not search using the -L
|
||||||
|
arguments. */
|
||||||
|
if (gld${EMULATION_NAME}_search_needed (command_line.rpath, l->name))
|
||||||
|
continue;
|
||||||
|
lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
|
||||||
|
if (gld${EMULATION_NAME}_search_needed (lib_path, l->name))
|
||||||
|
continue;
|
||||||
|
len = strlen (l->name);
|
||||||
|
for (search = search_head; search != NULL; search = search->next)
|
||||||
|
{
|
||||||
|
char *filename;
|
||||||
|
|
||||||
|
if (search->cmdline)
|
||||||
|
continue;
|
||||||
|
filename = (char *) xmalloc (strlen (search->name) + len + 2);
|
||||||
|
sprintf (filename, "%s/%s", search->name, l->name);
|
||||||
|
if (gld${EMULATION_NAME}_try_needed (filename))
|
||||||
|
break;
|
||||||
|
free (filename);
|
||||||
|
}
|
||||||
|
if (search != NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
einfo ("%P: warning: %s, needed by %B, not found\n",
|
||||||
|
l->name, l->by);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Search for a needed file in a path. */
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
gld${EMULATION_NAME}_search_needed (path, name)
|
||||||
|
const char *path;
|
||||||
|
const char *name;
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (path == NULL || *path == '\0')
|
||||||
|
return false;
|
||||||
|
len = strlen (name);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
char *filename, *sset;
|
||||||
|
|
||||||
|
s = strchr (path, ':');
|
||||||
|
if (s == NULL)
|
||||||
|
s = path + strlen (path);
|
||||||
|
|
||||||
|
filename = (char *) xmalloc (s - path + len + 2);
|
||||||
|
if (s == path)
|
||||||
|
sset = filename;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy (filename, path, s - path);
|
||||||
|
filename[s - path] = '/';
|
||||||
|
sset = filename + (s - path) + 1;
|
||||||
|
}
|
||||||
|
strcpy (sset, name);
|
||||||
|
|
||||||
|
if (gld${EMULATION_NAME}_try_needed (filename))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
free (filename);
|
||||||
|
|
||||||
|
if (*s == '\0')
|
||||||
|
break;
|
||||||
|
path = s + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function is called for each possible name for a dynamic object
|
||||||
|
named by a DT_NEEDED entry. */
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
gld${EMULATION_NAME}_try_needed (name)
|
||||||
|
const char *name;
|
||||||
|
{
|
||||||
|
bfd *abfd;
|
||||||
|
|
||||||
|
abfd = bfd_openr (name, bfd_get_target (output_bfd));
|
||||||
|
if (abfd == NULL)
|
||||||
|
return false;
|
||||||
|
if (! bfd_check_format (abfd, bfd_object))
|
||||||
|
{
|
||||||
|
(void) bfd_close (abfd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
|
||||||
|
{
|
||||||
|
(void) bfd_close (abfd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We've found a dynamic object matching the DT_NEEDED entry. */
|
||||||
|
|
||||||
|
/* Tell the ELF backend that don't want the output file to have a
|
||||||
|
DT_NEEDED entry for this file. */
|
||||||
|
bfd_elf_set_dt_needed_name (abfd, "");
|
||||||
|
|
||||||
|
/* Add this file into the symbol table. */
|
||||||
|
if (! bfd_link_add_symbols (abfd, &link_info))
|
||||||
|
einfo ("%F%B: could not read symbols: %E\n", abfd);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See if an input file matches a DT_NEEDED entry. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
gld${EMULATION_NAME}_check_needed (s)
|
||||||
|
lang_input_statement_type *s;
|
||||||
|
{
|
||||||
|
if (s->filename != NULL
|
||||||
|
&& strcmp (s->filename, global_needed->name) == 0)
|
||||||
|
global_found = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* This is called after the sections have been attached to output
|
/* This is called after the sections have been attached to output
|
||||||
sections, but before any sizes or addresses have been set. */
|
sections, but before any sizes or addresses have been set. */
|
||||||
|
|
||||||
|
@ -173,6 +347,37 @@ gld${EMULATION_NAME}_before_allocation ()
|
||||||
s->_raw_size = 0;
|
s->_raw_size = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined (TARGET_IS_elf32bmip) || defined (TARGET_IS_elf32lmip)
|
||||||
|
/* For MIPS ELF the .reginfo section requires special handling.
|
||||||
|
Each input section is 24 bytes, and the final output section must
|
||||||
|
also be 24 bytes. We handle this by clobbering all but the first
|
||||||
|
input section size to 0. The .reginfo section is handled
|
||||||
|
specially by the backend code anyhow. */
|
||||||
|
{
|
||||||
|
boolean found = false;
|
||||||
|
LANG_FOR_EACH_INPUT_STATEMENT (is)
|
||||||
|
{
|
||||||
|
asection *s;
|
||||||
|
|
||||||
|
if (is->just_syms_flag)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
s = bfd_get_section_by_name (is->the_bfd, ".reginfo");
|
||||||
|
if (s == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (! found)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->_raw_size = 0;
|
||||||
|
s->_cooked_size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is called by the before_allocation routine via
|
/* This is called by the before_allocation routine via
|
||||||
|
@ -235,6 +440,7 @@ static lang_output_section_statement_type *hold_use;
|
||||||
static lang_output_section_statement_type *hold_text;
|
static lang_output_section_statement_type *hold_text;
|
||||||
static lang_output_section_statement_type *hold_data;
|
static lang_output_section_statement_type *hold_data;
|
||||||
static lang_output_section_statement_type *hold_bss;
|
static lang_output_section_statement_type *hold_bss;
|
||||||
|
static lang_output_section_statement_type *hold_rel;
|
||||||
|
|
||||||
/*ARGSUSED*/
|
/*ARGSUSED*/
|
||||||
static boolean
|
static boolean
|
||||||
|
@ -265,8 +471,10 @@ gld${EMULATION_NAME}_place_orphan (file, s)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
secname = bfd_get_section_name (s->owner, s);
|
||||||
|
|
||||||
/* Decide which segment the section should go in based on the
|
/* Decide which segment the section should go in based on the
|
||||||
section flags. */
|
section name and section flags. */
|
||||||
place = NULL;
|
place = NULL;
|
||||||
if ((s->flags & SEC_HAS_CONTENTS) == 0
|
if ((s->flags & SEC_HAS_CONTENTS) == 0
|
||||||
&& hold_bss != NULL)
|
&& hold_bss != NULL)
|
||||||
|
@ -274,37 +482,29 @@ gld${EMULATION_NAME}_place_orphan (file, s)
|
||||||
else if ((s->flags & SEC_READONLY) == 0
|
else if ((s->flags & SEC_READONLY) == 0
|
||||||
&& hold_data != NULL)
|
&& hold_data != NULL)
|
||||||
place = hold_data;
|
place = hold_data;
|
||||||
|
else if (strncmp (secname, ".rel", 4) == 0
|
||||||
|
&& hold_rel != NULL)
|
||||||
|
place = hold_rel;
|
||||||
else if ((s->flags & SEC_READONLY) != 0
|
else if ((s->flags & SEC_READONLY) != 0
|
||||||
&& hold_text != NULL)
|
&& hold_text != NULL)
|
||||||
place = hold_text;
|
place = hold_text;
|
||||||
if (place == NULL)
|
if (place == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
secname = bfd_get_section_name (s->owner, s);
|
|
||||||
|
|
||||||
/* When generating an object which is to be dynamically linked, we
|
|
||||||
do not support orphaned reloc sections. This is because all the
|
|
||||||
reloc sections must be contiguous in order to generate correct
|
|
||||||
DT_REL entries. When this case arises, you can just add the
|
|
||||||
appropriate reloc sections to the linker script. Note that the
|
|
||||||
.rel.plt section must always be the last reloc section. FIXME:
|
|
||||||
This should simply be handled correctly here. */
|
|
||||||
ASSERT (strncmp (secname, ".rel", 4) != 0
|
|
||||||
|| bfd_get_section_by_name (output_bfd, ".dynamic") == NULL);
|
|
||||||
|
|
||||||
/* Create the section in the output file, and put it in the right
|
/* Create the section in the output file, and put it in the right
|
||||||
place. This shuffling to make the output file look neater, and
|
place. This shuffling is to make the output file look neater. */
|
||||||
also means that the BFD backend does not have to sort the
|
|
||||||
sections in order by address. */
|
|
||||||
snew = bfd_make_section (output_bfd, secname);
|
snew = bfd_make_section (output_bfd, secname);
|
||||||
if (snew == NULL)
|
if (snew == NULL)
|
||||||
einfo ("%P%F: output format %s cannot represent section called %s\n",
|
einfo ("%P%F: output format %s cannot represent section called %s\n",
|
||||||
output_bfd->xvec->name, secname);
|
output_bfd->xvec->name, secname);
|
||||||
for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
|
if (place->bfd_section != NULL)
|
||||||
;
|
{
|
||||||
*pps = snew->next;
|
for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
|
||||||
snew->next = place->bfd_section->next;
|
;
|
||||||
place->bfd_section->next = snew;
|
*pps = snew->next;
|
||||||
|
snew->next = place->bfd_section->next;
|
||||||
|
place->bfd_section->next = snew;
|
||||||
|
}
|
||||||
|
|
||||||
/* Start building a list of statements for this section. */
|
/* Start building a list of statements for this section. */
|
||||||
old = stat_ptr;
|
old = stat_ptr;
|
||||||
|
@ -382,6 +582,9 @@ gld${EMULATION_NAME}_place_section (s)
|
||||||
hold_data = os;
|
hold_data = os;
|
||||||
else if (strcmp (os->name, ".bss") == 0)
|
else if (strcmp (os->name, ".bss") == 0)
|
||||||
hold_bss = os;
|
hold_bss = os;
|
||||||
|
else if (hold_rel == NULL
|
||||||
|
&& strncmp (os->name, ".rel", 4) == 0)
|
||||||
|
hold_rel = os;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
|
@ -451,7 +654,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
|
||||||
syslib_default,
|
syslib_default,
|
||||||
hll_default,
|
hll_default,
|
||||||
after_parse_default,
|
after_parse_default,
|
||||||
after_open_default,
|
gld${EMULATION_NAME}_after_open,
|
||||||
after_allocation_default,
|
after_allocation_default,
|
||||||
set_output_arch_default,
|
set_output_arch_default,
|
||||||
ldemul_default_target,
|
ldemul_default_target,
|
||||||
|
|
Loading…
Reference in New Issue