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:
parent
013dec1ad9
commit
2a9fa50cd8
9 changed files with 410 additions and 170 deletions
28
ld/ChangeLog
28
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.
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -25,6 +25,7 @@ Do-first:
|
|||
Things-to-keep:
|
||||
|
||||
README
|
||||
elf32.em
|
||||
generic.em
|
||||
gld960.em
|
||||
gld960c.em
|
||||
|
|
196
ld/emultempl/elf32.em
Normal file
196
ld/emultempl/elf32.em
Normal 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
85
ld/ld.h
|
@ -18,66 +18,41 @@
|
|||
along with GLD; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#ifndef LD_H
|
||||
#define LD_H
|
||||
|
||||
#define flag_is_not_at_end(x) ((x) & BSF_NOT_AT_END)
|
||||
#define flag_is_ordinary_local(x) (((x) & (BSF_LOCAL))&!((x) & (BSF_DEBUGGING)))
|
||||
#define flag_is_debugger(x) ((x) & BSF_DEBUGGING)
|
||||
#define flag_is_undefined_or_global(x) ((x) & (BSF_UNDEFINED | BSF_GLOBAL))
|
||||
#define flag_is_defined(x) (!((x) & (BSF_UNDEFINED)))
|
||||
#define flag_is_global_or_common(x) ((x) & (BSF_GLOBAL | BSF_FORT_COMM))
|
||||
#define flag_is_undefined_or_global_or_common(x) ((x) & (BSF_UNDEFINED | BSF_GLOBAL | BSF_FORT_COMM))
|
||||
#define flag_is_undefined_or_global_or_common_or_constructor(x) ((x) & (BSF_UNDEFINED | BSF_GLOBAL | BSF_FORT_COMM | BSF_CONSTRUCTOR))
|
||||
#define flag_is_constructor(x) ((x) & BSF_CONSTRUCTOR)
|
||||
#define flag_is_common(x) ((x) & BSF_FORT_COMM)
|
||||
#define flag_is_global(x) ((x) & (BSF_GLOBAL))
|
||||
#define flag_is_weak(x) ((x) & BSF_WEAK)
|
||||
#define flag_is_undefined(x) ((x) & BSF_UNDEFINED)
|
||||
#define flag_set(x,y) (x = y)
|
||||
#define flag_is_fort_comm(x) ((x) & BSF_FORT_COMM)
|
||||
#define flag_is_absolute(x) ((x) & BSF_ABSOLUTE)
|
||||
/* Extra information we hold on sections */
|
||||
typedef struct user_section_struct {
|
||||
typedef struct user_section_struct
|
||||
{
|
||||
/* Pointer to the section where this data will go */
|
||||
struct lang_input_statement_struct *file;
|
||||
} section_userdata_type;
|
||||
|
||||
|
||||
#define get_userdata(x) ((x)->userdata)
|
||||
#define as_output_section_statement(x) ((x)->otheruserdata)
|
||||
|
||||
|
||||
|
||||
/* Which symbols should be stripped (omitted from the output):
|
||||
none, all, or debugger symbols. */
|
||||
typedef enum { STRIP_NONE, STRIP_ALL, STRIP_DEBUGGER, STRIP_SOME } strip_symbols_type;
|
||||
|
||||
|
||||
|
||||
|
||||
/* Which local symbols should be omitted:
|
||||
none, all, or those starting with L.
|
||||
This is irrelevant if STRIP_NONE. */
|
||||
typedef enum { DISCARD_NONE, DISCARD_ALL, DISCARD_L } discard_locals_type;
|
||||
|
||||
|
||||
#define BYTE_SIZE (1)
|
||||
#define SHORT_SIZE (2)
|
||||
#define LONG_SIZE (4)
|
||||
#define QUAD_SIZE (8)
|
||||
|
||||
/* ALIGN macro changed to ALIGN_N to avoid */
|
||||
/* conflict in /usr/include/machine/machparam.h */
|
||||
/* WARNING: If THIS is a 64 bit address and BOUNDARY is an unsigned int,
|
||||
/* WARNING: If THIS is a 64 bit address and BOUNDARY is a 32 bit int,
|
||||
you must coerce boundary to the same type as THIS.
|
||||
??? Is there a portable way to avoid this. */
|
||||
#define ALIGN_N(this, boundary) ((( (this) + ((boundary) -1)) & (~((boundary)-1))))
|
||||
#define ALIGN_N(this, boundary) \
|
||||
((( (this) + ((boundary) -1)) & (~((boundary)-1))))
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
/* 1 => assign space to common symbols even if `relocatable_output'. */
|
||||
boolean force_common_definition;
|
||||
boolean relax;
|
||||
|
||||
} args_type;
|
||||
|
||||
extern args_type command_line;
|
||||
|
||||
typedef int token_code_type;
|
||||
|
||||
typedef struct
|
||||
|
@ -85,41 +60,37 @@ typedef struct
|
|||
bfd_size_type specified_data_size;
|
||||
boolean magic_demand_paged;
|
||||
boolean make_executable;
|
||||
/* 1 => write relocation into output file so can re-input it later. */
|
||||
boolean relocateable_output;
|
||||
|
||||
/* Will we build contstructors, or leave alone ? */
|
||||
/* If true, doing a dynamic link. */
|
||||
boolean dynamic_link;
|
||||
|
||||
boolean build_constructors;
|
||||
|
||||
/* If true, warn about merging common symbols with others. */
|
||||
boolean warn_common;
|
||||
|
||||
boolean sort_common;
|
||||
/* these flags may seem mutually exclusive, but not setting them
|
||||
allows the back end to decide what would be the best thing to do */
|
||||
|
||||
boolean text_read_only;
|
||||
|
||||
char *map_filename;
|
||||
FILE *map_file;
|
||||
char *map_filename;
|
||||
FILE *map_file;
|
||||
|
||||
boolean stats;
|
||||
} ld_config_type;
|
||||
#define set_asymbol_chain(x,y) ((x)->udata = (PTR)y)
|
||||
#define get_asymbol_chain(x) ((asymbol **)((x)->udata))
|
||||
#define get_loader_symbol(x) ((loader_global_asymbol *)((x)->udata))
|
||||
#define set_loader_symbol(x,y) ((x)->udata = (PTR)y)
|
||||
|
||||
extern ld_config_type config;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
lang_first_phase_enum,
|
||||
lang_allocating_phase_enum,
|
||||
lang_final_phase_enum } lang_phase_type;
|
||||
lang_final_phase_enum
|
||||
} lang_phase_type;
|
||||
|
||||
extern boolean had_script;
|
||||
extern boolean force_make_executable;
|
||||
|
||||
extern int yyparse PARAMS ((void));
|
||||
|
||||
|
||||
|
||||
int yyparse();
|
||||
#endif
|
||||
|
|
54
ld/ldfile.c
54
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;
|
||||
|
||||
|
|
83
ld/ldmain.c
83
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;
|
||||
}
|
||||
|
||||
|
|
55
ld/lexsup.c
55
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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue