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.
This commit is contained in:
Ian Lance Taylor 1994-05-19 18:25:10 +00:00
parent 013dec1ad9
commit 2a9fa50cd8
9 changed files with 410 additions and 170 deletions

View 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) Wed May 18 10:15:39 1994 Ian Lance Taylor (ian@cygnus.com)
* Makefile.in (install): Redirect output of ln to /dev/null. * Makefile.in (install): Redirect output of ln to /dev/null.

View file

@ -372,7 +372,7 @@ emipsidtl.c: $(srcdir)/emulparams/mipsidtl.sh \
$(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/mips.sc ${GEN_DEPENDS} $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/mips.sc ${GEN_DEPENDS}
${GENSCRIPTS} mipsidtl ${GENSCRIPTS} mipsidtl
eelf_i386.c: $(srcdir)/emulparams/elf_i386.sh \ 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 ${GENSCRIPTS} elf_i386
eelf32mipb.c: $(srcdir)/emulparams/elf32mipb.sh \ eelf32mipb.c: $(srcdir)/emulparams/elf32mipb.sh \
$(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}

View file

@ -25,6 +25,7 @@ Do-first:
Things-to-keep: Things-to-keep:
README README
elf32.em
generic.em generic.em
gld960.em gld960.em
gld960c.em gld960c.em

196
ld/emultempl/elf32.em Normal file
View file

@ -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

85
ld/ld.h
View file

@ -18,66 +18,41 @@
along with GLD; see the file COPYING. If not, write to along with GLD; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 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 */ /* 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 */ /* Pointer to the section where this data will go */
struct lang_input_statement_struct *file; struct lang_input_statement_struct *file;
} section_userdata_type; } section_userdata_type;
#define get_userdata(x) ((x)->userdata) #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 BYTE_SIZE (1)
#define SHORT_SIZE (2) #define SHORT_SIZE (2)
#define LONG_SIZE (4) #define LONG_SIZE (4)
#define QUAD_SIZE (8)
/* ALIGN macro changed to ALIGN_N to avoid */ /* ALIGN macro changed to ALIGN_N to avoid */
/* conflict in /usr/include/machine/machparam.h */ /* 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. you must coerce boundary to the same type as THIS.
??? Is there a portable way to avoid 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'. */ /* 1 => assign space to common symbols even if `relocatable_output'. */
boolean force_common_definition; boolean force_common_definition;
boolean relax; boolean relax;
} args_type; } args_type;
extern args_type command_line;
typedef int token_code_type; typedef int token_code_type;
typedef struct typedef struct
@ -85,41 +60,37 @@ typedef struct
bfd_size_type specified_data_size; bfd_size_type specified_data_size;
boolean magic_demand_paged; boolean magic_demand_paged;
boolean make_executable; 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; boolean build_constructors;
/* If true, warn about merging common symbols with others. */ /* If true, warn about merging common symbols with others. */
boolean warn_common; boolean warn_common;
boolean sort_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; boolean text_read_only;
char *map_filename; char *map_filename;
FILE *map_file; FILE *map_file;
boolean stats;
} ld_config_type; } 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_first_phase_enum,
lang_allocating_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));
#endif
int yyparse();

View file

