aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1994-05-19 18:25:10 +0000
committerIan Lance Taylor <ian@airs.com>1994-05-19 18:25:10 +0000
commit2a9fa50cd8ae5dc1e99056c9683bece549e0b68f (patch)
treed4a3dce560b126bc852e1b8cd1dabaa266b7ba2d
parent013dec1ad95ef067951314b9f1beb2fa53296a6f (diff)
downloadgdb-2a9fa50cd8ae5dc1e99056c9683bece549e0b68f.zip
gdb-2a9fa50cd8ae5dc1e99056c9683bece549e0b68f.tar.gz
gdb-2a9fa50cd8ae5dc1e99056c9683bece549e0b68f.tar.bz2
Add support for ELF shared libraries.
* ld.h (ld_config_type): Add field dynamic_link. * ldmain.c (main): Initialize config.dynamic_link to false. Warn on attempts to use -r with -relax, -call_shared or -s. * lexsup.c (longopts): Separate OPTION_CALL_SHARED from OPTION_NON_SHARED. Add OPTION_IGNORE. Adjust macro values accordingly. Add "dy" and "non_shared" options. Change "Qy" to OPTION_IGNORE for now. Handle OPTION_CALL_SHARED and OPTION_NON_SHARED by setting dynamic_link field accordingly. Handle OPTION_IGNORE by ignoring it. Clear dynamic_link field for -r and -Ur. * ldfile.c (ldfile_open_file): If config.dynamic_link is true, try opening a file with a .so extension first. * emultempl/elf32.em: New file. * emulparams/elf32_sparc.sh (TEXT_START_ADDR): Change to 0x10000. (NONPAGED_TEXT_START_ADDR): Likewise. (TEMPLATE_NAME): Define as elf32. (DATA_PLT): Define. * emulparams/elf_i386.sh (TEMPLATE_NAME): Define as elf32. * scripttempl/elf.sc: Add placement for new dynamic sections. Don't use CREATE_OBJECT_SYMBOLS. Define _etext, _edata and _end outside of any section. Don't use ALIGN(8); just let one section VMA follow another. Put .dynbss in .bss. Don't mention debugging sections; they'll be handled correctly anyhow. * Makefile.in (eelf_i386.c): Depend upon elf32.em, not generic.em.
-rw-r--r--ld/ChangeLog28
-rw-r--r--ld/Makefile.in2
-rw-r--r--ld/emultempl/.Sanitize1
-rw-r--r--ld/emultempl/elf32.em196
-rw-r--r--ld/ld.h85
-rw-r--r--ld/ldfile.c54
-rw-r--r--ld/ldmain.c83
-rw-r--r--ld/lexsup.c55
-rw-r--r--ld/scripttempl/elf.sc76
9 files changed, 410 insertions, 170 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index c28c53f..4e22493 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,31 @@
+Thu May 19 13:31:33 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ Add support for ELF shared libraries.
+ * ld.h (ld_config_type): Add field dynamic_link.
+ * ldmain.c (main): Initialize config.dynamic_link to false. Warn
+ on attempts to use -r with -relax, -call_shared or -s.
+ * lexsup.c (longopts): Separate OPTION_CALL_SHARED from
+ OPTION_NON_SHARED. Add OPTION_IGNORE. Adjust macro values
+ accordingly. Add "dy" and "non_shared" options. Change "Qy" to
+ OPTION_IGNORE for now. Handle OPTION_CALL_SHARED and
+ OPTION_NON_SHARED by setting dynamic_link field accordingly.
+ Handle OPTION_IGNORE by ignoring it. Clear dynamic_link field for
+ -r and -Ur.
+ * ldfile.c (ldfile_open_file): If config.dynamic_link is true, try
+ opening a file with a .so extension first.
+ * emultempl/elf32.em: New file.
+ * emulparams/elf32_sparc.sh (TEXT_START_ADDR): Change to 0x10000.
+ (NONPAGED_TEXT_START_ADDR): Likewise.
+ (TEMPLATE_NAME): Define as elf32.
+ (DATA_PLT): Define.
+ * emulparams/elf_i386.sh (TEMPLATE_NAME): Define as elf32.
+ * scripttempl/elf.sc: Add placement for new dynamic sections.
+ Don't use CREATE_OBJECT_SYMBOLS. Define _etext, _edata and _end
+ outside of any section. Don't use ALIGN(8); just let one section
+ VMA follow another. Put .dynbss in .bss. Don't mention debugging
+ sections; they'll be handled correctly anyhow.
+ * Makefile.in (eelf_i386.c): Depend upon elf32.em, not generic.em.
+
Wed May 18 10:15:39 1994 Ian Lance Taylor (ian@cygnus.com)
* Makefile.in (install): Redirect output of ln to /dev/null.
diff --git a/ld/Makefile.in b/ld/Makefile.in
index 948cca4..c3f42c0 100644
--- a/ld/Makefile.in
+++ b/ld/Makefile.in
@@ -372,7 +372,7 @@ emipsidtl.c: $(srcdir)/emulparams/mipsidtl.sh \
$(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/mips.sc ${GEN_DEPENDS}
${GENSCRIPTS} mipsidtl
eelf_i386.c: $(srcdir)/emulparams/elf_i386.sh \
- $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf_i386
eelf32mipb.c: $(srcdir)/emulparams/elf32mipb.sh \
$(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
diff --git a/ld/emultempl/.Sanitize b/ld/emultempl/.Sanitize
index 18e6d03..c0f5649 100644
--- a/ld/emultempl/.Sanitize
+++ b/ld/emultempl/.Sanitize
@@ -25,6 +25,7 @@ Do-first:
Things-to-keep:
README
+elf32.em
generic.em
gld960.em
gld960c.em
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
new file mode 100644
index 0000000..1ce59dd
--- /dev/null
+++ b/ld/emultempl/elf32.em
@@ -0,0 +1,196 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* This file is is generated by a shell script. DO NOT EDIT! */
+
+/* 32 bit ELF emulation code for ${EMULATION_NAME}
+ Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+ Written by Steve Chamberlain <sac@cygnus.com>
+ ELF support by Ian Lance Taylor <ian@cygnus.com>
+
+This file is part of GLD, the Gnu Linker.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "config.h"
+#include "ldmain.h"
+#include "ldemul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+#include "ldexp.h"
+#include "ldlang.h"
+
+static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
+static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
+static void gld${EMULATION_NAME}_find_statement_assignment
+ PARAMS ((lang_statement_union_type *));
+static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *));
+static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
+
+static void
+gld${EMULATION_NAME}_before_parse()
+{
+ ldfile_output_architecture = bfd_arch_${ARCH};
+ config.dynamic_link = true;
+}
+
+/* This is called after the sections have been attached to output
+ sections, but before any sizes or addresses have been set. */
+
+static void
+gld${EMULATION_NAME}_before_allocation ()
+{
+ /* If we are going to make any variable assignments, we need to let
+ the ELF backend know about them in case the variables are
+ referred to by dynamic objects. */
+ lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
+
+ /* Let the ELF backend work out the sizes of any sections required
+ by dynamic linking. */
+ if (! bfd_elf32_size_dynamic_sections (output_bfd, &link_info))
+ einfo ("%P%F: failed to set dynamic section sizes: %E\n");
+}
+
+/* This is called by the before_allocation routine via
+ lang_for_each_statement. It locates any assignment statements, and
+ tells the ELF backend about them, in case they are assignments to
+ symbols which are referred to by dynamic objects. */
+
+static void
+gld${EMULATION_NAME}_find_statement_assignment (s)
+ lang_statement_union_type *s;
+{
+ if (s->header.type == lang_assignment_statement_enum)
+ gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
+}
+
+/* Look through an expression for an assignment statement. */
+
+static void
+gld${EMULATION_NAME}_find_exp_assignment (exp)
+ etree_type *exp;
+{
+ switch (exp->type.node_class)
+ {
+ case etree_assign:
+ if (strcmp (exp->assign.dst, ".") != 0)
+ {
+ if (! bfd_elf32_record_link_assignment (output_bfd, &link_info,
+ exp->assign.dst))
+ einfo ("%P%F: failed to record assignment to %s: %E\n",
+ exp->assign.dst);
+ }
+ gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
+ break;
+
+ case etree_binary:
+ gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
+ gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
+ break;
+
+ case etree_trinary:
+ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
+ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
+ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs);
+ break;
+
+ case etree_unary:
+ gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static char *
+gld${EMULATION_NAME}_get_script(isfile)
+ int *isfile;
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc='s/["\\]/\\&/g
+s/$/\\n\\/
+1s/^/"/
+$s/$/n"/
+'
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`;
+ else if (link_info.relocateable == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xr`;
+ else if (!config.text_read_only)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`;
+ else if (!config.magic_demand_paged)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`;
+ else
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
+}
+EOF
+
+else
+# Scripts read from the filesystem.
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 1;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocateable == true)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+ gld${EMULATION_NAME}_before_parse,
+ syslib_default,
+ hll_default,
+ after_parse_default,
+ after_allocation_default,
+ set_output_arch_default,
+ ldemul_default_target,
+ gld${EMULATION_NAME}_before_allocation,
+ gld${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}"
+};
+EOF
diff --git a/ld/ld.h b/ld/ld.h
index 5aa8036..2ab94f6 100644
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -18,66 +18,41 @@
along with GLD; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+#ifndef LD_H
+#define LD_H
-#define flag_is_not_at_end(x) ((x) & BSF_NOT_AT_END)
-#define flag_is_ordinary_local(x) (((x) & (BSF_LOCAL))&!((x) & (BSF_DEBUGGING)))
-#define flag_is_debugger(x) ((x) & BSF_DEBUGGING)
-#define flag_is_undefined_or_global(x) ((x) & (BSF_UNDEFINED | BSF_GLOBAL))
-#define flag_is_defined(x) (!((x) & (BSF_UNDEFINED)))
-#define flag_is_global_or_common(x) ((x) & (BSF_GLOBAL | BSF_FORT_COMM))
-#define flag_is_undefined_or_global_or_common(x) ((x) & (BSF_UNDEFINED | BSF_GLOBAL | BSF_FORT_COMM))
-#define flag_is_undefined_or_global_or_common_or_constructor(x) ((x) & (BSF_UNDEFINED | BSF_GLOBAL | BSF_FORT_COMM | BSF_CONSTRUCTOR))
-#define flag_is_constructor(x) ((x) & BSF_CONSTRUCTOR)
-#define flag_is_common(x) ((x) & BSF_FORT_COMM)
-#define flag_is_global(x) ((x) & (BSF_GLOBAL))
-#define flag_is_weak(x) ((x) & BSF_WEAK)
-#define flag_is_undefined(x) ((x) & BSF_UNDEFINED)
-#define flag_set(x,y) (x = y)
-#define flag_is_fort_comm(x) ((x) & BSF_FORT_COMM)
-#define flag_is_absolute(x) ((x) & BSF_ABSOLUTE)
/* Extra information we hold on sections */
-typedef struct user_section_struct {
+typedef struct user_section_struct
+{
/* Pointer to the section where this data will go */
struct lang_input_statement_struct *file;
} section_userdata_type;
#define get_userdata(x) ((x)->userdata)
-#define as_output_section_statement(x) ((x)->otheruserdata)
-
-
-
-/* Which symbols should be stripped (omitted from the output):
- none, all, or debugger symbols. */
-typedef enum { STRIP_NONE, STRIP_ALL, STRIP_DEBUGGER, STRIP_SOME } strip_symbols_type;
-
-
-
-
-/* Which local symbols should be omitted:
- none, all, or those starting with L.
- This is irrelevant if STRIP_NONE. */
-typedef enum { DISCARD_NONE, DISCARD_ALL, DISCARD_L } discard_locals_type;
-
#define BYTE_SIZE (1)
#define SHORT_SIZE (2)
#define LONG_SIZE (4)
+#define QUAD_SIZE (8)
/* ALIGN macro changed to ALIGN_N to avoid */
/* conflict in /usr/include/machine/machparam.h */
-/* WARNING: If THIS is a 64 bit address and BOUNDARY is an unsigned int,
+/* WARNING: If THIS is a 64 bit address and BOUNDARY is a 32 bit int,
you must coerce boundary to the same type as THIS.
??? Is there a portable way to avoid this. */
-#define ALIGN_N(this, boundary) ((( (this) + ((boundary) -1)) & (~((boundary)-1))))
+#define ALIGN_N(this, boundary) \
+ ((( (this) + ((boundary) -1)) & (~((boundary)-1))))
-typedef struct {
+typedef struct
+{
/* 1 => assign space to common symbols even if `relocatable_output'. */
boolean force_common_definition;
boolean relax;
-
} args_type;
+extern args_type command_line;
+
typedef int token_code_type;
typedef struct
@@ -85,41 +60,37 @@ typedef struct
bfd_size_type specified_data_size;
boolean magic_demand_paged;
boolean make_executable;
- /* 1 => write relocation into output file so can re-input it later. */
- boolean relocateable_output;
- /* Will we build contstructors, or leave alone ? */
+ /* If true, doing a dynamic link. */
+ boolean dynamic_link;
+
boolean build_constructors;
/* If true, warn about merging common symbols with others. */
boolean warn_common;
boolean sort_common;
-/* these flags may seem mutually exclusive, but not setting them
- allows the back end to decide what would be the best thing to do */
+
boolean text_read_only;
- char *map_filename;
- FILE *map_file;
+ char *map_filename;
+ FILE *map_file;
+ boolean stats;
} ld_config_type;
-#define set_asymbol_chain(x,y) ((x)->udata = (PTR)y)
-#define get_asymbol_chain(x) ((asymbol **)((x)->udata))
-#define get_loader_symbol(x) ((loader_global_asymbol *)((x)->udata))
-#define set_loader_symbol(x,y) ((x)->udata = (PTR)y)
-
-
+extern ld_config_type config;
-
-
-typedef enum {
+typedef enum
+{
lang_first_phase_enum,
lang_allocating_phase_enum,
- lang_final_phase_enum } lang_phase_type;
-
-
+ lang_final_phase_enum
+} lang_phase_type;
+extern boolean had_script;
+extern boolean force_make_executable;
+extern int yyparse PARAMS ((void));
-int yyparse();
+#endif
diff --git a/ld/ldfile.c b/ld/ldfile.c
index 6bcca03..43e9575 100644
--- a/ld/ldfile.c
+++ b/ld/ldfile.c
@@ -1,5 +1,4 @@
-
-/* Copyright (C) 1991 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 93, 94 Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker.
@@ -32,6 +31,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "ldlang.h"
#include "ldfile.h"
#include "ldmain.h"
+#include "ldgram.h"
#include "ldlex.h"
#include <ctype.h>
@@ -89,7 +89,7 @@ ldfile_add_library_path(name)
char *name;
{
search_dirs_type *new =
- (search_dirs_type *)ldmalloc((bfd_size_type)(sizeof(search_dirs_type)));
+ (search_dirs_type *)xmalloc((bfd_size_type)(sizeof(search_dirs_type)));
new->name = name;
new->next = (search_dirs_type*)NULL;
*search_tail_ptr = new;
@@ -160,41 +160,42 @@ open_a(arch, entry, lib, suffix)
void
ldfile_open_file (entry)
-lang_input_statement_type *entry;
+ lang_input_statement_type *entry;
{
-
- if (entry->superfile)
+ if (entry->superfile != NULL)
ldfile_open_file (entry->superfile);
- if (entry->search_dirs_flag)
+ if (! entry->search_dirs_flag)
+ entry->the_bfd = cached_bfd_openr (entry->filename, entry);
+ else
{
search_arch_type *arch;
+
/* Try to open <filename><suffix> or lib<filename><suffix>.a */
-
for (arch = search_arch_head;
- arch != (search_arch_type *)NULL;
- arch = arch->next) {
- if (open_a(arch->name,entry,"lib",".a") != (bfd *)NULL) {
- return;
- }
+ arch != (search_arch_type *) NULL;
+ arch = arch->next)
+ {
+ if (config.dynamic_link)
+ {
+ /* FIXME: Perhaps we will sometimes want something other
+ than .so. */
+ if (open_a (arch->name, entry, "lib", ".so") != (bfd *) NULL)
+ return;
+ }
+ if (open_a (arch->name, entry, "lib", ".a") != (bfd *) NULL)
+ return;
#ifdef VMS
- if (open_a(arch->name,entry,":lib",".a") != (bfd *)NULL) {
- return;
- }
+ if (open_a (arch->name, entry, ":lib", ".a") != (bfd *) NULL)
+ return;
#endif
-
- }
-
+ }
}
- else {
- entry->the_bfd = cached_bfd_openr (entry->filename, entry);
- }
- if (!entry->the_bfd)
+ if (entry->the_bfd == NULL)
einfo("%F%P: cannot open %s: %E\n", entry->local_sym_name);
}
-
/* Try to open NAME; if that fails, try NAME with EXTEN appended to it. */
static FILE *
@@ -264,6 +265,7 @@ char *name;
ldlex_input_stack = ldfile_find_command_file(name, "");
if (ldlex_input_stack == (FILE *)NULL) {
+ bfd_set_error (bfd_error_system_call);
einfo("%P%F: cannot open linker script file %s: %E\n",name);
}
lex_push_file(ldlex_input_stack, name);
@@ -316,7 +318,7 @@ ldfile_add_arch(name)
char *name;
{
search_arch_type *new =
- (search_arch_type *)ldmalloc((bfd_size_type)(sizeof(search_arch_type)));
+ (search_arch_type *)xmalloc((bfd_size_type)(sizeof(search_arch_type)));
if (*name != '\0') {
@@ -343,7 +345,7 @@ ldfile_add_arch (in_name)
{
char *name = buystring(in_name);
search_arch_type *new =
- (search_arch_type *)ldmalloc((bfd_size_type)(sizeof(search_arch_type)));
+ (search_arch_type *)xmalloc((bfd_size_type)(sizeof(search_arch_type)));
ldfile_output_machine_name = in_name;
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 7dfa75b..7deeb6a 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -72,9 +72,6 @@ boolean trace_file_tries;
instead of complaining if no input files are given. */
boolean version_printed;
-/* 1 => write load map. */
-boolean write_map;
-
args_type command_line;
ld_config_type config;
@@ -93,11 +90,10 @@ static boolean multiple_common PARAMS ((struct bfd_link_info *,
bfd_vma));
static boolean add_to_set PARAMS ((struct bfd_link_info *,
struct bfd_link_hash_entry *,
- unsigned int bitsize,
+ bfd_reloc_code_real_type,
bfd *, asection *, bfd_vma));
static boolean constructor_callback PARAMS ((struct bfd_link_info *,
boolean constructor,
- unsigned int bitsize,
const char *name,
bfd *, asection *, bfd_vma));
static boolean warning_callback PARAMS ((struct bfd_link_info *,
@@ -162,8 +158,8 @@ main (argc, argv)
/* Initialize the data about options. */
trace_files = trace_file_tries = version_printed = false;
- write_map = false;
config.build_constructors = true;
+ config.dynamic_link = false;
command_line.force_common_definition = false;
link_info.callbacks = &link_callbacks;
@@ -195,6 +191,16 @@ main (argc, argv)
lang_has_input_file = false;
parse_args (argc, argv);
+ if (link_info.relocateable)
+ {
+ if (command_line.relax)
+ einfo ("%P%F: -relax and -r may not be used together\n");
+ if (config.dynamic_link)
+ einfo ("%P%F: -r and -call_shared may not be used together\n");
+ if (link_info.strip == strip_all)
+ einfo ("%P%F: -r and -s may not be used together\n");
+ }
+
/* This essentially adds another -L directory so this must be done after
the -L's in argv have been processed. */
set_scripts_dir ();
@@ -213,10 +219,6 @@ main (argc, argv)
yyparse ();
}
- if (link_info.relocateable && command_line.relax)
- {
- einfo ("%P%F: -relax and -r may not be used together\n");
- }
lang_final ();
if (lang_has_input_file == false)
@@ -296,7 +298,8 @@ main (argc, argv)
}
else
{
- bfd_close (output_bfd);
+ if (! bfd_close (output_bfd))
+ einfo ("%F%B: final close failed: %E\n", output_bfd);
}
if (config.stats)
@@ -568,8 +571,8 @@ add_archive_element (info, abfd, name)
ldlang_add_file (input);
- if (write_map)
- info_msg ("%s needed due to %T\n", abfd->filename, name);
+ if (config.map_file != (FILE *) NULL)
+ minfo ("%s needed due to %T\n", abfd->filename, name);
if (trace_files || trace_file_tries)
info_msg ("%I\n", input);
@@ -664,15 +667,28 @@ multiple_common (info, name, obfd, otype, osize, nbfd, ntype, nsize)
/*ARGSUSED*/
static boolean
-add_to_set (info, h, bitsize, abfd, section, value)
+add_to_set (info, h, reloc, abfd, section, value)
struct bfd_link_info *info;
struct bfd_link_hash_entry *h;
- unsigned int bitsize;
+ bfd_reloc_code_real_type reloc;
bfd *abfd;
asection *section;
bfd_vma value;
{
- ldctor_add_set_entry (h, bitsize, section, value);
+ if (! config.build_constructors)
+ return true;
+
+ ldctor_add_set_entry (h, reloc, section, value);
+
+ if (h->type == bfd_link_hash_new)
+ {
+ h->type = bfd_link_hash_undefined;
+ h->u.undef.abfd = abfd;
+ /* We don't call bfd_link_add_undef to add this to the list of
+ undefined symbols because we are going to define it
+ ourselves. */
+ }
+
return true;
}
@@ -682,10 +698,9 @@ add_to_set (info, h, bitsize, abfd, section, value)
adding an element to a set, but less general. */
static boolean
-constructor_callback (info, constructor, bitsize, name, abfd, section, value)
+constructor_callback (info, constructor, name, abfd, section, value)
struct bfd_link_info *info;
boolean constructor;
- unsigned int bitsize;
const char *name;
bfd *abfd;
asection *section;
@@ -698,6 +713,11 @@ constructor_callback (info, constructor, bitsize, name, abfd, section, value)
if (! config.build_constructors)
return true;
+ /* Ensure that BFD_RELOC_CTOR exists now, so that we can give a
+ useful error message. */
+ if (bfd_reloc_type_lookup (output_bfd, BFD_RELOC_CTOR) == NULL)
+ einfo ("%P%F: BFD backend error: BFD_RELOC_CTOR unsupported");
+
set_name = (char *) alloca (1 + sizeof "__CTOR_LIST__");
s = set_name;
if (bfd_get_symbol_leading_char (abfd) != '\0')
@@ -707,8 +727,9 @@ constructor_callback (info, constructor, bitsize, name, abfd, section, value)
else
strcpy (s, "__DTOR_LIST__");
- if (write_map)
- info_msg ("Adding %s to constructor/destructor set %s\n", name, set_name);
+ if (config.map_file != (FILE *) NULL)
+ fprintf (config.map_file,
+ "Adding %s to constructor/destructor set %s\n", name, set_name);
h = bfd_link_hash_lookup (info->hash, set_name, true, true, true);
if (h == (struct bfd_link_hash_entry *) NULL)
@@ -722,7 +743,7 @@ constructor_callback (info, constructor, bitsize, name, abfd, section, value)
ourselves. */
}
- ldctor_add_set_entry (h, bitsize, section, value);
+ ldctor_add_set_entry (h, BFD_RELOC_CTOR, section, value);
return true;
}
@@ -790,8 +811,11 @@ reloc_overflow (info, name, reloc_name, addend, abfd, section, address)
asection *section;
bfd_vma address;
{
- einfo ("%X%C: relocation truncated to fit: %s %T", abfd, section,
- address, reloc_name, name);
+ if (abfd == (bfd *) NULL)
+ einfo ("%P%X: generated");
+ else
+ einfo ("%X%C:", abfd, section, address);
+ einfo (" relocation truncated to fit: %s %T", reloc_name, name);
if (addend != 0)
einfo ("+%v", addend);
einfo ("\n");
@@ -809,7 +833,11 @@ reloc_dangerous (info, message, abfd, section, address)
asection *section;
bfd_vma address;
{
- einfo ("%X%C: dangerous relocation: %s\n", abfd, section, address, message);
+ if (abfd == (bfd *) NULL)
+ einfo ("%P%X: generated");
+ else
+ einfo ("%X%C:", abfd, section, address);
+ einfo ("dangerous relocation: %s\n", message);
return true;
}
@@ -825,8 +853,11 @@ unattached_reloc (info, name, abfd, section, address)
asection *section;
bfd_vma address;
{
- einfo ("%X%C: reloc refers to symbol `%T' which is not being output\n",
- abfd, section, address, name);
+ if (abfd == (bfd *) NULL)
+ einfo ("%P%X: generated");
+ else
+ einfo ("%X%C:", abfd, section, address);
+ einfo (" reloc refers to symbol `%T' which is not being output\n", name);
return true;
}
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 0b07e0f..a397574 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -57,50 +57,53 @@ parse_args (argc, argv)
static struct option longopts[] = {
#define OPTION_CALL_SHARED 150
+#define OPTION_NON_SHARED 151
{"call_shared", no_argument, NULL, OPTION_CALL_SHARED},
{"dc", no_argument, NULL, 'd'},
-#define OPTION_DEFSYM 151
+#define OPTION_DEFSYM 152
{"defsym", required_argument, NULL, OPTION_DEFSYM},
- {"dn", no_argument, NULL, OPTION_CALL_SHARED},
+ {"dn", no_argument, NULL, OPTION_NON_SHARED},
{"dp", no_argument, NULL, 'd'},
-#define OPTION_EB 152
+ {"dy", no_argument, NULL, OPTION_CALL_SHARED},
+#define OPTION_EB 153
{"EB", no_argument, NULL, OPTION_EB},
-#define OPTION_EL 153
+#define OPTION_EL 154
{"EL", no_argument, NULL, OPTION_EL},
{"format", required_argument, NULL, 'b'},
-#define OPTION_HELP 154
+#define OPTION_HELP 155
{"help", no_argument, NULL, OPTION_HELP},
-#define OPTION_MAP 155
+#define OPTION_MAP 156
{"Map", required_argument, NULL, OPTION_MAP},
-#define OPTION_NO_KEEP_MEMORY 156
+#define OPTION_NO_KEEP_MEMORY 157
{"no-keep-memory", no_argument, NULL, OPTION_NO_KEEP_MEMORY},
-#define OPTION_NOINHIBIT_EXEC 157
+#define OPTION_NOINHIBIT_EXEC 158
{"noinhibit-exec", no_argument, NULL, OPTION_NOINHIBIT_EXEC},
{"noinhibit_exec", no_argument, NULL, OPTION_NOINHIBIT_EXEC},
- {"non_shared", no_argument, NULL, OPTION_CALL_SHARED},
-#define OPTION_OFORMAT 158
+ {"non_shared", no_argument, NULL, OPTION_NON_SHARED},
+#define OPTION_OFORMAT 159
{"oformat", required_argument, NULL, OPTION_OFORMAT},
- {"Qy", no_argument, NULL, OPTION_CALL_SHARED},
-#define OPTION_RELAX 159
+#define OPTION_IGNORE 160
+ {"Qy", no_argument, NULL, OPTION_IGNORE},
+#define OPTION_RELAX 161
{"relax", no_argument, NULL, OPTION_RELAX},
-#define OPTION_RETAIN_SYMBOLS_FILE 160
+#define OPTION_RETAIN_SYMBOLS_FILE 162
{"retain-symbols-file", no_argument, NULL, OPTION_RETAIN_SYMBOLS_FILE},
-#define OPTION_SORT_COMMON 161
+#define OPTION_SORT_COMMON 163
{"sort-common", no_argument, NULL, OPTION_SORT_COMMON},
{"sort_common", no_argument, NULL, OPTION_SORT_COMMON},
-#define OPTION_STATS 162
+#define OPTION_STATS 164
{"stats", no_argument, NULL, OPTION_STATS},
-#define OPTION_TBSS 163
+#define OPTION_TBSS 165
{"Tbss", required_argument, NULL, OPTION_TBSS},
-#define OPTION_TDATA 164
+#define OPTION_TDATA 166
{"Tdata", required_argument, NULL, OPTION_TDATA},
-#define OPTION_TTEXT 165
+#define OPTION_TTEXT 167
{"Ttext", required_argument, NULL, OPTION_TTEXT},
-#define OPTION_UR 166
+#define OPTION_UR 168
{"Ur", no_argument, NULL, OPTION_UR},
-#define OPTION_VERSION 167
+#define OPTION_VERSION 169
{"version", no_argument, NULL, OPTION_VERSION},
-#define OPTION_WARN_COMMON 168
+#define OPTION_WARN_COMMON 170
{"warn-common", no_argument, NULL, OPTION_WARN_COMMON},
{NULL, no_argument, NULL, 0}
};
@@ -124,6 +127,8 @@ parse_args (argc, argv)
(char *) NULL);
break;
+ case OPTION_IGNORE:
+ break;
case 'A':
ldfile_add_arch (optarg);
break;
@@ -139,7 +144,10 @@ parse_args (argc, argv)
yyparse ();
break;
case OPTION_CALL_SHARED:
- set_default_dirlist ((char *) longopts[longind].name);
+ config.dynamic_link = true;
+ break;
+ case OPTION_NON_SHARED:
+ config.dynamic_link = false;
break;
case 'd':
command_line.force_common_definition = true;
@@ -194,7 +202,6 @@ parse_args (argc, argv)
/* Ignore. Was handled in a pre-parse. */
break;
case OPTION_MAP:
- write_map = true;
config.map_filename = optarg;
break;
case 'N':
@@ -229,6 +236,7 @@ parse_args (argc, argv)
config.build_constructors = false;
config.magic_demand_paged = false;
config.text_read_only = false;
+ config.dynamic_link = false;
break;
case 'R':
lang_add_input_file (optarg,
@@ -275,6 +283,7 @@ parse_args (argc, argv)
config.build_constructors = true;
config.magic_demand_paged = false;
config.text_read_only = false;
+ config.dynamic_link = false;
break;
case 'u':
ldlang_add_undef (optarg);
diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc
index 321a35b..49c3ed4 100644
--- a/ld/scripttempl/elf.sc
+++ b/ld/scripttempl/elf.sc
@@ -8,12 +8,18 @@
# (e.g., .PARISC.global)
# EXECUTABLE_SYMBOLS - symbols that must be defined for an
# executable (e.g., _DYNAMIC_LINK)
+# TEXT_START_SYMBOLS - symbols that appear at the start of the
+# .text section.
+# DATA_START_SYMBOLS - symbols that appear at the start of the
+# .data section.
# OTHER_BSS_SYMBOLS - symbols that appear at the start of the
# .bss section besides __bss_start.
+# DATA_PLT - .plt should be in data segment, not text segment.
#
# When adding sections, do note that the names of some sections are used
# when specifying the start address of the next.
#
+PLT=".plt ${RELOCATING-0} : { *(.plt) }"
cat <<EOF
OUTPUT_FORMAT("${OUTPUT_FORMAT}")
OUTPUT_ARCH(${ARCH})
@@ -29,62 +35,58 @@ ${RELOCATING- /* For some reason, the Solaris linker makes bad executables
SECTIONS
{
/* Read-only sections, merged into text segment: */
- .text ${RELOCATING+${TEXT_START_ADDR}} ${RELOCATING-0} :
+ ${RELOCATING+. = ${TEXT_START_ADDR} + SIZEOF_HEADERS;}
+ .interp ${RELOCATING-0} : { *(.interp) }
+ .hash ${RELOCATING-0} : { *(.hash) }
+ .dynsym ${RELOCATING-0} : { *(.dynsym) }
+ .dynstr ${RELOCATING-0} : { *(.dynstr) }
+ .rel.bss ${RELOCATING-0} : { *(.rel.bss) }
+ .rel.plt ${RELOCATING-0} : { *(.rel.plt) }
+ .rela.bss ${RELOCATING-0} : { *(.rela.bss) }
+ .rela.plt ${RELOCATING-0} : { *(.rela.plt) }
+ .init ${RELOCATING-0} : { *(.init) } =${NOP-0}
+ ${DATA_PLT-${PLT}}
+ .text ${RELOCATING-0} :
{
+ ${RELOCATING+${TEXT_START_SYMBOLS}}
*(.text)
- CREATE_OBJECT_SYMBOLS
- ${RELOCATING+_etext = .;}
}
- .init ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : { *(.init) } =${NOP-0}
- .fini ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : { *(.fini) } =${NOP-0}
- .ctors ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : { *(.ctors) }
- .dtors ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : { *(.dtors) }
- .rodata ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : { *(.rodata) }
- .rodata1 ${RELOCATING+ALIGN(8)} ${RELOCATING-0} :
- {
- *(.rodata1)
- ${RELOCATING+. = ALIGN(8);}
- }
+ ${RELOCATING+_etext = .;}
+ .fini ${RELOCATING-0} : { *(.fini) } =${NOP-0}
+ .ctors ${RELOCATING-0} : { *(.ctors) }
+ .dtors ${RELOCATING-0} : { *(.dtors) }
+ .rodata ${RELOCATING-0} : { *(.rodata) }
+ .rodata1 ${RELOCATING-0} : { *(.rodata1) }
${RELOCATING+${OTHER_READONLY_SECTIONS}}
- /* also: .hash .dynsym .dynstr .plt(if r/o) .rel.got */
/* Read-write section, merged into data segment: */
- .data ${RELOCATING+
- ${DATA_ADDR- ADDR(.rodata1)+SIZEOF(.rodata1)+${MAXPAGESIZE}}
- }
- ${RELOCATING-0} :
+ ${RELOCATING+. = ${DATA_ADDR- ALIGN(8) + ${MAXPAGESIZE}};}
+ .data ${RELOCATING-0} :
{
+ ${RELOCATING+${DATA_START_SYMBOLS}}
*(.data)
${CONSTRUCTING+CONSTRUCTORS}
}
- .data1 ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : { *(.data1) }
+ .data1 ${RELOCATING-0} : { *(.data1) }
${RELOCATING+${OTHER_READWRITE_SECTIONS}}
- /* also (before uninitialized portion): .dynamic .got .plt(if r/w)
- (or does .dynamic go into its own segment?) */
+ .got ${RELOCATING-0} : { *(.got) }
+ .dynamic ${RELOCATING-0} : { *(.dynamic) }
+ ${DATA_PLT+${PLT}}
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
- .sdata ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : { *(.sdata) }
+ .sdata ${RELOCATING-0} : { *(.sdata) }
${RELOCATING+_edata = .;}
- ${RELOCATING+__bss_start = ALIGN(8);}
+ ${RELOCATING+__bss_start = .;}
${RELOCATING+${OTHER_BSS_SYMBOLS}}
- .sbss ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : { *(.sbss) *(.scommon) }
- .bss ${RELOCATING+ALIGN(8)} ${RELOCATING-0} :
+ .sbss ${RELOCATING-0} : { *(.sbss) *(.scommon) }
+ .bss ${RELOCATING-0} :
{
+ *(.dynbss)
*(.bss)
*(COMMON)
- ${RELOCATING+_end = . };
- ${RELOCATING+end = . };
}
-
- /* Debug sections. These should never be loadable, but they must have
- zero addresses for the debuggers to work correctly. */
- .line 0 : { *(.line) }
- .debug 0 : { *(.debug) }
- .debug_sfnames 0 : { *(.debug_sfnames) }
- .debug_srcinfo 0 : { *(.debug_srcinfo) }
- .debug_macinfo 0 : { *(.debug_macinfo) }
- .debug_pubnames 0 : { *(.debug_pubnames) }
- .debug_aranges 0 : { *(.debug_aranges) }
+ ${RELOCATING+_end = . ;}
+ ${RELOCATING+end = . ;}
}
EOF