Add support for ELF shared libraries.
authorIan Lance Taylor <ian@airs.com>
Thu, 19 May 1994 18:25:10 +0000 (18:25 +0000)
committerIan Lance Taylor <ian@airs.com>
Thu, 19 May 1994 18:25:10 +0000 (18:25 +0000)
* 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.

ld/ChangeLog
ld/Makefile.in
ld/emultempl/.Sanitize
ld/emultempl/elf32.em [new file with mode: 0644]
ld/ld.h
ld/ldfile.c
ld/ldmain.c
ld/lexsup.c
ld/scripttempl/elf.sc

index c28c53f..4e22493 100644 (file)
@@ -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.
index 948cca4..c3f42c0 100644 (file)
@@ -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}
index 18e6d03..c0f5649 100644 (file)
@@ -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 (file)
index 0000000..1ce59dd
--- /dev/null
@@ -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 (file)
--- a/ld/ld.h
+++ b/ld/ld.h
    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
index 6bcca03..43e9575 100644 (file)
@@ -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;
 
index 7dfa75b..7deeb6a 100644 (file)
@@ -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;
 }
 
index 0b07e0f..a397574 100644 (file)
@@ -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);
index 321a35b..49c3ed4 100644 (file)
@@ -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