@ -1,5 +1,4 @@
/* Copyright (C) 1991, 92, 93, 94 Free Software Foundation, Inc.
/* Copyright (C) 1991 Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker. 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 "ldlang.h"
#include "ldfile.h" #include "ldfile.h"
#include "ldmain.h" #include "ldmain.h"
#include "ldgram.h"
#include "ldlex.h" #include "ldlex.h"
#include <ctype.h> #include <ctype.h>
@ -89,7 +89,7 @@ ldfile_add_library_path(name)
char *name; char *name;
{ {
search_dirs_type *new = 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->name = name;
new->next = (search_dirs_type*)NULL; new->next = (search_dirs_type*)NULL;
*search_tail_ptr = new; *search_tail_ptr = new;
@ -160,41 +160,42 @@ open_a(arch, entry, lib, suffix)
void void
ldfile_open_file (entry) ldfile_open_file (entry)
lang_input_statement_type *entry; lang_input_statement_type *entry;
{ {
if (entry->superfile != NULL)
if (entry->superfile)
ldfile_open_file (entry->superfile); 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; search_arch_type *arch;
/* Try to open <filename><suffix> or lib<filename><suffix>.a */ /* Try to open <filename><suffix> or lib<filename><suffix>.a */
for (arch = search_arch_head; for (arch = search_arch_head;
arch != (search_arch_type *)NULL; arch != (search_arch_type *) NULL;
arch = arch->next) { arch = arch->next)
if (open_a(arch->name,entry,"lib",".a") != (bfd *)NULL) { {
return; 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 #ifdef VMS
if (open_a(arch->name,entry,":lib",".a") != (bfd *)NULL) { if (open_a (arch->name, entry, ":lib", ".a") != (bfd *) NULL)
return; return;
}
#endif #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); 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. */ /* Try to open NAME; if that fails, try NAME with EXTEN appended to it. */
static FILE * static FILE *
@ -264,6 +265,7 @@ char *name;
ldlex_input_stack = ldfile_find_command_file(name, ""); ldlex_input_stack = ldfile_find_command_file(name, "");
if (ldlex_input_stack == (FILE *)NULL) { 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); einfo("%P%F: cannot open linker script file %s: %E\n",name);
} }
lex_push_file(ldlex_input_stack, name); lex_push_file(ldlex_input_stack, name);
@ -316,7 +318,7 @@ ldfile_add_arch(name)
char *name; char *name;
{ {
search_arch_type *new = 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') { if (*name != '\0') {
@ -343,7 +345,7 @@ ldfile_add_arch (in_name)
{ {
char *name = buystring(in_name); char *name = buystring(in_name);
search_arch_type *new = 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; ldfile_output_machine_name = in_name;

View file

@ -72,9 +72,6 @@ boolean trace_file_tries;
instead of complaining if no input files are given. */ instead of complaining if no input files are given. */
boolean version_printed; boolean version_printed;
/* 1 => write load map. */
boolean write_map;
args_type command_line; args_type command_line;
ld_config_type config; ld_config_type config;
@ -93,11 +90,10 @@ static boolean multiple_common PARAMS ((struct bfd_link_info *,
bfd_vma)); bfd_vma));
static boolean add_to_set PARAMS ((struct bfd_link_info *, static boolean add_to_set PARAMS ((struct bfd_link_info *,
struct bfd_link_hash_entry *, struct bfd_link_hash_entry *,
unsigned int bitsize, bfd_reloc_code_real_type,
bfd *, asection *, bfd_vma)); bfd *, asection *, bfd_vma));
static boolean constructor_callback PARAMS ((struct bfd_link_info *, static boolean constructor_callback PARAMS ((struct bfd_link_info *,
boolean constructor, boolean constructor,
unsigned int bitsize,
const char *name, const char *name,
bfd *, asection *, bfd_vma)); bfd *, asection *, bfd_vma));
static boolean warning_callback PARAMS ((struct bfd_link_info *, static boolean warning_callback PARAMS ((struct bfd_link_info *,
@ -162,8 +158,8 @@ main (argc, argv)
/* Initialize the data about options. */ /* Initialize the data about options. */
trace_files = trace_file_tries = version_printed = false; trace_files = trace_file_tries = version_printed = false;
write_map = false;
config.build_constructors = true; config.build_constructors = true;
config.dynamic_link = false;
command_line.force_common_definition = false; command_line.force_common_definition = false;
link_info.callbacks = &link_callbacks; link_info.callbacks = &link_callbacks;
@ -195,6 +191,16 @@ main (argc, argv)
lang_has_input_file = false; lang_has_input_file = false;
parse_args (argc, argv); 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 /* This essentially adds another -L directory so this must be done after
the -L's in argv have been processed. */ the -L's in argv have been processed. */
set_scripts_dir (); set_scripts_dir ();
@ -213,10 +219,6 @@ main (argc, argv)
yyparse (); yyparse ();
} }
if (link_info.relocateable && command_line.relax)
{
einfo ("%P%F: -relax and -r may not be used together\n");
}
lang_final (); lang_final ();
if (lang_has_input_file == false) if (lang_has_input_file == false)
@ -296,7 +298,8 @@ main (argc, argv)
} }
else else
{ {
bfd_close (output_bfd); if (! bfd_close (output_bfd))
einfo ("%F%B: final close failed: %E\n", output_bfd);
} }
if (config.stats) if (config.stats)
@ -568,8 +571,8 @@ add_archive_element (info, abfd, name)
ldlang_add_file (input); ldlang_add_file (input);
if (write_map) if (config.map_file != (FILE *) NULL)
info_msg ("%s needed due to %T\n", abfd->filename, name); minfo ("%s needed due to %T\n", abfd->filename, name);
if (trace_files || trace_file_tries) if (trace_files || trace_file_tries)
info_msg ("%I\n", input); info_msg ("%I\n", input);
@ -664,15 +667,28 @@ multiple_common (info, name, obfd, otype, osize, nbfd, ntype, nsize)
/*ARGSUSED*/ /*ARGSUSED*/
static boolean 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_info *info;
struct bfd_link_hash_entry *h; struct bfd_link_hash_entry *h;
unsigned int bitsize; bfd_reloc_code_real_type reloc;
bfd *abfd; bfd *abfd;
asection *section; asection *section;
bfd_vma value; 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; return true;
} }
@ -682,10 +698,9 @@ add_to_set (info, h, bitsize, abfd, section, value)
adding an element to a set, but less general. */ adding an element to a set, but less general. */
static boolean static boolean
constructor_callback (info, constructor, bitsize, name, abfd, section, value) constructor_callback (info, constructor, name, abfd, section, value)
struct bfd_link_info *info; struct bfd_link_info *info;
boolean constructor; boolean constructor;
unsigned int bitsize;
const char *name; const char *name;
bfd *abfd; bfd *abfd;
asection *section; asection *section;
@ -698,6 +713,11 @@ constructor_callback (info, constructor, bitsize, name, abfd, section, value)
if (! config.build_constructors) if (! config.build_constructors)
return true; 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__"); set_name = (char *) alloca (1 + sizeof "__CTOR_LIST__");
s = set_name; s = set_name;
if (bfd_get_symbol_leading_char (abfd) != '\0') if (bfd_get_symbol_leading_char (abfd) != '\0')
@ -707,8 +727,9 @@ constructor_callback (info, constructor, bitsize, name, abfd, section, value)
else else
strcpy (s, "__DTOR_LIST__"); strcpy (s, "__DTOR_LIST__");
if (write_map) if (config.map_file != (FILE *) NULL)
info_msg ("Adding %s to constructor/destructor set %s\n", name, set_name); 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); h = bfd_link_hash_lookup (info->hash, set_name, true, true, true);
if (h == (struct bfd_link_hash_entry *) NULL) if (h == (struct bfd_link_hash_entry *) NULL)
@ -722,7 +743,7 @@ constructor_callback (info, constructor, bitsize, name, abfd, section, value)
ourselves. */ ourselves. */
} }
ldctor_add_set_entry (h, bitsize, section, value); ldctor_add_set_entry (h, BFD_RELOC_CTOR, section, value);
return true; return true;
} }
@ -790,8 +811,11 @@ reloc_overflow (info, name, reloc_name, addend, abfd, section, address)
asection *section; asection *section;
bfd_vma address; bfd_vma address;
{ {
einfo ("%X%C: relocation truncated to fit: %s %T", abfd, section, if (abfd == (bfd *) NULL)
address, reloc_name, name); einfo ("%P%X: generated");
else
einfo ("%X%C:", abfd, section, address);
einfo (" relocation truncated to fit: %s %T", reloc_name, name);
if (addend != 0) if (addend != 0)
einfo ("+%v", addend); einfo ("+%v", addend);
einfo ("\n"); einfo ("\n");
@ -809,7 +833,11 @@ reloc_dangerous (info, message, abfd, section, address)
asection *section; asection *section;
bfd_vma address; 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; return true;
} }
@ -825,8 +853,11 @@ unattached_reloc (info, name, abfd, section, address)
asection *section; asection *section;
bfd_vma address; bfd_vma address;
{ {
einfo ("%X%C: reloc refers to symbol `%T' which is not being output\n", if (abfd == (bfd *) NULL)
abfd, section, address, name); 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; return true;
} }

