diff options
-rw-r--r-- | ld/ChangeLog | 28 | ||||
-rw-r--r-- | ld/Makefile.in | 2 | ||||
-rw-r--r-- | ld/emultempl/.Sanitize | 1 | ||||
-rw-r--r-- | ld/emultempl/elf32.em | 196 | ||||
-rw-r--r-- | ld/ld.h | 85 | ||||
-rw-r--r-- | ld/ldfile.c | 54 | ||||
-rw-r--r-- | ld/ldmain.c | 83 | ||||
-rw-r--r-- | ld/lexsup.c | 55 | ||||
-rw-r--r-- | ld/scripttempl/elf.sc | 76 |
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 @@ -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 |