Merge changes from gnu/dist/ld.
This commit is contained in:
parent
cbef3ca9f3
commit
6e4a918853
|
@ -139,6 +139,8 @@ ALL_EMULATIONS = \
|
|||
eelf32lppc.o \
|
||||
eelf32ppc.o \
|
||||
eelf32ppclinux.o \
|
||||
eelf32shlunx.o \
|
||||
eelf32shunx.o \
|
||||
eelf_i386.o \
|
||||
eelf_i386_be.o \
|
||||
egld960.o \
|
||||
|
@ -201,8 +203,10 @@ ALL_EMULATIONS = \
|
|||
esh.o \
|
||||
eshelf.o \
|
||||
eshlelf.o \
|
||||
eshlunx.o \
|
||||
eshl.o \
|
||||
eshpe.o \
|
||||
eshunx.o \
|
||||
esparcaout.o \
|
||||
esparclinux.o \
|
||||
esparclynx.o \
|
||||
|
@ -636,6 +640,18 @@ eshl.c: $(srcdir)/emulparams/shl.sh \
|
|||
eshpe.c: $(srcdir)/emulparams/shpe.sh \
|
||||
$(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
|
||||
${GENSCRIPTS} shpe "$(tdir_shl)"
|
||||
eshunx.c: $(srcdir)/emulparams/shunx.sh \
|
||||
$(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/sh.sc ${GEN_DEPENDS}
|
||||
${GENSCRIPTS} shunx "$(tdir_shunx)"
|
||||
eshlunx.c: $(srcdir)/emulparams/shlunx.sh \
|
||||
$(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/shunx.sc ${GEN_DEPENDS}
|
||||
${GENSCRIPTS} shlunx "$(tdir_shlunx)"
|
||||
eelf32shunx.c: $(srcdir)/emulparams/elf32shunx.sh \
|
||||
$(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
|
||||
${GENSCRIPTS} elf32shunx "$(tdir_elf32shunx)"
|
||||
eelf32shlunx.c: $(srcdir)/emulparams/elf32shlunx.sh \
|
||||
$(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
|
||||
${GENSCRIPTS} elf32shlunx "$(tdir_elf32shlunx)"
|
||||
esparcaout.c: $(srcdir)/emulparams/sparcaout.sh \
|
||||
$(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS}
|
||||
${GENSCRIPTS} sparcaout "$(tdir_sparcaout)"
|
||||
|
|
|
@ -242,6 +242,8 @@ ALL_EMULATIONS = \
|
|||
eelf32lppc.o \
|
||||
eelf32ppc.o \
|
||||
eelf32ppclinux.o \
|
||||
eelf32shlunx.o \
|
||||
eelf32shunx.o \
|
||||
eelf_i386.o \
|
||||
eelf_i386_be.o \
|
||||
egld960.o \
|
||||
|
@ -304,8 +306,10 @@ ALL_EMULATIONS = \
|
|||
esh.o \
|
||||
eshelf.o \
|
||||
eshlelf.o \
|
||||
eshlunx.o \
|
||||
eshl.o \
|
||||
eshpe.o \
|
||||
eshunx.o \
|
||||
esparcaout.o \
|
||||
esparclinux.o \
|
||||
esparclynx.o \
|
||||
|
@ -1335,6 +1339,18 @@ eshl.c: $(srcdir)/emulparams/shl.sh \
|
|||
eshpe.c: $(srcdir)/emulparams/shpe.sh \
|
||||
$(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
|
||||
${GENSCRIPTS} shpe "$(tdir_shl)"
|
||||
eshunx.c: $(srcdir)/emulparams/shunx.sh \
|
||||
$(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/sh.sc ${GEN_DEPENDS}
|
||||
${GENSCRIPTS} shunx "$(tdir_shunx)"
|
||||
eshlunx.c: $(srcdir)/emulparams/shlunx.sh \
|
||||
$(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/shunx.sc ${GEN_DEPENDS}
|
||||
${GENSCRIPTS} shlunx "$(tdir_shlunx)"
|
||||
eelf32shunx.c: $(srcdir)/emulparams/elf32shunx.sh \
|
||||
$(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
|
||||
${GENSCRIPTS} elf32shunx "$(tdir_elf32shunx)"
|
||||
eelf32shlunx.c: $(srcdir)/emulparams/elf32shlunx.sh \
|
||||
$(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
|
||||
${GENSCRIPTS} elf32shlunx "$(tdir_elf32shlunx)"
|
||||
esparcaout.c: $(srcdir)/emulparams/sparcaout.sh \
|
||||
$(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS}
|
||||
${GENSCRIPTS} sparcaout "$(tdir_sparcaout)"
|
||||
|
|
|
@ -21,7 +21,7 @@ alpha*-*-linux-gnu*)
|
|||
HOSTING_LIBS='`if [ -f ../gcc/libgcc.a ] ; then echo ../gcc/libgcc.a ; else ${CC} -print-libgcc-file-name; fi` -L`dirname \`${CC} --print-file-name=libc.so\`` -lc `if [ -f ../gcc/libgcc.a ] ; then echo ../gcc/libgcc.a ; else ${CC} -print-libgcc-file-name; fi` `if [ -f ../gcc/crtend.o ]; then echo ../gcc/crtend.o; else ${CC} --print-file-name=crtend.o; fi` `${CC} --print-file-name=crtn.o`'
|
||||
;;
|
||||
|
||||
alpha*-*-netbsd*)
|
||||
*-*-netbsd*)
|
||||
# The new BSD `make' has a bug: it doesn't pass empty arguments in
|
||||
# shell commands. So we need to make this value non-empty in order
|
||||
# for the genscripts.sh call to work. There's nothing magic about
|
||||
|
@ -54,7 +54,7 @@ i[3456]86-*-freebsdelf*)
|
|||
HOSTING_LIBS='`if [ -f ../gcc/libgcc.a ] ; then echo ../gcc/libgcc.a ; else ${CC} -print-libgcc-file-name; fi` -L`dirname \`${CC} --print-file-name=libc.so\`` -lc `if [ -f ../gcc/libgcc.a ] ; then echo ../gcc/libgcc.a ; else ${CC} -print-libgcc-file-name; fi` `if [ -f ../gcc/crtend.o ]; then echo ../gcc/crtend.o; else ${CC} --print-file-name=crtend.o; fi` `${CC} --print-file-name=crtn.o`'
|
||||
;;
|
||||
|
||||
i[3456]86-*-bsd* | i[3456]86-*-freebsd* | i[3456]86-*-netbsd*)
|
||||
i[3456]86-*-bsd* | i[3456]86-*-freebsd*)
|
||||
# The new BSD `make' has a bug: it doesn't pass empty arguments in
|
||||
# shell commands. So we need to make this value non-empty in order
|
||||
# for the genscripts.sh call to work. There's nothing magic about
|
||||
|
|
|
@ -56,7 +56,7 @@ sparc*-*-linux-gnu*) targ_emul=elf32_sparc
|
|||
;;
|
||||
sparc*-*-lynxos*) targ_emul=sparclynx ;;
|
||||
sparc64-*-netbsd*) targ_emul=elf64_sparc ;;
|
||||
sparc*-*-netbsd*elf*) targ_emul=elf32_sparc ;;
|
||||
sparc*-*-netbsdelf*) targ_emul=elf32_sparc ;;
|
||||
sparc*-*-netbsd*) targ_emul=sparcnbsd ;;
|
||||
sparc-*-solaris2.[0-6] | sparc-*-solaris2.[0-6].*)
|
||||
targ_emul=elf32_sparc ;;
|
||||
|
@ -122,6 +122,7 @@ i[3456]86-*-sysv4*) targ_emul=elf_i386 ;;
|
|||
i[3456]86-*-solaris2*) targ_emul=elf_i386 ;;
|
||||
i[3456]86-*-unixware) targ_emul=elf_i386 ;;
|
||||
i[3456]86-*-solaris*) targ_emul=elf_i386 ;;
|
||||
i[3456]86-*-netbsdelf*) targ_emul=elf_i386 ;;
|
||||
i[3456]86-*-netbsd*) targ_emul=i386nbsd ;;
|
||||
i[3456]86-*-netware) targ_emul=i386nw ;;
|
||||
i[3456]86-*-elf*) targ_emul=elf_i386 ;;
|
||||
|
@ -203,7 +204,8 @@ m68k-*-linux-gnu*) targ_emul=m68kelf
|
|||
;;
|
||||
m68*-*-gnu*) targ_emul=m68kelf ;;
|
||||
m68*-*-lynxos*) targ_emul=m68klynx ;;
|
||||
m68*-hp*-netbsd*) targ_emul=m68k4knbsd ;;
|
||||
m68k4k-*-netbsd*) targ_emul=m68k4knbsd ;;
|
||||
m68*-*-netbsdelf*) targ_emul=m68kelf ;;
|
||||
m68*-*-netbsd*) targ_emul=m68knbsd ;;
|
||||
m68*-*-psos*) targ_emul=m68kpsos ;;
|
||||
m68*-*-rtemscoff*) targ_emul=m68kcoff ;;
|
||||
|
@ -227,7 +229,8 @@ mips*-sgi-irix*) targ_emul=mipsbig ;;
|
|||
mips*el-*-ecoff*) targ_emul=mipsidtl ;;
|
||||
mips*-*-ecoff*) targ_emul=mipsidt ;;
|
||||
mips*-dec-bsd*) targ_emul=mipsbsd ;;
|
||||
mips*-dec-netbsd*) targ_emul=elf32lmip ;;
|
||||
mips*el*-*-netbsd*) targ_emul=elf32lmip ;;
|
||||
mips*eb*-*-netbsd*) targ_emul=elf32bmip ;;
|
||||
mips*-*-bsd*) targ_emul=mipsbig ;;
|
||||
mips*vr4300el-*-elf*) targ_emul=elf32l4300 ;;
|
||||
mips*vr4300-*-elf*) targ_emul=elf32b4300 ;;
|
||||
|
@ -263,7 +266,7 @@ alpha*-*-netware*) targ_emul=alpha ;;
|
|||
alpha*-*-netbsd*) targ_emul=elf64alpha ;;
|
||||
z8k-*-coff) targ_emul=z8002; targ_extra_emuls=z8001 ;;
|
||||
ns32k-pc532-mach* | ns32k-pc532-ux*) targ_emul=pc532macha ;;
|
||||
ns32k-pc532-netbsd* | ns32k-pc532-lites*) targ_emul=ns32knbsd ;;
|
||||
ns32k-*-netbsd* | ns32k-pc532-lites*) targ_emul=ns32knbsd ;;
|
||||
powerpc-*-linux-gnu*) targ_emul=elf32ppclinux; targ_extra_emuls=elf32ppc;
|
||||
targ_extra_libpath=elf32ppc ;;
|
||||
pjl*-*-*) targ_emul=pjlelf ; targ_extra_emuls="elf_i386" ;;
|
||||
|
|
|
@ -9,3 +9,4 @@ MACHINE=
|
|||
TEMPLATE_NAME=elf32
|
||||
DATA_PLT=
|
||||
GENERATE_SHLIB_SCRIPT=yes
|
||||
ELFSIZE=32
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
SCRIPT_NAME=elf
|
||||
OUTPUT_FORMAT="elf32-shl-unx"
|
||||
TEXT_START_ADDR=0x1000
|
||||
MAXPAGESIZE=0x1000
|
||||
ARCH=sh
|
||||
MACHINE=
|
||||
TEMPLATE_NAME=elf32
|
||||
GENERATE_SHLIB_SCRIPT=yes
|
||||
|
||||
# These are for compatibility with the COFF toolchain.
|
||||
ENTRY=start
|
||||
CTOR_START='___ctors = .;'
|
||||
CTOR_END='___ctors_end = .;'
|
||||
DTOR_START='___dtors = .;'
|
||||
DTOR_END='___dtors_end = .;'
|
|
@ -0,0 +1,15 @@
|
|||
SCRIPT_NAME=elf
|
||||
OUTPUT_FORMAT="elf32-sh-unx"
|
||||
TEXT_START_ADDR=0x1000
|
||||
MAXPAGESIZE=0x1000
|
||||
ARCH=sh
|
||||
MACHINE=
|
||||
TEMPLATE_NAME=elf32
|
||||
GENERATE_SHLIB_SCRIPT=yes
|
||||
|
||||
# These are for compatibility with the COFF toolchain.
|
||||
ENTRY=start
|
||||
CTOR_START='___ctors = .;'
|
||||
CTOR_END='___ctors_end = .;'
|
||||
DTOR_START='___dtors = .;'
|
||||
DTOR_END='___dtors_end = .;'
|
|
@ -8,3 +8,4 @@ MACHINE=
|
|||
NOP=0x9090
|
||||
TEMPLATE_NAME=elf32
|
||||
GENERATE_SHLIB_SCRIPT=yes
|
||||
ELFSIZE=32
|
||||
|
|
|
@ -3,4 +3,4 @@ TEXT_START_ADDR=0x1020
|
|||
OUTPUT_FORMAT="a.out-i386-netbsd"
|
||||
TARGET_PAGE_SIZE=0x1000
|
||||
ARCH=i386
|
||||
EXECUTABLE_SYMBOLS='__DYNAMIC = 0;'
|
||||
TEMPLATE_NAME=netbsdaout
|
||||
|
|
|
@ -8,3 +8,4 @@ MACHINE=
|
|||
NOP=0x4e75
|
||||
TEMPLATE_NAME=elf32
|
||||
GENERATE_SHLIB_SCRIPT=yes
|
||||
ELFSIZE=32
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
SCRIPT_NAME=sh
|
||||
OUTPUT_FORMAT="coff-sh"
|
||||
TEXT_START_ADDR=0x8000
|
||||
TARGET_PAGE_SIZE=128
|
||||
TEXT_START_ADDR=0x1000
|
||||
TARGET_PAGE_SIZE=0x1000
|
||||
ARCH=sh
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
SCRIPT_NAME=elf
|
||||
OUTPUT_FORMAT="elf32-sh"
|
||||
TEXT_START_ADDR=0x1000
|
||||
MAXPAGESIZE=128
|
||||
MAXPAGESIZE=0x1000
|
||||
ARCH=sh
|
||||
MACHINE=
|
||||
TEMPLATE_NAME=elf32
|
||||
GENERATE_SHLIB_SCRIPT=yes
|
||||
EMBEDDED=yes
|
||||
|
||||
# These are for compatibility with the COFF toolchain.
|
||||
ENTRY=start
|
||||
|
@ -14,4 +13,3 @@ CTOR_START='___ctors = .;'
|
|||
CTOR_END='___ctors_end = .;'
|
||||
DTOR_START='___dtors = .;'
|
||||
DTOR_END='___dtors_end = .;'
|
||||
OTHER_RELOCATING_SECTIONS='.stack 0x30000 : { _stack = .; *(.stack) }'
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
SCRIPT_NAME=shunx
|
||||
OUTPUT_FORMAT="coff-shl"
|
||||
TEXT_START_ADDR=0x1000
|
||||
TARGET_PAGE_SIZE=0x1000
|
||||
ARCH=sh
|
|
@ -0,0 +1,5 @@
|
|||
SCRIPT_NAME=shunx
|
||||
OUTPUT_FORMAT="coff-sh"
|
||||
TEXT_START_ADDR=0x1000
|
||||
TARGET_PAGE_SIZE=0x1000
|
||||
ARCH=sh
|
|
@ -1,5 +1,5 @@
|
|||
SCRIPT_NAME=aout
|
||||
TEXT_START_ADDR=0x1020
|
||||
TEXT_START_ADDR=0x2020
|
||||
OUTPUT_FORMAT="a.out-sparc-netbsd"
|
||||
TARGET_PAGE_SIZE=0x1000
|
||||
TARGET_PAGE_SIZE=0x2000
|
||||
ARCH=sparc
|
||||
|
|
|
@ -0,0 +1,974 @@
|
|||
# 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! */
|
||||
|
||||
/* NetBSD emulation code for ${EMULATION_NAME}
|
||||
Copyright (C) 1991, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
|
||||
Written by Steve Chamberlain <sac@cygnus.com>
|
||||
SunOS shared library support by Ian Lance Taylor <ian@cygnus.com>
|
||||
NetBSD changes by Krister Walfridsson <cato@df.lth.se>
|
||||
|
||||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#define TARGET_IS_${EMULATION_NAME}
|
||||
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "bfd.h"
|
||||
#include "sysdep.h"
|
||||
#include "bfdlink.h"
|
||||
#include "libiberty.h"
|
||||
|
||||
#include "ld.h"
|
||||
#include "ldmain.h"
|
||||
#include "ldemul.h"
|
||||
#include "ldfile.h"
|
||||
#include "ldmisc.h"
|
||||
#include "ldexp.h"
|
||||
#include "ldlang.h"
|
||||
|
||||
#ifdef HAVE_DIRENT_H
|
||||
# include <dirent.h>
|
||||
#else
|
||||
# define dirent direct
|
||||
# ifdef HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# ifdef HAVE_SYS_DIR_H
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# ifdef HAVE_NDIR_H
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
|
||||
static void gld${EMULATION_NAME}_set_symbols PARAMS ((void));
|
||||
static void gld${EMULATION_NAME}_create_output_section_statements
|
||||
PARAMS ((void));
|
||||
static void gld${EMULATION_NAME}_find_so
|
||||
PARAMS ((lang_input_statement_type *));
|
||||
static char *gld${EMULATION_NAME}_search_dir
|
||||
PARAMS ((const char *, const char *, boolean *));
|
||||
static void gld${EMULATION_NAME}_after_open PARAMS ((void));
|
||||
static void gld${EMULATION_NAME}_check_needed
|
||||
PARAMS ((lang_input_statement_type *));
|
||||
static boolean gld${EMULATION_NAME}_search_needed
|
||||
PARAMS ((const char *, const char *));
|
||||
static boolean gld${EMULATION_NAME}_try_needed
|
||||
PARAMS ((const char *, const char *));
|
||||
static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
|
||||
static void gld${EMULATION_NAME}_find_assignment
|
||||
PARAMS ((lang_statement_union_type *));
|
||||
static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *));
|
||||
static void gld${EMULATION_NAME}_count_need
|
||||
PARAMS ((lang_input_statement_type *));
|
||||
static void gld${EMULATION_NAME}_set_need
|
||||
PARAMS ((lang_input_statement_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 command line arguments have been parsed,
|
||||
but before the linker script has been read. If this is a native
|
||||
linker, we add the directories in LD_LIBRARY_PATH to the search
|
||||
list. */
|
||||
|
||||
static void
|
||||
gld${EMULATION_NAME}_set_symbols ()
|
||||
{
|
||||
EOF
|
||||
if [ "x${host}" = "x${target}" ] ; then
|
||||
if [ "x${DEFAULT_EMULATION}" = "x${EMULATION_NAME}" ] ; then
|
||||
cat >>e${EMULATION_NAME}.c <<EOF
|
||||
const char *env;
|
||||
|
||||
env = (const char *) getenv ("LD_LIBRARY_PATH");
|
||||
if (env != NULL)
|
||||
{
|
||||
char *l;
|
||||
|
||||
l = xstrdup (env);
|
||||
while (1)
|
||||
{
|
||||
char *c;
|
||||
|
||||
c = strchr (l, ':');
|
||||
if (c != NULL)
|
||||
*c++ = '\0';
|
||||
if (*l != '\0')
|
||||
ldfile_add_library_path (l, false);
|
||||
if (c == NULL)
|
||||
break;
|
||||
l = c;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
cat >>e${EMULATION_NAME}.c <<EOF
|
||||
}
|
||||
|
||||
/* Despite the name, we use this routine to search for dynamic
|
||||
libraries. On NetBSD this requires a directory search. We need to
|
||||
find the .so file with the highest version number. The user may
|
||||
restrict the major version by saying, e.g., -lc.1. */
|
||||
|
||||
static void
|
||||
gld${EMULATION_NAME}_create_output_section_statements ()
|
||||
{
|
||||
lang_for_each_input_file (gld${EMULATION_NAME}_find_so);
|
||||
}
|
||||
|
||||
/* Search the directory for a .so file for each library search. */
|
||||
|
||||
static void
|
||||
gld${EMULATION_NAME}_find_so (inp)
|
||||
lang_input_statement_type *inp;
|
||||
{
|
||||
search_dirs_type *search;
|
||||
char *found;
|
||||
char *alc;
|
||||
struct stat st;
|
||||
|
||||
if (! inp->search_dirs_flag
|
||||
|| ! inp->is_archive
|
||||
|| ! inp->dynamic)
|
||||
return;
|
||||
|
||||
ASSERT (strncmp (inp->local_sym_name, "-l", 2) == 0);
|
||||
|
||||
for (search = search_head; search != NULL; search = search->next)
|
||||
{
|
||||
boolean found_static;
|
||||
|
||||
found = gld${EMULATION_NAME}_search_dir (search->name, inp->filename,
|
||||
&found_static);
|
||||
if (found != NULL || found_static)
|
||||
break;
|
||||
}
|
||||
|
||||
if (found == NULL)
|
||||
{
|
||||
/* We did not find a matching .so file. This isn't an error,
|
||||
since there might still be a matching .a file, which will be
|
||||
found by the usual search. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Replace the filename with the one we have found. */
|
||||
alc = (char *) xmalloc (strlen (search->name) + strlen (found) + 2);
|
||||
sprintf (alc, "%s/%s", search->name, found);
|
||||
inp->filename = alc;
|
||||
|
||||
/* We are only interested in the symbols. */
|
||||
inp->just_syms_flag = true;
|
||||
|
||||
/* Turn off the search_dirs_flag to prevent ldfile_open_file from
|
||||
searching for this file again. */
|
||||
inp->search_dirs_flag = false;
|
||||
|
||||
free (found);
|
||||
}
|
||||
|
||||
/* Search a directory for a .so file. */
|
||||
|
||||
static char *
|
||||
gld${EMULATION_NAME}_search_dir (dirname, filename, found_static)
|
||||
const char *dirname;
|
||||
const char *filename;
|
||||
boolean *found_static;
|
||||
{
|
||||
int force_maj, force_min;
|
||||
const char *dot;
|
||||
unsigned int len;
|
||||
char *alc;
|
||||
char *found;
|
||||
int max_maj, max_min;
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
|
||||
*found_static = false;
|
||||
|
||||
force_maj = -1;
|
||||
force_min = -1;
|
||||
dot = strchr (filename, '.');
|
||||
if (dot == NULL)
|
||||
{
|
||||
len = strlen (filename);
|
||||
alc = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
force_maj = atoi (dot + 1);
|
||||
|
||||
len = dot - filename;
|
||||
alc = (char *) xmalloc (len + 1);
|
||||
strncpy (alc, filename, len);
|
||||
alc[len] = '\0';
|
||||
filename = alc;
|
||||
|
||||
dot = strchr (dot + 1, '.');
|
||||
if (dot != NULL)
|
||||
force_min = atoi (dot + 1);
|
||||
}
|
||||
|
||||
found = NULL;
|
||||
max_maj = max_min = 0;
|
||||
|
||||
dir = opendir (dirname);
|
||||
if (dir == NULL)
|
||||
return NULL;
|
||||
|
||||
while ((entry = readdir (dir)) != NULL)
|
||||
{
|
||||
const char *s;
|
||||
int found_maj, found_min;
|
||||
|
||||
if (strncmp (entry->d_name, "lib", 3) != 0
|
||||
|| strncmp (entry->d_name + 3, filename, len) != 0)
|
||||
continue;
|
||||
|
||||
if (dot == NULL
|
||||
&& strcmp (entry->d_name + 3 + len, ".a") == 0)
|
||||
{
|
||||
*found_static = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We accept libfoo.so without a version number, even though the
|
||||
native linker does not. This is more convenient for packages
|
||||
which just generate .so files for shared libraries, as on ELF
|
||||
systems. */
|
||||
if (strncmp (entry->d_name + 3 + len, ".so", 3) != 0)
|
||||
continue;
|
||||
if (entry->d_name[6 + len] == '\0')
|
||||
;
|
||||
else if (entry->d_name[6 + len] == '.'
|
||||
&& isdigit (entry->d_name[7 + len]))
|
||||
;
|
||||
else
|
||||
continue;
|
||||
|
||||
for (s = entry->d_name + 6 + len; *s != '\0'; s++)
|
||||
if (*s != '.' && ! isdigit (*s))
|
||||
break;
|
||||
if (*s != '\0')
|
||||
continue;
|
||||
|
||||
/* We've found a .so file. Work out the major and minor
|
||||
version numbers. */
|
||||
found_maj = 0;
|
||||
found_min = 0;
|
||||
sscanf (entry->d_name + 3 + len, ".so.%d.%d",
|
||||
&found_maj, &found_min);
|
||||
|
||||
if ((force_maj != -1 && force_maj != found_maj)
|
||||
|| (force_min != -1 && force_min != found_min))
|
||||
continue;
|
||||
|
||||
/* We've found a match for the name we are searching for. See
|
||||
if this is the version we should use. If the major and minor
|
||||
versions match, we use the last entry in alphabetical order. */
|
||||
if (found == NULL
|
||||
|| (found_maj > max_maj)
|
||||
|| (found_maj == max_maj
|
||||
&& (found_min > max_min
|
||||
|| (found_min == max_min
|
||||
&& strcmp (entry->d_name, found) > 0))))
|
||||
{
|
||||
if (found != NULL)
|
||||
free (found);
|
||||
found = (char *) xmalloc (strlen (entry->d_name) + 1);
|
||||
strcpy (found, entry->d_name);
|
||||
max_maj = found_maj;
|
||||
max_min = found_min;
|
||||
}
|
||||
}
|
||||
|
||||
closedir (dir);
|
||||
|
||||
if (alc != NULL)
|
||||
free (alc);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/* These variables are required to pass information back and forth
|
||||
between after_open and check_needed. */
|
||||
|
||||
static struct bfd_link_needed_list *global_needed;
|
||||
static boolean global_found;
|
||||
|
||||
/* This is called after all the input files have been opened. */
|
||||
|
||||
static void
|
||||
gld${EMULATION_NAME}_after_open ()
|
||||
{
|
||||
struct bfd_link_needed_list *needed, *l;
|
||||
|
||||
/* We only need to worry about this when doing a final link. */
|
||||
if (link_info.relocateable || link_info.shared)
|
||||
return;
|
||||
|
||||
/* Get the list of files which appear in ld_need entries in dynamic
|
||||
objects included in the link. For each such file, we want to
|
||||
track down the corresponding library, and include the symbol
|
||||
table in the link. This is what the runtime dynamic linker will
|
||||
do. Tracking the files down here permits one dynamic object to
|
||||
include another without requiring special action by the person
|
||||
doing the link. Note that the needed list can actually grow
|
||||
while we are stepping through this loop. */
|
||||
needed = bfd_netbsd_get_needed_list (output_bfd, &link_info);
|
||||
for (l = needed; l != NULL; l = l->next)
|
||||
{
|
||||
struct bfd_link_needed_list *ll;
|
||||
const char *lname;
|
||||
search_dirs_type *search;
|
||||
|
||||
lname = l->name;
|
||||
|
||||
/* If we've already seen this file, skip it. */
|
||||
for (ll = needed; ll != l; ll = ll->next)
|
||||
if (strcmp (ll->name, lname) == 0)
|
||||
break;
|
||||
if (ll != l)
|
||||
continue;
|
||||
|
||||
/* See if this file was included in the link explicitly. */
|
||||
global_needed = l;
|
||||
global_found = false;
|
||||
lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
|
||||
if (global_found)
|
||||
continue;
|
||||
|
||||
if (strncmp (lname, "-l", 2) != 0)
|
||||
{
|
||||
bfd *abfd;
|
||||
|
||||
abfd = bfd_openr (lname, bfd_get_target (output_bfd));
|
||||
if (abfd != NULL)
|
||||
{
|
||||
if (! bfd_check_format (abfd, bfd_object))
|
||||
{
|
||||
(void) bfd_close (abfd);
|
||||
abfd = NULL;
|
||||
}
|
||||
}
|
||||
if (abfd != NULL)
|
||||
{
|
||||
if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
|
||||
{
|
||||
(void) bfd_close (abfd);
|
||||
abfd = NULL;
|
||||
}
|
||||
}
|
||||
if (abfd != NULL)
|
||||
{
|
||||
/* We've found the needed dynamic object. */
|
||||
if (! bfd_link_add_symbols (abfd, &link_info))
|
||||
einfo ("%F%B: could not read symbols: %E\n", abfd);
|
||||
}
|
||||
else
|
||||
{
|
||||
einfo ("%P: warning: %s, needed by %B, not found\n",
|
||||
lname, l->by);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
lname += 2;
|
||||
|
||||
/* We want to search for the file in the same way that the
|
||||
dynamic linker will search. That means that we want to use
|
||||
rpath_link, rpath or -L, then the environment variable
|
||||
LD_LIBRARY_PATH (native only), then (if rpath was used) the
|
||||
linker script LIB_SEARCH_DIRS. */
|
||||
if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
|
||||
lname))
|
||||
continue;
|
||||
if (command_line.rpath != NULL)
|
||||
{
|
||||
if (gld${EMULATION_NAME}_search_needed (command_line.rpath, lname))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (search = search_head; search != NULL; search = search->next)
|
||||
if (gld${EMULATION_NAME}_try_needed (search->name, lname))
|
||||
break;
|
||||
if (search != NULL)
|
||||
continue;
|
||||
}
|
||||
EOF
|
||||
if [ "x${host}" = "x${target}" ] ; then
|
||||
if [ "x${DEFAULT_EMULATION}" = "x${EMULATION_NAME}" ] ; then
|
||||
cat >>e${EMULATION_NAME}.c <<EOF
|
||||
{
|
||||
const char *lib_path;
|
||||
|
||||
lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
|
||||
if (gld${EMULATION_NAME}_search_needed (lib_path, lname))
|
||||
continue;
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
cat >>e${EMULATION_NAME}.c <<EOF
|
||||
if (command_line.rpath != NULL)
|
||||
{
|
||||
for (search = search_head; search != NULL; search = search->next)
|
||||
{
|
||||
if (search->cmdline)
|
||||
continue;
|
||||
if (gld${EMULATION_NAME}_try_needed (search->name, lname))
|
||||
break;
|
||||
}
|
||||
if (search != NULL)
|
||||
continue;
|
||||
}
|
||||
|
||||
einfo ("%P: warning: %s, needed by %B, not found\n",
|
||||
l->name, l->by);
|
||||
}
|
||||
}
|
||||
|
||||
/* Search for a needed file in a path. */
|
||||
|
||||
static boolean
|
||||
gld${EMULATION_NAME}_search_needed (path, name)
|
||||
const char *path;
|
||||
const char *name;
|
||||
{
|
||||
const char *s;
|
||||
|
||||
if (path == NULL || *path == '\0')
|
||||
return false;
|
||||
while (1)
|
||||
{
|
||||
const char *dir;
|
||||
char *dircopy;
|
||||
|
||||
s = strchr (path, ':');
|
||||
if (s == NULL)
|
||||
{
|
||||
dircopy = NULL;
|
||||
dir = path;
|
||||
}
|
||||
else
|
||||
{
|
||||
dircopy = (char *) xmalloc (s - path + 1);
|
||||
memcpy (dircopy, path, s - path);
|
||||
dircopy[s - path] = '\0';
|
||||
dir = dircopy;
|
||||
}
|
||||
|
||||
if (gld${EMULATION_NAME}_try_needed (dir, name))
|
||||
return true;
|
||||
|
||||
if (dircopy != NULL)
|
||||
free (dircopy);
|
||||
|
||||
if (s == NULL)
|
||||
break;
|
||||
path = s + 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This function is called for each possible directory for a needed
|
||||
dynamic object. */
|
||||
|
||||
static boolean
|
||||
gld${EMULATION_NAME}_try_needed (dir, name)
|
||||
const char *dir;
|
||||
const char *name;
|
||||
{
|
||||
char *file;
|
||||
char *alc;
|
||||
boolean ignore;
|
||||
bfd *abfd;
|
||||
|
||||
file = gld${EMULATION_NAME}_search_dir (dir, name, &ignore);
|
||||
if (file == NULL)
|
||||
return false;
|
||||
|
||||
alc = (char *) xmalloc (strlen (dir) + strlen (file) + 2);
|
||||
sprintf (alc, "%s/%s", dir, file);
|
||||
free (file);
|
||||
abfd = bfd_openr (alc, bfd_get_target (output_bfd));
|
||||
if (abfd == NULL)
|
||||
return false;
|
||||
if (! bfd_check_format (abfd, bfd_object))
|
||||
{
|
||||
(void) bfd_close (abfd);
|
||||
return false;
|
||||
}
|
||||
if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
|
||||
{
|
||||
(void) bfd_close (abfd);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* We've found the needed dynamic object. */
|
||||
|
||||
/* Add this file into the symbol table. */
|
||||
if (! bfd_link_add_symbols (abfd, &link_info))
|
||||
einfo ("%F%B: could not read symbols: %E\n", abfd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* See if we have already included a needed object in the link. This
|
||||
does not have to be precise, as it does no harm to include a
|
||||
dynamic object more than once. */
|
||||
|
||||
static void
|
||||
gld${EMULATION_NAME}_check_needed (s)
|
||||
lang_input_statement_type *s;
|
||||
{
|
||||
if (s->filename == NULL)
|
||||
return;
|
||||
if (strncmp (global_needed->name, "-l", 2) != 0)
|
||||
{
|
||||
if (strcmp (s->filename, global_needed->name) == 0)
|
||||
global_found = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *sname, *lname;
|
||||
const char *sdot, *ldot;
|
||||
int lmaj, lmin, smaj, smin;
|
||||
|
||||
lname = global_needed->name + 2;
|
||||
|
||||
sname = strrchr (s->filename, '/');
|
||||
if (sname == NULL)
|
||||
sname = s->filename;
|
||||
else
|
||||
++sname;
|
||||
|
||||
if (strncmp (sname, "lib", 3) != 0)
|
||||
return;
|
||||
sname += 3;
|
||||
|
||||
ldot = strchr (lname, '.');
|
||||
if (ldot == NULL)
|
||||
ldot = lname + strlen (lname);
|
||||
|
||||
sdot = strstr (sname, ".so.");
|
||||
if (sdot == NULL)
|
||||
return;
|
||||
|
||||
if (sdot - sname != ldot - lname
|
||||
|| strncmp (lname, sname, sdot - sname) != 0)
|
||||
return;
|
||||
|
||||
lmaj = lmin = -1;
|
||||
sscanf (ldot, ".%d.%d", &lmaj, &lmin);
|
||||
smaj = smin = -1;
|
||||
sscanf (sdot, ".so.%d.%d", &smaj, &smin);
|
||||
if ((smaj != lmaj && smaj != -1 && lmaj != -1)
|
||||
|| (smin != lmin && smin != -1 && lmin != -1))
|
||||
return;
|
||||
|
||||
global_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* We need to use static variables to pass information around the call
|
||||
to lang_for_each_statement. Ick. */
|
||||
|
||||
static const char *find_assign;
|
||||
static boolean found_assign;
|
||||
|
||||
/* We need to use static variables to pass information around the call
|
||||
to lang_for_each_input_file. Ick. */
|
||||
|
||||
static bfd_size_type need_size;
|
||||
static bfd_size_type need_entries;
|
||||
static bfd_byte *need_contents;
|
||||
static bfd_byte *need_pinfo;
|
||||
static bfd_byte *need_pnames;
|
||||
|
||||
/* The size of one entry in the .need section, not including the file
|
||||
name. */
|
||||
|
||||
#define NEED_ENTRY_SIZE (16)
|
||||
|
||||
/* 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 ()
|
||||
{
|
||||
struct bfd_link_hash_entry *hdyn = NULL;
|
||||
asection *sneed;
|
||||
asection *srules;
|
||||
asection *sdyn;
|
||||
|
||||
if (link_info.shared)
|
||||
{
|
||||
lang_output_section_statement_type *os;
|
||||
|
||||
/* Set the .text section to start at 0x20, not 0x2020. FIXME:
|
||||
This is too magical. */
|
||||
os = lang_output_section_statement_lookup (".text");
|
||||
if (os->addr_tree == NULL)
|
||||
os->addr_tree = exp_intop (0x20);
|
||||
}
|
||||
|
||||
/* We need to create a __DYNAMIC symbol. We don't do this in the
|
||||
linker script because we want to set the value to the start of
|
||||
the dynamic section if there is one, or to zero if there isn't
|
||||
one. We need to create the symbol before calling
|
||||
size_dynamic_sections, although we can't set the value until
|
||||
afterward. */
|
||||
if (! link_info.relocateable)
|
||||
{
|
||||
hdyn = bfd_link_hash_lookup (link_info.hash, "__DYNAMIC", true, false,
|
||||
false);
|
||||
if (hdyn == NULL)
|
||||
einfo ("%P%F: bfd_link_hash_lookup: %E\n");
|
||||
if (! bfd_netbsd_record_link_assignment (output_bfd, &link_info,
|
||||
"__DYNAMIC"))
|
||||
einfo ("%P%F: failed to record assignment to __DYNAMIC: %E\n");
|
||||
}
|
||||
|
||||
/* If we are going to make any variable assignments, we need to let
|
||||
the backend linker know about them in case the variables are
|
||||
referred to by dynamic objects. */
|
||||
lang_for_each_statement (gld${EMULATION_NAME}_find_assignment);
|
||||
|
||||
/* Let the backend linker work out the sizes of any sections
|
||||
required by dynamic linking. */
|
||||
if (! bfd_netbsd_size_dynamic_sections (output_bfd, &link_info, &sdyn,
|
||||
&sneed, &srules))
|
||||
einfo ("%P%F: failed to set dynamic section sizes: %E\n");
|
||||
|
||||
if (sneed != NULL)
|
||||
{
|
||||
/* Set up the .need section. See the description of the ld_need
|
||||
field in include/aout/sun4.h. */
|
||||
|
||||
need_entries = 0;
|
||||
need_size = 0;
|
||||
|
||||
lang_for_each_input_file (gld${EMULATION_NAME}_count_need);
|
||||
|
||||
/* We should only have a .need section if we have at least one
|
||||
dynamic object. */
|
||||
ASSERT (need_entries != 0);
|
||||
|
||||
sneed->_raw_size = need_size;
|
||||
sneed->contents = (bfd_byte *) xmalloc (need_size);
|
||||
|
||||
need_contents = sneed->contents;
|
||||
need_pinfo = sneed->contents;
|
||||
need_pnames = sneed->contents + need_entries * 16;
|
||||
|
||||
lang_for_each_input_file (gld${EMULATION_NAME}_set_need);
|
||||
|
||||
ASSERT ((bfd_size_type) (need_pnames - sneed->contents) == need_size);
|
||||
}
|
||||
|
||||
if (srules != NULL)
|
||||
{
|
||||
/* Set up the .rules section. This is just a PATH like string
|
||||
of the -L arguments given on the command line. We permit the
|
||||
user to specify the directories using the -rpath command line
|
||||
option. */
|
||||
if (command_line.rpath)
|
||||
{
|
||||
srules->_raw_size = strlen (command_line.rpath);
|
||||
srules->contents = (bfd_byte *) command_line.rpath;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int size;
|
||||
search_dirs_type *search;
|
||||
|
||||
size = 0;
|
||||
for (search = search_head; search != NULL; search = search->next)
|
||||
if (search->cmdline)
|
||||
size += strlen (search->name) + 1;
|
||||
srules->_raw_size = size;
|
||||
if (size > 0)
|
||||
{
|
||||
char *p;
|
||||
|
||||
srules->contents = (bfd_byte *) xmalloc (size);
|
||||
p = (char *) srules->contents;
|
||||
*p = '\0';
|
||||
for (search = search_head; search != NULL; search = search->next)
|
||||
{
|
||||
if (search->cmdline)
|
||||
{
|
||||
if (p != (char *) srules->contents)
|
||||
*p++ = ':';
|
||||
strcpy (p, search->name);
|
||||
p += strlen (p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We must assign a value to __DYNAMIC. It should be zero if we are
|
||||
not doing a dynamic link, or the start of the .dynamic section if
|
||||
we are doing one. */
|
||||
if (! link_info.relocateable)
|
||||
{
|
||||
hdyn->type = bfd_link_hash_defined;
|
||||
hdyn->u.def.value = 0;
|
||||
if (sdyn != NULL)
|
||||
hdyn->u.def.section = sdyn;
|
||||
else
|
||||
hdyn->u.def.section = bfd_abs_section_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is called by the before_allocation routine via
|
||||
lang_for_each_statement. It does one of two things: if the
|
||||
variable find_assign is set, it sets found_assign if it finds an
|
||||
assignment to that variable; otherwise it tells the backend linker
|
||||
about all assignment statements, in case they are assignments to
|
||||
symbols which are referred to by dynamic objects. */
|
||||
|
||||
static void
|
||||
gld${EMULATION_NAME}_find_assignment (s)
|
||||
lang_statement_union_type *s;
|
||||
{
|
||||
if (s->header.type == lang_assignment_statement_enum
|
||||
&& (find_assign == NULL || ! found_assign))
|
||||
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 (find_assign != NULL)
|
||||
{
|
||||
if (strcmp (find_assign, exp->assign.dst) == 0)
|
||||
found_assign = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp (exp->assign.dst, ".") != 0)
|
||||
{
|
||||
if (! bfd_netbsd_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.cond);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Work out the size of the .need section, and the number of entries.
|
||||
The backend will set the ld_need field of the dynamic linking
|
||||
information to point to the .need section. See include/aout/sun4.h
|
||||
for more information. */
|
||||
|
||||
static void
|
||||
gld${EMULATION_NAME}_count_need (inp)
|
||||
lang_input_statement_type *inp;
|
||||
{
|
||||
if (inp->the_bfd != NULL
|
||||
&& (inp->the_bfd->flags & DYNAMIC) != 0)
|
||||
{
|
||||
++need_entries;
|
||||
need_size += NEED_ENTRY_SIZE;
|
||||
if (! inp->is_archive)
|
||||
need_size += strlen (inp->filename) + 1;
|
||||
else
|
||||
{
|
||||
ASSERT (inp->local_sym_name[0] == '-'
|
||||
&& inp->local_sym_name[1] == 'l');
|
||||
need_size += strlen (inp->local_sym_name + 2) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill in the contents of the .need section. */
|
||||
|
||||
static void
|
||||
gld${EMULATION_NAME}_set_need (inp)
|
||||
lang_input_statement_type *inp;
|
||||
{
|
||||
if (inp->the_bfd != NULL
|
||||
&& (inp->the_bfd->flags & DYNAMIC) != 0)
|
||||
{
|
||||
bfd_size_type c;
|
||||
|
||||
/* To really fill in the .need section contents, we need to know
|
||||
the final file position of the section, but we don't.
|
||||
Instead, we use offsets, and rely on the BFD backend to
|
||||
finish the section up correctly. FIXME: Talk about lack of
|
||||
referential locality. */
|
||||
bfd_put_32 (output_bfd, need_pnames - need_contents, need_pinfo);
|
||||
if (! inp->is_archive)
|
||||
{
|
||||
bfd_put_32 (output_bfd, (bfd_vma) 0, need_pinfo + 4);
|
||||
bfd_put_16 (output_bfd, (bfd_vma) 0, need_pinfo + 8);
|
||||
bfd_put_16 (output_bfd, (bfd_vma) 0, need_pinfo + 10);
|
||||
strcpy (need_pnames, inp->filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *verstr;
|
||||
int maj, min;
|
||||
|
||||
if (bfd_big_endian(output_bfd))
|
||||
bfd_put_32 (output_bfd, (bfd_vma) 0x80000000, need_pinfo + 4);
|
||||
else
|
||||
bfd_put_32 (output_bfd, (bfd_vma) 0x00000001, need_pinfo + 4);
|
||||
maj = 0;
|
||||
min = 0;
|
||||
verstr = strstr (inp->filename, ".so.");
|
||||
if (verstr != NULL)
|
||||
sscanf (verstr, ".so.%d.%d", &maj, &min);
|
||||
bfd_put_16 (output_bfd, (bfd_vma) maj, need_pinfo + 8);
|
||||
bfd_put_16 (output_bfd, (bfd_vma) min, need_pinfo + 10);
|
||||
strcpy (need_pnames, inp->local_sym_name + 2);
|
||||
}
|
||||
|
||||
c = (need_pinfo - need_contents) / NEED_ENTRY_SIZE;
|
||||
if (c + 1 >= need_entries)
|
||||
bfd_put_32 (output_bfd, (bfd_vma) 0, need_pinfo + 12);
|
||||
else
|
||||
bfd_put_32 (output_bfd, (bfd_vma) (c + 1) * NEED_ENTRY_SIZE,
|
||||
need_pinfo + 12);
|
||||
|
||||
need_pinfo += NEED_ENTRY_SIZE;
|
||||
need_pnames += strlen (need_pnames) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
gld${EMULATION_NAME}_after_open,
|
||||
after_allocation_default,
|
||||
set_output_arch_default,
|
||||
ldemul_default_target,
|
||||
gld${EMULATION_NAME}_before_allocation,
|
||||
gld${EMULATION_NAME}_get_script,
|
||||
"${EMULATION_NAME}",
|
||||
"${OUTPUT_FORMAT}",
|
||||
NULL, /* finish */
|
||||
gld${EMULATION_NAME}_create_output_section_statements,
|
||||
NULL, /* open_dynamic_library */
|
||||
NULL, /* place_orphan */
|
||||
gld${EMULATION_NAME}_set_symbols
|
||||
};
|
||||
EOF
|
|
@ -43,23 +43,17 @@ if [ "x${LIB_PATH}" = "x" ] ; then
|
|||
case " $EMULATION_LIBPATH " in
|
||||
*" ${EMULATION_NAME} "*)
|
||||
# Native, and default or emulation requesting LIB_PATH.
|
||||
LIB_PATH=/lib:/usr/lib
|
||||
LIB_PATH=/usr/lib
|
||||
if [ -n "${NATIVE_LIB_DIRS}" ]; then
|
||||
LIB_PATH=${LIB_PATH}:${NATIVE_LIB_DIRS}
|
||||
fi
|
||||
if [ "${libdir}" != /usr/lib ]; then
|
||||
LIB_PATH=${LIB_PATH}:${libdir}
|
||||
fi
|
||||
if [ "${libdir}" != /usr/local/lib ] ; then
|
||||
LIB_PATH=${LIB_PATH}:/usr/local/lib
|
||||
fi
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
# Always search $(tooldir)/lib, aka /usr/local/TARGET/lib.
|
||||
LIB_PATH=${LIB_PATH}:${tool_lib}
|
||||
|
||||
LIB_SEARCH_DIRS=`echo ${LIB_PATH} | tr ':' ' ' | sed -e 's/\([^ ][^ ]*\)/SEARCH_DIR(\1);/g'`
|
||||
|
||||
# Generate 5 or 6 script files from a master script template in
|
||||
|
|
|
@ -178,6 +178,9 @@ typedef struct
|
|||
parameter. */
|
||||
boolean has_shared;
|
||||
|
||||
/* If true, do not use SEARCH_DIR directives from the linker script. */
|
||||
boolean no_std_path;
|
||||
|
||||
/* If true, build constructors. */
|
||||
boolean build_constructors;
|
||||
|
||||
|
|
|
@ -1630,7 +1630,7 @@ case 69:
|
|||
break;}
|
||||
case 70:
|
||||
#line 311 "ldgram.y"
|
||||
{ ldfile_add_library_path (yyvsp[-1].name, false); ;
|
||||
{ if (!config.no_std_path) ldfile_add_library_path (yyvsp[-1].name, false); ;
|
||||
break;}
|
||||
case 71:
|
||||
#line 313 "ldgram.y"
|
||||
|
|
|
@ -308,7 +308,7 @@ ifile_p1:
|
|||
| TARGET_K '(' NAME ')'
|
||||
{ lang_add_target($3); }
|
||||
| SEARCH_DIR '(' filename ')'
|
||||
{ ldfile_add_library_path ($3, false); }
|
||||
{ if (!config.no_std_path) ldfile_add_library_path ($3, false); }
|
||||
| OUTPUT '(' filename ')'
|
||||
{ lang_add_output($3, 1); }
|
||||
| OUTPUT_FORMAT '(' NAME ')'
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -200,6 +200,7 @@ main (argc, argv)
|
|||
config.build_constructors = true;
|
||||
config.dynamic_link = false;
|
||||
config.has_shared = false;
|
||||
config.no_std_path = (getenv("LD_NOSTD_PATH") ? true : false);
|
||||
command_line.force_common_definition = false;
|
||||
command_line.interpreter = NULL;
|
||||
command_line.rpath = NULL;
|
||||
|
|
|
@ -123,6 +123,7 @@ int parsing_defsym = 0;
|
|||
#define OPTION_NO_UNDEFINED (OPTION_MPC860C0 + 1)
|
||||
#define OPTION_INIT (OPTION_NO_UNDEFINED + 1)
|
||||
#define OPTION_FINI (OPTION_INIT + 1)
|
||||
#define OPTION_NO_STD_PATH (OPTION_FINI + 1)
|
||||
|
||||
/* The long options. This structure is used for both the option
|
||||
parsing and the help text. */
|
||||
|
@ -303,6 +304,8 @@ static const struct ld_option ld_options[] =
|
|||
'\0', NULL, N_("Create an output file even if errors occur"), TWO_DASHES },
|
||||
{ {"noinhibit_exec", no_argument, NULL, OPTION_NOINHIBIT_EXEC},
|
||||
'\0', NULL, NULL, NO_HELP },
|
||||
{ {"nostdlib", no_argument, NULL, OPTION_NO_STD_PATH}, /* NetBSD. */
|
||||
'\0', NULL, "Do not use default library search path", ONE_DASH },
|
||||
{ {"oformat", required_argument, NULL, OPTION_OFORMAT},
|
||||
'\0', N_("TARGET"), N_("Specify target of output file"), TWO_DASHES },
|
||||
{ {"qmagic", no_argument, NULL, OPTION_IGNORE},
|
||||
|
@ -318,7 +321,7 @@ static const struct ld_option ld_options[] =
|
|||
'\0', N_("PATH"), N_("Set link time shared library search path"), ONE_DASH },
|
||||
{ {"shared", no_argument, NULL, OPTION_SHARED},
|
||||
'\0', NULL, N_("Create a shared library"), ONE_DASH },
|
||||
{ {"Bshareable", no_argument, NULL, OPTION_SHARED }, /* FreeBSD. */
|
||||
{ {"Bshareable", no_argument, NULL, OPTION_SHARED }, /* FreeBSD, NetBSD. */
|
||||
'\0', NULL, NULL, ONE_DASH },
|
||||
{ {"sort-common", no_argument, NULL, OPTION_SORT_COMMON},
|
||||
'\0', NULL, N_("Sort common symbols by size"), TWO_DASHES },
|
||||
|
@ -364,6 +367,8 @@ static const struct ld_option ld_options[] =
|
|||
TWO_DASHES },
|
||||
{ {"whole-archive", no_argument, NULL, OPTION_WHOLE_ARCHIVE},
|
||||
'\0', NULL, N_("Include all objects from following archives"), TWO_DASHES },
|
||||
{ {"Bforcearchive", no_argument, NULL, OPTION_WHOLE_ARCHIVE}, /* NetBSD. */
|
||||
'\0', NULL, NULL, TWO_DASHES },
|
||||
{ {"wrap", required_argument, NULL, OPTION_WRAP},
|
||||
'\0', N_("SYMBOL"), N_("Use wrapper functions for SYMBOL"), TWO_DASHES },
|
||||
{ {"mpc860c0", optional_argument, NULL, OPTION_MPC860C0},
|
||||
|
@ -688,6 +693,9 @@ parse_args (argc, argv)
|
|||
case OPTION_NO_KEEP_MEMORY:
|
||||
link_info.keep_memory = false;
|
||||
break;
|
||||
case OPTION_NO_STD_PATH:
|
||||
config.no_std_path = true;
|
||||
break;
|
||||
case OPTION_NO_UNDEFINED:
|
||||
link_info.no_undefined = true;
|
||||
break;
|
||||
|
|
|
@ -6,16 +6,13 @@ TORS=".tors :
|
|||
___dtors = . ;
|
||||
*(.dtors)
|
||||
___dtors_end = . ;
|
||||
} > ram"
|
||||
}"
|
||||
|
||||
|
||||
cat <<EOF
|
||||
OUTPUT_FORMAT("${OUTPUT_FORMAT}")
|
||||
OUTPUT_ARCH(${ARCH})
|
||||
|
||||
MEMORY
|
||||
{
|
||||
ram : o = 0x1000, l = 512k
|
||||
}
|
||||
${LIB_SEARCH_DIRS}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
@ -24,25 +21,25 @@ SECTIONS
|
|||
*(.text)
|
||||
*(.strings)
|
||||
${RELOCATING+ _etext = . ; }
|
||||
} ${RELOCATING+ > ram}
|
||||
}
|
||||
${CONSTRUCTING+${TORS}}
|
||||
.data :
|
||||
.data ${RELOCATING+ ALIGN(${TARGET_PAGE_SIZE})} :
|
||||
{
|
||||
*(.data)
|
||||
${RELOCATING+ _edata = . ; }
|
||||
} ${RELOCATING+ > ram}
|
||||
.bss :
|
||||
}
|
||||
.bss ${RELOCATING+ ALIGN(${TARGET_PAGE_SIZE})} :
|
||||
{
|
||||
${RELOCATING+ _bss_start = . ; }
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
${RELOCATING+ _end = . ; }
|
||||
} ${RELOCATING+ > ram}
|
||||
.stack ${RELOCATING+ 0x30000 } :
|
||||
}
|
||||
.stack :
|
||||
{
|
||||
${RELOCATING+ _stack = . ; }
|
||||
*(.stack)
|
||||
} ${RELOCATING+ > ram}
|
||||
}
|
||||
.stab 0 ${RELOCATING+(NOLOAD)} :
|
||||
{
|
||||
*(.stab)
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
TORS=".tors :
|
||||
{
|
||||
___ctors = . ;
|
||||
*(.ctors)
|
||||
___ctors_end = . ;
|
||||
___dtors = . ;
|
||||
*(.dtors)
|
||||
___dtors_end = . ;
|
||||
}"
|
||||
|
||||
|
||||
cat <<EOF
|
||||
OUTPUT_FORMAT("${OUTPUT_FORMAT}")
|
||||
OUTPUT_ARCH(${ARCH})
|
||||
${LIB_SEARCH_DIRS}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = ${TEXT_START_ADDR} + SIZEOF_HEADERS;
|
||||
.text ALIGN(0x10):
|
||||
{
|
||||
*(.text)
|
||||
*(.strings)
|
||||
${RELOCATING+ _etext = . ; }
|
||||
}
|
||||
${CONSTRUCTING+${TORS}}
|
||||
.data ${RELOCATING+ ALIGN(${TARGET_PAGE_SIZE})} :
|
||||
{
|
||||
*(.data)
|
||||
${RELOCATING+ _edata = . ; }
|
||||
}
|
||||
.bss ${RELOCATING+ ALIGN(${TARGET_PAGE_SIZE})} :
|
||||
{
|
||||
${RELOCATING+ _bss_start = . ; }
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
${RELOCATING+ _end = . ; }
|
||||
}
|
||||
.stack :
|
||||
{
|
||||
${RELOCATING+ _stack = . ; }
|
||||
*(.stack)
|
||||
}
|
||||
.stab 0 ${RELOCATING+(NOLOAD)} :
|
||||
{
|
||||
*(.stab)
|
||||
}
|
||||
.stabstr 0 ${RELOCATING+(NOLOAD)} :
|
||||
{
|
||||
*(.stabstr)
|
||||
}
|
||||
}
|
||||
EOF
|
Loading…
Reference in New Issue