View file

@ -57,50 +57,53 @@ parse_args (argc, argv)
static struct option longopts[] = { static struct option longopts[] = {
#define OPTION_CALL_SHARED 150 #define OPTION_CALL_SHARED 150
#define OPTION_NON_SHARED 151
{"call_shared", no_argument, NULL, OPTION_CALL_SHARED}, {"call_shared", no_argument, NULL, OPTION_CALL_SHARED},
{"dc", no_argument, NULL, 'd'}, {"dc", no_argument, NULL, 'd'},
#define OPTION_DEFSYM 151 #define OPTION_DEFSYM 152
{"defsym", required_argument, NULL, OPTION_DEFSYM}, {"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'}, {"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}, {"EB", no_argument, NULL, OPTION_EB},
#define OPTION_EL 153 #define OPTION_EL 154
{"EL", no_argument, NULL, OPTION_EL}, {"EL", no_argument, NULL, OPTION_EL},
{"format", required_argument, NULL, 'b'}, {"format", required_argument, NULL, 'b'},
#define OPTION_HELP 154 #define OPTION_HELP 155
{"help", no_argument, NULL, OPTION_HELP}, {"help", no_argument, NULL, OPTION_HELP},
#define OPTION_MAP 155 #define OPTION_MAP 156
{"Map", required_argument, NULL, OPTION_MAP}, {"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}, {"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},
{"noinhibit_exec", no_argument, NULL, OPTION_NOINHIBIT_EXEC}, {"noinhibit_exec", no_argument, NULL, OPTION_NOINHIBIT_EXEC},
{"non_shared", no_argument, NULL, OPTION_CALL_SHARED}, {"non_shared", no_argument, NULL, OPTION_NON_SHARED},
#define OPTION_OFORMAT 158 #define OPTION_OFORMAT 159
{"oformat", required_argument, NULL, OPTION_OFORMAT}, {"oformat", required_argument, NULL, OPTION_OFORMAT},
{"Qy", no_argument, NULL, OPTION_CALL_SHARED}, #define OPTION_IGNORE 160
#define OPTION_RELAX 159 {"Qy", no_argument, NULL, OPTION_IGNORE},
#define OPTION_RELAX 161
{"relax", no_argument, NULL, OPTION_RELAX}, {"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}, {"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},
{"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}, {"stats", no_argument, NULL, OPTION_STATS},
#define OPTION_TBSS 163 #define OPTION_TBSS 165
{"Tbss", required_argument, NULL, OPTION_TBSS}, {"Tbss", required_argument, NULL, OPTION_TBSS},
#define OPTION_TDATA 164 #define OPTION_TDATA 166
{"Tdata", required_argument, NULL, OPTION_TDATA}, {"Tdata", required_argument, NULL, OPTION_TDATA},
#define OPTION_TTEXT 165 #define OPTION_TTEXT 167
{"Ttext", required_argument, NULL, OPTION_TTEXT}, {"Ttext", required_argument, NULL, OPTION_TTEXT},
#define OPTION_UR 166 #define OPTION_UR 168
{"Ur", no_argument, NULL, OPTION_UR}, {"Ur", no_argument, NULL, OPTION_UR},
#define OPTION_VERSION 167 #define OPTION_VERSION 169
{"version", no_argument, NULL, OPTION_VERSION}, {"version", no_argument, NULL, OPTION_VERSION},
#define OPTION_WARN_COMMON 168 #define OPTION_WARN_COMMON 170
{"warn-common", no_argument, NULL, OPTION_WARN_COMMON}, {"warn-common", no_argument, NULL, OPTION_WARN_COMMON},
{NULL, no_argument, NULL, 0} {NULL, no_argument, NULL, 0}
}; };
@ -124,6 +127,8 @@ parse_args (argc, argv)
(char *) NULL); (char *) NULL);
break; break;
case OPTION_IGNORE:
break;
case 'A': case 'A':
ldfile_add_arch (optarg); ldfile_add_arch (optarg);
break; break;
@ -139,7 +144,10 @@ parse_args (argc, argv)
yyparse (); yyparse ();
break; break;
case OPTION_CALL_SHARED: 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; break;
case 'd': case 'd':
command_line.force_common_definition = true; command_line.force_common_definition = true;
@ -194,7 +202,6 @@ parse_args (argc, argv)
/* Ignore. Was handled in a pre-parse. */ /* Ignore. Was handled in a pre-parse. */
break; break;
case OPTION_MAP: case OPTION_MAP:
write_map = true;
config.map_filename = optarg; config.map_filename = optarg;
break; break;
case 'N': case 'N':
@ -229,6 +236,7 @@ parse_args (argc, argv)
config.build_constructors = false; config.build_constructors = false;
config.magic_demand_paged = false; config.magic_demand_paged = false;
config.text_read_only = false; config.text_read_only = false;
config.dynamic_link = false;
break; break;
case 'R': case 'R':
lang_add_input_file (optarg, lang_add_input_file (optarg,
@ -275,6 +283,7 @@ parse_args (argc, argv)
config.build_constructors = true; config.build_constructors = true;
config.magic_demand_paged = false; config.magic_demand_paged = false;
config.text_read_only = false; config.text_read_only = false;
config.dynamic_link = false;
break; break;
case 'u': case 'u':
ldlang_add_undef (optarg); ldlang_add_undef (optarg);

View file

@ -8,12 +8,18 @@
# (e.g., .PARISC.global) # (e.g., .PARISC.global)
# EXECUTABLE_SYMBOLS - symbols that must be defined for an # EXECUTABLE_SYMBOLS - symbols that must be defined for an
# executable (e.g., _DYNAMIC_LINK) # 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 # OTHER_BSS_SYMBOLS - symbols that appear at the start of the
# .bss section besides __bss_start. # .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 adding sections, do note that the names of some sections are used
# when specifying the start address of the next. # when specifying the start address of the next.
# #
PLT=".plt ${RELOCATING-0} : { *(.plt) }"
cat <<EOF cat <<EOF
OUTPUT_FORMAT("${OUTPUT_FORMAT}") OUTPUT_FORMAT("${OUTPUT_FORMAT}")
OUTPUT_ARCH(${ARCH}) OUTPUT_ARCH(${ARCH})
@ -29,62 +35,58 @@ ${RELOCATING- /* For some reason, the Solaris linker makes bad executables
SECTIONS SECTIONS
{ {
/* Read-only sections, merged into text segment: */ /* 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) *(.text)
CREATE_OBJECT_SYMBOLS
${RELOCATING+_etext = .;}
} }
.init ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : { *(.init) } =${NOP-0} ${RELOCATING+_etext = .;}
.fini ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : { *(.fini) } =${NOP-0} .fini ${RELOCATING-0} : { *(.fini) } =${NOP-0}
.ctors ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : { *(.ctors) } .ctors ${RELOCATING-0} : { *(.ctors) }
.dtors ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : { *(.dtors) } .dtors ${RELOCATING-0} : { *(.dtors) }
.rodata ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : { *(.rodata) } .rodata ${RELOCATING-0} : { *(.rodata) }
.rodata1 ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : .rodata1 ${RELOCATING-0} : { *(.rodata1) }
{
*(.rodata1)
${RELOCATING+. = ALIGN(8);}
}
${RELOCATING+${OTHER_READONLY_SECTIONS}} ${RELOCATING+${OTHER_READONLY_SECTIONS}}
/* also: .hash .dynsym .dynstr .plt(if r/o) .rel.got */
/* Read-write section, merged into data segment: */ /* Read-write section, merged into data segment: */
.data ${RELOCATING+ ${RELOCATING+. = ${DATA_ADDR- ALIGN(8) + ${MAXPAGESIZE}};}
${DATA_ADDR- ADDR(.rodata1)+SIZEOF(.rodata1)+${MAXPAGESIZE}} .data ${RELOCATING-0} :
}
${RELOCATING-0} :
{ {
${RELOCATING+${DATA_START_SYMBOLS}}
*(.data) *(.data)
${CONSTRUCTING+CONSTRUCTORS} ${CONSTRUCTING+CONSTRUCTORS}
} }
.data1 ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : { *(.data1) } .data1 ${RELOCATING-0} : { *(.data1) }
${RELOCATING+${OTHER_READWRITE_SECTIONS}} ${RELOCATING+${OTHER_READWRITE_SECTIONS}}
/* also (before uninitialized portion): .dynamic .got .plt(if r/w) .got ${RELOCATING-0} : { *(.got) }
(or does .dynamic go into its own segment?) */ .dynamic ${RELOCATING-0} : { *(.dynamic) }
${DATA_PLT+${PLT}}
/* We want the small data sections together, so single-instruction offsets /* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */ we can shorten the on-disk segment size. */
.sdata ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : { *(.sdata) } .sdata ${RELOCATING-0} : { *(.sdata) }
${RELOCATING+_edata = .;} ${RELOCATING+_edata = .;}
${RELOCATING+__bss_start = ALIGN(8);} ${RELOCATING+__bss_start = .;}
${RELOCATING+${OTHER_BSS_SYMBOLS}} ${RELOCATING+${OTHER_BSS_SYMBOLS}}
.sbss ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : { *(.sbss) *(.scommon) } .sbss ${RELOCATING-0} : { *(.sbss) *(.scommon) }
.bss ${RELOCATING+ALIGN(8)} ${RELOCATING-0} : .bss ${RELOCATING-0} :
{ {
*(.dynbss)
*(.bss) *(.bss)
*(COMMON) *(COMMON)
${RELOCATING+_end = . };
${RELOCATING+end = . };
} }
${RELOCATING+_end = . ;}
/* Debug sections. These should never be loadable, but they must have ${RELOCATING+end = . ;}
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) }
} }
EOF EOF