/* This file is is generated by a shell script. DO NOT EDIT! */
/* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME}
- Copyright (C) 1991, 93, 94, 95, 96, 97, 98, 1999
+ Copyright (C) 1991, 93, 94, 95, 96, 97, 98, 99, 2000
Free Software Foundation, Inc.
Written by Steve Chamberlain <sac@cygnus.com>
ELF support by Ian Lance Taylor <ian@cygnus.com>
#include "ld.h"
#include "ldmain.h"
-#include "ldemul.h"
-#include "ldfile.h"
#include "ldmisc.h"
#include "ldexp.h"
#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
#include "ldgram.h"
+#include "elf/common.h"
static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
static boolean gld${EMULATION_NAME}_open_dynamic_archive
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 char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
static void
filename = entry->filename;
+ /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION
+ is defined, but it does not seem worth the headache to optimize
+ away those two bytes of space. */
string = (char *) xmalloc (strlen (search->name)
+ strlen (filename)
+ strlen (arch)
+#ifdef EXTRA_SHLIB_EXTENSION
+ + strlen (EXTRA_SHLIB_EXTENSION)
+#endif
+ sizeof "/lib.so");
sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
+#ifdef EXTRA_SHLIB_EXTENSION
+ /* Try the .so extension first. If that fails build a new filename
+ using EXTRA_SHLIB_EXTENSION. */
if (! ldfile_try_open_bfd (string, entry))
- {
- /* It failed using .so, try again with .sl for oddball systems
- that use a different naming scheme (ie hpux). */
- sprintf (string, "%s/lib%s%s.sl", search->name, filename, arch);
+ sprintf (string, "%s/lib%s%s%s", search->name,
+ filename, arch, EXTRA_SHLIB_EXTENSION);
+#endif
- if (! ldfile_try_open_bfd (string, entry))
- {
- free (string);
- return false;
- }
+ if (! ldfile_try_open_bfd (string, entry))
+ {
+ free (string);
+ return false;
}
entry->filename = string;
if (bfd_check_format (entry->the_bfd, bfd_object)
&& (entry->the_bfd->flags & DYNAMIC) != 0)
{
- char *filname, *needed_name;
+ char *needed_name;
ASSERT (entry->is_archive && entry->search_dirs_flag);
/* Rather than duplicating the logic above. Just use the
- filename we recorded earlier.o
+ filename we recorded earlier.
First strip off everything before the last '/'. */
filename = strrchr (entry->filename, '/');
filename++;
- needed_name = (char *) xmalloc (strlen (filename)) + 1;
+ needed_name = (char *) xmalloc (strlen (filename) + 1);
strcpy (needed_name, filename);
bfd_elf_set_dt_needed_name (entry->the_bfd, needed_name);
}
path = s + 1;
}
- return false;
+ return false;
}
/* This function is called for each possible name for a dynamic object
DT_NEEDED entry for this file. */
bfd_elf_set_dt_needed_name (abfd, "");
+ /* First strip off everything before the last '/'. */
+ name = strrchr (abfd->filename, '/');
+ if (name)
+ name++;
+ else
+ name = 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. */
+ bfd_elf_set_dt_needed_soname (abfd, name);
+
/* 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);
/* 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;
-static lang_output_section_statement_type *hold_text;
-static lang_output_section_statement_type *hold_rodata;
-static lang_output_section_statement_type *hold_data;
-static lang_output_section_statement_type *hold_bss;
-static lang_output_section_statement_type *hold_rel;
-static lang_output_section_statement_type *hold_interp;
+struct orphan_save
+{
+ lang_output_section_statement_type *os;
+ asection **section;
+ lang_statement_union_type **stmt;
+};
/*ARGSUSED*/
static boolean
lang_input_statement_type *file;
asection *s;
{
- lang_output_section_statement_type *place;
- asection *snew, **pps;
+ 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;
etree_type *address;
const char *outsecname;
lang_output_section_statement_type *os;
- if ((s->flags & SEC_ALLOC) == 0)
- return false;
+ 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. */
if (! link_info.shared
&& ! link_info.relocateable
&& strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
- && hold_text != NULL)
+ && hold_text.os != NULL)
{
- wild_doit (&hold_text->children, s, hold_text, file);
+ wild_doit (&hold_text.os->children, s, hold_text.os, file);
return true;
}
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. */
- place = NULL;
+#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 != NULL)
- place = hold_interp;
+ && strncmp (secname, ".note", 4) == 0
+ && HAVE_SECTION (hold_interp, ".interp"))
+ place = &hold_interp;
else if ((s->flags & SEC_HAS_CONTENTS) == 0
- && hold_bss != NULL)
- place = hold_bss;
+ && HAVE_SECTION (hold_bss, ".bss"))
+ place = &hold_bss;
else if ((s->flags & SEC_READONLY) == 0
- && hold_data != NULL)
- place = hold_data;
+ && HAVE_SECTION (hold_data, ".data"))
+ place = &hold_data;
else if (strncmp (secname, ".rel", 4) == 0
- && hold_rel != NULL)
- place = hold_rel;
+ && (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 != NULL)
- place = hold_rodata;
+ && HAVE_SECTION (hold_rodata, ".rodata"))
+ place = &hold_rodata;
else if ((s->flags & SEC_READONLY) != 0
- && hold_text != NULL)
- place = hold_text;
- if (place == NULL)
- return false;
+ && hold_text.os != NULL)
+ place = &hold_text;
+ 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
outsecname = newname;
}
- /* Create the section in the output file, and put it in the right
- place. This shuffling is to make the output file look neater. */
- snew = bfd_make_section (output_bfd, outsecname);
- if (snew == NULL)
- einfo ("%P%F: output format %s cannot represent section called %s\n",
- output_bfd->xvec->name, outsecname);
- if (place->bfd_section != NULL)
- {
- for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
- ;
- *pps = snew->next;
- snew->next = place->bfd_section->next;
- place->bfd_section->next = snew;
- }
-
- /* Start building a list of statements for this section. */
- old = stat_ptr;
- stat_ptr = &add;
- lang_list_init (stat_ptr);
-
- /* 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++)
- if (! isalnum ((unsigned char) *ps) && *ps != '_')
- break;
- if (*ps == '\0' && config.build_constructors)
+ if (place != NULL)
{
- char *symname;
-
- symname = (char *) xmalloc (ps - outsecname + sizeof "__start_");
- sprintf (symname, "__start_%s", outsecname);
- lang_add_assignment (exp_assop ('=', symname,
- exp_unop (ALIGN_K,
- exp_intop ((bfd_vma) 1
- << s->alignment_power))));
+ /* Start building a list of statements for this section. */
+ old = stat_ptr;
+ stat_ptr = &add;
+ lang_list_init (stat_ptr);
+
+ /* 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++)
+ if (! isalnum ((unsigned char) *ps) && *ps != '_')
+ break;
+ if (*ps == '\0' && config.build_constructors)
+ {
+ char *symname;
+ etree_type *e_align;
+
+ symname = (char *) xmalloc (ps - outsecname + sizeof "__start_");
+ sprintf (symname, "__start_%s", outsecname);
+ e_align = exp_unop (ALIGN_K,
+ exp_intop ((bfd_vma) 1 << s->alignment_power));
+ lang_add_assignment (exp_assop ('=', symname, e_align));
+ }
}
- if (! link_info.relocateable)
- address = NULL;
- else
+ if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
address = exp_intop ((bfd_vma) 0);
+ 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
- ((bfd_vma) 0, "*default*", (struct lang_output_section_phdr_list *) NULL);
- stat_ptr = &add;
+ ((bfd_vma) 0, "*default*",
+ (struct lang_output_section_phdr_list *) NULL, "*default*");
- if (*ps == '\0' && config.build_constructors)
+ if (place != NULL)
{
- char *symname;
+ asection *snew, **pps;
- symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
- sprintf (symname, "__stop_%s", outsecname);
- lang_add_assignment (exp_assop ('=', symname,
- exp_nameop (NAME, ".")));
- }
+ stat_ptr = &add;
+
+ if (*ps == '\0' && config.build_constructors)
+ {
+ char *symname;
+
+ symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
+ sprintf (symname, "__stop_%s", outsecname);
+ lang_add_assignment (exp_assop ('=', symname,
+ exp_nameop (NAME, ".")));
+ }
+ stat_ptr = old;
+
+ snew = os->bfd_section;
+ if (place->os->bfd_section != NULL || place->section != NULL)
+ {
+ /* Shuffle the section to make the output file look neater. */
+ if (place->section == NULL)
+ {
+#if 0
+ /* Finding the end of the list is a little tricky. We
+ make a wild stab at it by comparing section flags. */
+ flagword first_flags = place->os->bfd_section->flags;
+ for (pps = &place->os->bfd_section->next;
+ *pps != NULL && (*pps)->flags == first_flags;
+ pps = &(*pps)->next)
+ ;
+ place->section = pps;
+#else
+ /* Put orphans after the first section on the list. */
+ place->section = &place->os->bfd_section->next;
+#endif
+ }
- /* Now stick the new statement list right after PLACE. */
- *add.tail = place->header.next;
- place->header.next = add.head;
+ /* Unlink the section. */
+ for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
+ ;
+ *pps = snew->next;
- stat_ptr = old;
+ /* Now tack it on to the "place->os" section list. */
+ snew->next = *place->section;
+ *place->section = snew;
+ }
+ place->section = &snew->next; /* Save the end of this list. */
+
+ if (place->stmt == NULL)
+ {
+ /* Put the new statement list right at the head. */
+ *add.tail = place->os->header.next;
+ place->os->header.next = add.head;
+ }
+ else
+ {
+ /* Put it after the last orphan statement we added. */
+ *add.tail = *place->stmt;
+ *place->stmt = add.head;
+ }
+ place->stmt = add.tail; /* Save the end of this list. */
+ }
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;
-
- os = &s->output_section_statement;
+ lang_statement_union_type *u;
+ lang_output_section_statement_type *lookup;
- 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;
- else if (strcmp (os->name, ".rodata") == 0)
- hold_rodata = os;
- else if (strcmp (os->name, ".data") == 0)
- hold_data = os;
- else if (strcmp (os->name, ".bss") == 0)
- hold_bss = os;
- else if (hold_rel == NULL
- && os->bfd_section != NULL
- && (os->bfd_section->flags & SEC_ALLOC) != 0
- && strncmp (os->name, ".rel", 4) == 0)
- hold_rel = os;
- else if (strcmp (os->name, ".interp") == 0)
- hold_interp = 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;
}
static char *
sc="-f stringify.sed"
cat >>e${EMULATION_NAME}.c <<EOF
-{
+{
*isfile = 0;
if (link_info.relocateable == true && config.build_constructors == true)
# Scripts read from the filesystem.
cat >>e${EMULATION_NAME}.c <<EOF
-{
+{
*isfile = 1;
if (link_info.relocateable == true && config.build_constructors == true)
fi
-if test -n "$PARSE_AND_LIST_ARGS" ; then
+if test -n "$PARSE_AND_LIST_ARGS_CASES" || test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
+NEED_PARSE_AND_LIST=yes
+
cat >>e${EMULATION_NAME}.c <<EOF
static int gld_${EMULATION_NAME}_parse_args PARAMS ((int, char **));
static void gld_${EMULATION_NAME}_list_options PARAMS ((FILE * file));
-
- $PARSE_AND_LIST_ARGS
EOF
else
+NEED_PARSE_AND_LIST=no
cat >>e${EMULATION_NAME}.c <<EOF
#define gld_${EMULATION_NAME}_parse_args NULL
fi
+if test -n "$PARSE_AND_LIST_PROLOGUE" ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ $PARSE_AND_LIST_PROLOGUE
+EOF
+fi
+
+if test "$NEED_PARSE_AND_LIST" = yes; then
+cat >>e${EMULATION_NAME}.c <<EOF
+
+#include "getopt.h"
+
+#define OPTION_DISABLE_NEW_DTAGS (400)
+#define OPTION_ENABLE_NEW_DTAGS (OPTION_DISABLE_NEW_DTAGS + 1)
+
+static struct option longopts[] =
+{
+EOF
+fi
+
+if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
+ {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
+EOF
+fi
+
+if test -n "$PARSE_AND_LIST_LONGOPTS" ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ $PARSE_AND_LIST_LONGOPTS
+EOF
+fi
+
+if test "$NEED_PARSE_AND_LIST" = yes; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ {NULL, no_argument, NULL, 0}
+};
+
+static int
+gld_${EMULATION_NAME}_parse_args (argc, argv)
+ int argc;
+ char ** argv;
+{
+ int longind, optc;
+ int prevoptind = optind;
+ int prevopterr = opterr;
+ int wanterror;
+ static int lastoptind = -1;
+
+ if (lastoptind != optind)
+ opterr = 0;
+
+ wanterror = opterr;
+ optc = getopt_long_only (argc, argv, "-z:", longopts, &longind);
+ opterr = prevopterr;
+
+ switch (optc)
+ {
+ default:
+ if (wanterror)
+ xexit (1);
+ optind = prevoptind;
+ return 0;
+
+EOF
+fi
+
+if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ case OPTION_DISABLE_NEW_DTAGS:
+ link_info.new_dtags = false;
+ break;
+
+ case OPTION_ENABLE_NEW_DTAGS:
+ link_info.new_dtags = true;
+ break;
+
+ case 'z':
+ if (strcmp (optarg, "initfirst") == 0)
+ link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
+ else if (strcmp (optarg, "interpose") == 0)
+ link_info.flags_1 |= (bfd_vma) DF_1_INTERPOSE;
+ else if (strcmp (optarg, "loadfltr") == 0)
+ link_info.flags_1 |= (bfd_vma) DF_1_LOADFLTR;
+ else if (strcmp (optarg, "nodefaultlib") == 0)
+ link_info.flags_1 |= (bfd_vma) DF_1_NODEFLIB;
+ else if (strcmp (optarg, "nodelete") == 0)
+ link_info.flags_1 |= (bfd_vma) DF_1_NODELETE;
+ else if (strcmp (optarg, "nodlopen") == 0)
+ link_info.flags_1 |= (bfd_vma) DF_1_NOOPEN;
+ else if (strcmp (optarg, "nodump") == 0)
+ link_info.flags_1 |= (bfd_vma) DF_1_NODUMP;
+ else if (strcmp (optarg, "now") == 0)
+ {
+ link_info.flags |= (bfd_vma) DF_BIND_NOW;
+ link_info.flags_1 |= (bfd_vma) DF_1_NOW;
+ }
+ else if (strcmp (optarg, "origin") == 0)
+ {
+ link_info.flags |= (bfd_vma) DF_ORIGIN;
+ link_info.flags_1 |= (bfd_vma) DF_1_ORIGIN;
+ }
+ /* What about the other Solaris -z options? FIXME. */
+ break;
+EOF
+fi
+
+if test -n "$PARSE_AND_LIST_ARGS_CASES" ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ $PARSE_AND_LIST_ARGS_CASES
+EOF
+fi
+
+if test "$NEED_PARSE_AND_LIST" = yes; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ }
+
+ return 1;
+}
+
+static void
+gld_${EMULATION_NAME}_list_options (file)
+ FILE * file;
+{
+EOF
+fi
+
+if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ fprintf (file, _(" --disable-new-dtags\tDisable new dynamic tags\n"));
+ fprintf (file, _(" --enable-new-dtags\tEnable new dynamic tags\n"));
+ fprintf (file, _(" -z initfirst\t\tMark DSO to be initialized first at rutime\n"));
+ fprintf (file, _(" -z interpose\t\tMark object to interpose all DSOs but execuable\n"));
+ fprintf (file, _(" -z loadfltr\t\tMark object requiring immediate process\n"));
+ fprintf (file, _(" -z nodefaultlib\tMark object not to use default search paths\n"));
+ fprintf (file, _(" -z nodelete\t\tMark DSO non-deletable at runtime\n"));
+ fprintf (file, _(" -z nodlopen\t\tMark DSO not availale to dlopen\n"));
+ fprintf (file, _(" -z nodump\t\tMark DSO not availale to dldump\n"));
+ fprintf (file, _(" -z now\t\tMark object non-lazy runtime binding\n"));
+ fprintf (file, _(" -z origin\t\tMark object requiring immediate \$ORIGIN processing\n"));
+ fprintf (file, _("\t\t\t at runtime\n"));
+ fprintf (file, _(" -z KEYWORD\t\tIgnored for Solaris compatibility\n"));
+EOF
+fi
+
+if test -n "$PARSE_AND_LIST_OPTIONS" ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ $PARSE_AND_LIST_OPTIONS
+EOF
+fi
+
+if test "$NEED_PARSE_AND_LIST" = yes; then
+cat >>e${EMULATION_NAME}.c <<EOF
+}
+EOF
+fi
+
+if test -n "$PARSE_AND_LIST_EPILOGUE" ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ $PARSE_AND_LIST_EPILOGUE
+EOF
+fi
+
cat >>e${EMULATION_NAME}.c <<EOF
-struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
{
gld${EMULATION_NAME}_before_parse,
syslib_default,
gld_${EMULATION_NAME}_parse_args,
NULL, /* unrecognized_file */
gld_${EMULATION_NAME}_list_options,
- NULL /* recognized_file */
+ NULL, /* recognized_file */
+ NULL /* find_potential_libraries */
};
EOF