forked from KolibriOS/kolibrios
binutils: build LD.
git-svn-id: svn://kolibrios.org@5199 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
84eba6470e
commit
8bb709c8c6
@ -15,7 +15,7 @@ CFLAGS = -c $(CFLAGS_OPT)
|
|||||||
LDFLAGS = -nostdlib -shared -s --image-base 0 -T ../newlib/dll.lds -e _DllStartup
|
LDFLAGS = -nostdlib -shared -s --image-base 0 -T ../newlib/dll.lds -e _DllStartup
|
||||||
LDFLAGS+= --out-implib
|
LDFLAGS+= --out-implib
|
||||||
|
|
||||||
SUBDIRS = libiberty bfd
|
SUBDIRS = libiberty bfd ld
|
||||||
|
|
||||||
# targets
|
# targets
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@ INCLUDES= -I. -I../include -I$(SDK_DIR)/sources/newlib/libc/include -I$(SDK_DIR
|
|||||||
|
|
||||||
DEFINES= -DHAVE_CONFIG_H -DHAVE_i386pe_vec -DHAVE_i386pei_vec -DHAVE_bfd_elf32_i386_vec -DHAVE_bfd_elf32_little_generic_vec
|
DEFINES= -DHAVE_CONFIG_H -DHAVE_i386pe_vec -DHAVE_i386pei_vec -DHAVE_bfd_elf32_i386_vec -DHAVE_bfd_elf32_little_generic_vec
|
||||||
DEFINES+= -DHAVE_bfd_elf32_big_generic_vec -DBINDIR="/home/autobuild/tools/win32/bin"
|
DEFINES+= -DHAVE_bfd_elf32_big_generic_vec -DBINDIR="/home/autobuild/tools/win32/bin"
|
||||||
|
TDEFS= -DDEFAULT_VECTOR=i386pe_vec "-DSELECT_VECS=&i386pe_vec,&i386pei_vec,&bfd_elf32_i386_vec,&bfd_elf32_little_generic_vec,&bfd_elf32_big_generic_vec"
|
||||||
|
TDEFS+= "-DSELECT_ARCHITECTURES=&bfd_i386_arch"
|
||||||
|
|
||||||
SRCS = \
|
SRCS = \
|
||||||
archive.c archures.c bfd.c bfdio.c \
|
archive.c archures.c bfd.c bfdio.c \
|
||||||
@ -19,9 +21,9 @@ SRCS = \
|
|||||||
elf-nacl.c elf-strtab.c elf-vxworks.c \
|
elf-nacl.c elf-strtab.c elf-vxworks.c \
|
||||||
format.c hash.c ihex.c init.c libbfd.c \
|
format.c hash.c ihex.c init.c libbfd.c \
|
||||||
linker.c merge.c opncls.c pe-i386.c \
|
linker.c merge.c opncls.c pe-i386.c \
|
||||||
peigen.c reloc.c section.c simple.c \
|
peigen.c pei-i386.c reloc.c section.c \
|
||||||
srec.c stabs.c stab-syms.c syms.c \
|
simple.c srec.c stabs.c stab-syms.c \
|
||||||
targets.c tekhex.c verilog.c
|
syms.c targets.c tekhex.c verilog.c
|
||||||
|
|
||||||
|
|
||||||
OBJS = $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS)))
|
OBJS = $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS)))
|
||||||
@ -32,13 +34,18 @@ all: libbfd.a
|
|||||||
|
|
||||||
libbfd.a : $(OBJS) MAkefile
|
libbfd.a : $(OBJS) MAkefile
|
||||||
$(AR) crs libbfd.a $(OBJS)
|
$(AR) crs libbfd.a $(OBJS)
|
||||||
# mv -f libbfd.a $(SDK_DIR)/lib
|
mv -f libbfd.a $(SDK_DIR)/lib
|
||||||
|
|
||||||
%.o : %.c Makefile
|
%.o : %.c Makefile
|
||||||
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $<
|
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $<
|
||||||
|
|
||||||
dwarf2.o : dwarf2.c Makefile
|
dwarf2.o : dwarf2.c Makefile
|
||||||
$(CC) $(CFLAGS) $(DEFINES) -DDEBUGDIR=\"/home/autobuild/tools/win32/lib/debug\" $(INCLUDES) -o $@ $<
|
$(CC) $(CFLAGS) $(DEFINES) -DDEBUGDIR='"/home/autobuild/tools/win32/lib/debug\"' $(INCLUDES) -o $@ $<
|
||||||
|
|
||||||
|
|
||||||
|
targets.o : targets.c Makefile
|
||||||
|
$(CC) $(CFLAGS) $(DEFINES) $(TDEFS) $(INCLUDES) -o $@ $<
|
||||||
|
|
||||||
|
archures.o : archures.c Makefile
|
||||||
|
$(CC) $(CFLAGS) $(DEFINES) $(TDEFS) $(INCLUDES) -o $@ $<
|
||||||
|
|
@ -69,15 +69,6 @@ real_fseek (FILE *file, file_ptr offset, int whence)
|
|||||||
static FILE *
|
static FILE *
|
||||||
close_on_exec (FILE *file)
|
close_on_exec (FILE *file)
|
||||||
{
|
{
|
||||||
#if defined (HAVE_FILENO) && defined (F_GETFD)
|
|
||||||
if (file)
|
|
||||||
{
|
|
||||||
int fd = fileno (file);
|
|
||||||
int old = fcntl (fd, F_GETFD, 0);
|
|
||||||
if (old >= 0)
|
|
||||||
fcntl (fd, F_SETFD, old | FD_CLOEXEC);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,23 +76,8 @@ static int max_open_files = 0;
|
|||||||
static int
|
static int
|
||||||
bfd_cache_max_open (void)
|
bfd_cache_max_open (void)
|
||||||
{
|
{
|
||||||
if (max_open_files == 0)
|
|
||||||
{
|
max_open_files = 16;
|
||||||
int max;
|
|
||||||
#ifdef HAVE_GETRLIMIT
|
|
||||||
struct rlimit rlim;
|
|
||||||
if (getrlimit (RLIMIT_NOFILE, &rlim) == 0
|
|
||||||
&& rlim.rlim_cur != RLIM_INFINITY)
|
|
||||||
max = rlim.rlim_cur / 8;
|
|
||||||
else
|
|
||||||
#endif /* HAVE_GETRLIMIT */
|
|
||||||
#ifdef _SC_OPEN_MAX
|
|
||||||
max = sysconf (_SC_OPEN_MAX) / 8;
|
|
||||||
#else
|
|
||||||
max = 10;
|
|
||||||
#endif /* _SC_OPEN_MAX */
|
|
||||||
max_open_files = max < 10 ? 10 : max;
|
|
||||||
}
|
|
||||||
|
|
||||||
return max_open_files;
|
return max_open_files;
|
||||||
}
|
}
|
||||||
|
@ -673,12 +673,14 @@ _maybe_make_executable (bfd * abfd)
|
|||||||
which run tests with "ld [...] -o /dev/null". */
|
which run tests with "ld [...] -o /dev/null". */
|
||||||
&& S_ISREG(buf.st_mode))
|
&& S_ISREG(buf.st_mode))
|
||||||
{
|
{
|
||||||
unsigned int mask = umask (0);
|
/*
|
||||||
|
unsigned int mask = umask (0);
|
||||||
|
|
||||||
umask (mask);
|
umask (mask);
|
||||||
chmod (abfd->filename,
|
chmod (abfd->filename,
|
||||||
(0777
|
(0777
|
||||||
& (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
|
& (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
46
contrib/toolchain/binutils/bfd/pei-i386.c
Normal file
46
contrib/toolchain/binutils/bfd/pei-i386.c
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/* BFD back-end for Intel 386 PE IMAGE COFF files.
|
||||||
|
Copyright 1995, 1996, 1999, 2002, 2004, 2005, 2006, 2007, 2009
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of BFD, the Binary File Descriptor library.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#include "sysdep.h"
|
||||||
|
#include "bfd.h"
|
||||||
|
|
||||||
|
#define TARGET_SYM i386pei_vec
|
||||||
|
#define TARGET_NAME "pei-i386"
|
||||||
|
#define COFF_IMAGE_WITH_PE
|
||||||
|
#define COFF_WITH_PE
|
||||||
|
#define PCRELOFFSET TRUE
|
||||||
|
#define TARGET_UNDERSCORE '_'
|
||||||
|
/* Long section names not allowed in executable images, only object files. */
|
||||||
|
#define COFF_LONG_SECTION_NAMES 0
|
||||||
|
#define COFF_SUPPORT_GNU_LINKONCE
|
||||||
|
#define COFF_LONG_FILENAMES
|
||||||
|
|
||||||
|
#define COFF_SECTION_ALIGNMENT_ENTRIES \
|
||||||
|
{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
|
||||||
|
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
|
||||||
|
{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
|
||||||
|
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
|
||||||
|
{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
|
||||||
|
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
|
||||||
|
{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
|
||||||
|
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
|
||||||
|
|
||||||
|
#include "coff-i386.c"
|
@ -27,6 +27,8 @@
|
|||||||
#error sysdep.h must be included in lieu of config.h
|
#error sysdep.h must be included in lieu of config.h
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "ansidecl.h"
|
#include "ansidecl.h"
|
||||||
|
55
contrib/toolchain/binutils/ld/Makefile
Normal file
55
contrib/toolchain/binutils/ld/Makefile
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
NAME= ld-new
|
||||||
|
|
||||||
|
LIB_DIR:= $(SDK_DIR)/lib
|
||||||
|
|
||||||
|
CFLAGS_OPT = -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 -U_MSC_VER -O2
|
||||||
|
CFLAGS_OPT+= -fomit-frame-pointer -fno-ident -mno-ms-bitfields
|
||||||
|
CFLAGS_OPT+= -W -Wall -Wmissing-prototypes -Wno-format -Werror
|
||||||
|
CFLAGS = -c $(CFLAGS_OPT)
|
||||||
|
|
||||||
|
INCLUDES= -I. -I../bfd -I../include -I$(SDK_DIR)/sources/newlib/libc/include
|
||||||
|
|
||||||
|
DEFINES= -DHAVE_CONFIG_H -DLOCALEDIR='"/home/autobuild/tools/win32/share/locale"'
|
||||||
|
FDEFS= -DSCRIPTDIR='"/home/autobuild/tools/win32/mingw32/lib"' -DBINDIR='"/home/autobuild/tools/win32/bin"'
|
||||||
|
FDEFS+= -DTOOLBINDIR='"/home/autobuild/tools/win32/mingw32/bin"'
|
||||||
|
MDEFS= -DDEFAULT_EMULATION='"i386pe"' -DBINDIR='"/home/autobuild/tools/win32/bin"'
|
||||||
|
MDEFS+= -DTOOLBINDIR='"/home/autobuild/tools/win32/mingw32/bin"' -DTARGET='"i686-pc-mingw32"'
|
||||||
|
MDEFS+= -DTARGET_SYSTEM_ROOT='"/home/autobuild/tools/win32"' -DTARGET_SYSTEM_ROOT_RELOCATABLE
|
||||||
|
|
||||||
|
LIBS= -lbfd -liberty -lz -lgcc -lc.dll -lapp
|
||||||
|
|
||||||
|
LIBPATH:= -L$(LIB_DIR) -L/home/autobuild/tools/win32/mingw32/lib
|
||||||
|
|
||||||
|
LDFLAGS = -static -nostdlib --stack 0x200000 -T$(SDK_DIR)/sources/newlib/app.lds --image-base 0
|
||||||
|
|
||||||
|
|
||||||
|
SRCS = \
|
||||||
|
deffilep.c ei386pe.c \
|
||||||
|
ldcref.c ldctor.c ldemul.c \
|
||||||
|
ldexp.c ldfile.c ldgram.c \
|
||||||
|
ldlang.c ldlex-wrapper.c \
|
||||||
|
ldmain.c ldmisc.c ldver.c \
|
||||||
|
ldwrite.c lexsup.c mri.c \
|
||||||
|
pe-dll.c
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
OBJS = $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS)))
|
||||||
|
|
||||||
|
# targets
|
||||||
|
|
||||||
|
all: $(NAME)
|
||||||
|
|
||||||
|
$(NAME): $(OBJS) Makefile
|
||||||
|
$(LD) $(LDFLAGS) $(LIBPATH) -o $@ $(OBJS) $(LIBS)
|
||||||
|
kos32-objcopy $@ -O binary
|
||||||
|
|
||||||
|
%.o : %.c Makefile
|
||||||
|
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $<
|
||||||
|
|
||||||
|
ldfile.o : ldfile.c Makefile
|
||||||
|
$(CC) $(CFLAGS) $(DEFINES) $(FDEFS) $(INCLUDES) -o $@ $<
|
||||||
|
|
||||||
|
ldmain.o : ldmain.c Makefile
|
||||||
|
$(CC) $(CFLAGS) $(DEFINES) $(MDEFS) $(INCLUDES) -o $@ $<
|
||||||
|
|
238
contrib/toolchain/binutils/ld/config.h
Normal file
238
contrib/toolchain/binutils/ld/config.h
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
/* config.h. Generated from config.in by configure. */
|
||||||
|
/* config.in. Generated from configure.in by autoheader. */
|
||||||
|
|
||||||
|
/* Check that config.h is #included before system headers
|
||||||
|
(this works only for glibc, but that should be enough). */
|
||||||
|
#if defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__CONFIG_H__)
|
||||||
|
# error config.h must be #included before system headers
|
||||||
|
#endif
|
||||||
|
#define __CONFIG_H__ 1
|
||||||
|
|
||||||
|
/* Define to 1 if translation of program messages to the user's native
|
||||||
|
language is requested. */
|
||||||
|
/* #undef ENABLE_NLS */
|
||||||
|
|
||||||
|
/* Additional extension a shared object might have. */
|
||||||
|
/* #undef EXTRA_SHLIB_EXTENSION */
|
||||||
|
|
||||||
|
/* Define to choose default GOT handling scheme */
|
||||||
|
#define GOT_HANDLING_DEFAULT GOT_HANDLING_TARGET_DEFAULT
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `close' function. */
|
||||||
|
#define HAVE_CLOSE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `environ', and to 0 if you
|
||||||
|
don't. */
|
||||||
|
#define HAVE_DECL_ENVIRON 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `free', and to 0 if you don't.
|
||||||
|
*/
|
||||||
|
#define HAVE_DECL_FREE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `getenv', and to 0 if you don't.
|
||||||
|
*/
|
||||||
|
#define HAVE_DECL_GETENV 1
|
||||||
|
|
||||||
|
/* Is the prototype for getopt in <unistd.h> in the expected format? */
|
||||||
|
#define HAVE_DECL_GETOPT 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `sbrk', and to 0 if you don't.
|
||||||
|
*/
|
||||||
|
#define HAVE_DECL_SBRK 0
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `strstr', and to 0 if you don't.
|
||||||
|
*/
|
||||||
|
#define HAVE_DECL_STRSTR 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
|
||||||
|
*/
|
||||||
|
#define HAVE_DIRENT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `dlclose' function. */
|
||||||
|
/* #undef HAVE_DLCLOSE */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||||
|
/* #undef HAVE_DLFCN_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `dlopen' function. */
|
||||||
|
/* #undef HAVE_DLOPEN */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `dlsym' function. */
|
||||||
|
/* #undef HAVE_DLSYM */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <elf-hints.h> header file. */
|
||||||
|
/* #undef HAVE_ELF_HINTS_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||||
|
#define HAVE_FCNTL_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `glob' function. */
|
||||||
|
/* #undef HAVE_GLOB */
|
||||||
|
|
||||||
|
/* Define .init_array/.fini_array sections are available and working. */
|
||||||
|
#define HAVE_INITFINI_ARRAY 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
|
#define HAVE_INTTYPES_H 1
|
||||||
|
|
||||||
|
/* Define if your <locale.h> file defines LC_MESSAGES. */
|
||||||
|
/* #undef HAVE_LC_MESSAGES */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <limits.h> header file. */
|
||||||
|
#define HAVE_LIMITS_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <locale.h> header file. */
|
||||||
|
#define HAVE_LOCALE_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `lseek' function. */
|
||||||
|
#define HAVE_LSEEK 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
|
#define HAVE_MEMORY_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `mkstemp' function. */
|
||||||
|
/* #undef HAVE_MKSTEMP */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
|
||||||
|
/* #undef HAVE_NDIR_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `open' function. */
|
||||||
|
#define HAVE_OPEN 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `realpath' function. */
|
||||||
|
/* #undef HAVE_REALPATH */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `sbrk' function. */
|
||||||
|
/* #undef HAVE_SBRK */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `setlocale' function. */
|
||||||
|
#define HAVE_SETLOCALE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
|
#define HAVE_STDINT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
|
#define HAVE_STDLIB_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
|
#define HAVE_STRINGS_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
|
#define HAVE_STRING_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
|
||||||
|
*/
|
||||||
|
/* #undef HAVE_SYS_DIR_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/file.h> header file. */
|
||||||
|
#define HAVE_SYS_FILE_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
|
||||||
|
*/
|
||||||
|
/* #undef HAVE_SYS_NDIR_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||||
|
#define HAVE_SYS_PARAM_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
|
#define HAVE_SYS_STAT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||||
|
#define HAVE_SYS_TIME_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
|
#define HAVE_SYS_TYPES_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
|
#define HAVE_UNISTD_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `waitpid' function. */
|
||||||
|
/* #undef HAVE_WAITPID */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <windows.h> header file. */
|
||||||
|
//#define HAVE_WINDOWS_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <zlib.h> header file. */
|
||||||
|
#define HAVE_ZLIB_H 1
|
||||||
|
|
||||||
|
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||||
|
*/
|
||||||
|
#define LT_OBJDIR ".libs/"
|
||||||
|
|
||||||
|
/* Name of package */
|
||||||
|
#define PACKAGE "ld"
|
||||||
|
|
||||||
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
|
#define PACKAGE_BUGREPORT ""
|
||||||
|
|
||||||
|
/* Define to the full name of this package. */
|
||||||
|
#define PACKAGE_NAME ""
|
||||||
|
|
||||||
|
/* Define to the full name and version of this package. */
|
||||||
|
#define PACKAGE_STRING ""
|
||||||
|
|
||||||
|
/* Define to the one symbol short name of this package. */
|
||||||
|
#define PACKAGE_TARNAME ""
|
||||||
|
|
||||||
|
/* Define to the home page for this package. */
|
||||||
|
#define PACKAGE_URL ""
|
||||||
|
|
||||||
|
/* Define to the version of this package. */
|
||||||
|
#define PACKAGE_VERSION ""
|
||||||
|
|
||||||
|
/* The size of `void *', as computed by sizeof. */
|
||||||
|
#define SIZEOF_VOID_P 4
|
||||||
|
|
||||||
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
|
#define STDC_HEADERS 1
|
||||||
|
|
||||||
|
/* Define if you can safely include both <string.h> and <strings.h>. */
|
||||||
|
#define STRING_WITH_STRINGS 1
|
||||||
|
|
||||||
|
/* Use b modifier when opening binary files? */
|
||||||
|
#define USE_BINARY_FOPEN 1
|
||||||
|
|
||||||
|
/* Enable extensions on AIX 3, Interix. */
|
||||||
|
#ifndef _ALL_SOURCE
|
||||||
|
# define _ALL_SOURCE 1
|
||||||
|
#endif
|
||||||
|
/* Enable GNU extensions on systems that have them. */
|
||||||
|
#ifndef _GNU_SOURCE
|
||||||
|
# define _GNU_SOURCE 1
|
||||||
|
#endif
|
||||||
|
/* Enable threading extensions on Solaris. */
|
||||||
|
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||||
|
# define _POSIX_PTHREAD_SEMANTICS 1
|
||||||
|
#endif
|
||||||
|
/* Enable extensions on HP NonStop. */
|
||||||
|
#ifndef _TANDEM_SOURCE
|
||||||
|
# define _TANDEM_SOURCE 1
|
||||||
|
#endif
|
||||||
|
/* Enable general extensions on Solaris. */
|
||||||
|
#ifndef __EXTENSIONS__
|
||||||
|
# define __EXTENSIONS__ 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Version number of package */
|
||||||
|
#define VERSION "2.24"
|
||||||
|
|
||||||
|
/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
|
||||||
|
`char[]'. */
|
||||||
|
/* #undef YYTEXT_POINTER */
|
||||||
|
|
||||||
|
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||||
|
/* #undef _FILE_OFFSET_BITS */
|
||||||
|
|
||||||
|
/* Define for large files, on AIX-style hosts. */
|
||||||
|
/* #undef _LARGE_FILES */
|
||||||
|
|
||||||
|
/* Define to 1 if on MINIX. */
|
||||||
|
/* #undef _MINIX */
|
||||||
|
|
||||||
|
/* Define to 2 if the system does not provide POSIX.1 features except with
|
||||||
|
this defined. */
|
||||||
|
/* #undef _POSIX_1_SOURCE */
|
||||||
|
|
||||||
|
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||||
|
/* #undef _POSIX_SOURCE */
|
118
contrib/toolchain/binutils/ld/deffile.h
Normal file
118
contrib/toolchain/binutils/ld/deffile.h
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/* deffile.h - header for .DEF file parser
|
||||||
|
Copyright 1998, 1999, 2000, 2002, 2003, 2005, 2006, 2007, 2009
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
Written by DJ Delorie dj@cygnus.com
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
The 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 GLD; see the file COPYING. If not, write to the Free
|
||||||
|
Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||||
|
02110-1301, USA. */
|
||||||
|
|
||||||
|
#ifndef DEFFILE_H
|
||||||
|
#define DEFFILE_H
|
||||||
|
|
||||||
|
/* DEF storage definitions. Note that any ordinal may be zero, and
|
||||||
|
any pointer may be NULL, if not defined by the DEF file. */
|
||||||
|
|
||||||
|
typedef struct def_file_section {
|
||||||
|
char *name; /* always set */
|
||||||
|
char *class; /* may be NULL */
|
||||||
|
char flag_read, flag_write, flag_execute, flag_shared;
|
||||||
|
} def_file_section;
|
||||||
|
|
||||||
|
typedef struct def_file_export {
|
||||||
|
char *name; /* always set */
|
||||||
|
char *internal_name; /* always set, may == name */
|
||||||
|
char *its_name; /* optional export table name refered to. */
|
||||||
|
int ordinal; /* -1 if not specified */
|
||||||
|
int hint;
|
||||||
|
char flag_private, flag_constant, flag_noname, flag_data, flag_forward;
|
||||||
|
} def_file_export;
|
||||||
|
|
||||||
|
typedef struct def_file_module {
|
||||||
|
struct def_file_module *next;
|
||||||
|
void *user_data;
|
||||||
|
char name[1]; /* extended via malloc */
|
||||||
|
} def_file_module;
|
||||||
|
|
||||||
|
typedef struct def_file_import {
|
||||||
|
char *internal_name; /* always set */
|
||||||
|
def_file_module *module; /* always set */
|
||||||
|
char *name; /* may be NULL; either this or ordinal will be set */
|
||||||
|
char *its_name; /* optional import table name refered to. */
|
||||||
|
int ordinal; /* may be -1 */
|
||||||
|
int data; /* = 1 if data */
|
||||||
|
} def_file_import;
|
||||||
|
|
||||||
|
typedef struct def_file_aligncomm {
|
||||||
|
struct def_file_aligncomm *next; /* Chain pointer. */
|
||||||
|
char *symbol_name; /* Name of common symbol. */
|
||||||
|
unsigned int alignment; /* log-2 alignment. */
|
||||||
|
} def_file_aligncomm;
|
||||||
|
|
||||||
|
typedef struct def_file {
|
||||||
|
/* From the NAME or LIBRARY command. */
|
||||||
|
char *name;
|
||||||
|
int is_dll; /* -1 if NAME/LIBRARY not given */
|
||||||
|
bfd_vma base_address; /* (bfd_vma)(-1) if unspecified */
|
||||||
|
|
||||||
|
/* From the DESCRIPTION command. */
|
||||||
|
char *description;
|
||||||
|
|
||||||
|
/* From the STACK/HEAP command, -1 if unspecified. */
|
||||||
|
int stack_reserve, stack_commit;
|
||||||
|
int heap_reserve, heap_commit;
|
||||||
|
|
||||||
|
/* From the SECTION/SEGMENT commands. */
|
||||||
|
int num_section_defs;
|
||||||
|
def_file_section *section_defs;
|
||||||
|
|
||||||
|
/* From the EXPORTS commands. */
|
||||||
|
int num_exports;
|
||||||
|
def_file_export *exports;
|
||||||
|
|
||||||
|
/* Used by imports for module names. */
|
||||||
|
def_file_module *modules;
|
||||||
|
|
||||||
|
/* From the IMPORTS commands. */
|
||||||
|
int num_imports;
|
||||||
|
def_file_import *imports;
|
||||||
|
|
||||||
|
/* From the VERSION command, -1 if not specified. */
|
||||||
|
int version_major, version_minor;
|
||||||
|
|
||||||
|
/* Only expected from .drectve sections, not .DEF files. */
|
||||||
|
def_file_aligncomm *aligncomms;
|
||||||
|
|
||||||
|
} def_file;
|
||||||
|
|
||||||
|
extern def_file *def_file_empty (void);
|
||||||
|
|
||||||
|
/* The second arg may be NULL. If not, this .def is appended to it. */
|
||||||
|
extern def_file *def_file_parse (const char *, def_file *);
|
||||||
|
extern void def_file_free (def_file *);
|
||||||
|
extern def_file_export *def_file_add_export (def_file *, const char *,
|
||||||
|
const char *, int,
|
||||||
|
const char *, int *);
|
||||||
|
extern def_file_import *def_file_add_import (def_file *, const char *,
|
||||||
|
const char *, int, const char *,
|
||||||
|
const char *, int *);
|
||||||
|
extern void def_file_add_directive (def_file *, const char *, int);
|
||||||
|
extern def_file_module *def_get_module (def_file *, const char *);
|
||||||
|
#ifdef DEF_FILE_PRINT
|
||||||
|
extern void def_file_print (FILE *, def_file *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* DEFFILE_H */
|
3426
contrib/toolchain/binutils/ld/deffilep.c
Normal file
3426
contrib/toolchain/binutils/ld/deffilep.c
Normal file
File diff suppressed because it is too large
Load Diff
3832
contrib/toolchain/binutils/ld/ei386pe.c
Normal file
3832
contrib/toolchain/binutils/ld/ei386pe.c
Normal file
File diff suppressed because it is too large
Load Diff
321
contrib/toolchain/binutils/ld/ld.h
Normal file
321
contrib/toolchain/binutils/ld/ld.h
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
/* ld.h -- general linker header file
|
||||||
|
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||||
|
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#ifndef LD_H
|
||||||
|
#define LD_H
|
||||||
|
|
||||||
|
#ifdef HAVE_LOCALE_H
|
||||||
|
#endif
|
||||||
|
#ifndef SEEK_CUR
|
||||||
|
#define SEEK_CUR 1
|
||||||
|
#endif
|
||||||
|
#ifndef SEEK_END
|
||||||
|
#define SEEK_END 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_LOCALE_H
|
||||||
|
# ifndef ENABLE_NLS
|
||||||
|
/* The Solaris version of locale.h always includes libintl.h. If we have
|
||||||
|
been configured with --disable-nls then ENABLE_NLS will not be defined
|
||||||
|
and the dummy definitions of bindtextdomain (et al) below will conflict
|
||||||
|
with the defintions in libintl.h. So we define these values to prevent
|
||||||
|
the bogus inclusion of libintl.h. */
|
||||||
|
# define _LIBINTL_H
|
||||||
|
# define _LIBGETTEXT_H
|
||||||
|
# endif
|
||||||
|
# include <locale.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_NLS
|
||||||
|
# include <libintl.h>
|
||||||
|
# define _(String) gettext (String)
|
||||||
|
# ifdef gettext_noop
|
||||||
|
# define N_(String) gettext_noop (String)
|
||||||
|
# else
|
||||||
|
# define N_(String) (String)
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define gettext(Msgid) (Msgid)
|
||||||
|
# define dgettext(Domainname, Msgid) (Msgid)
|
||||||
|
# define dcgettext(Domainname, Msgid, Category) (Msgid)
|
||||||
|
# define textdomain(Domainname) while (0) /* nothing */
|
||||||
|
# define bindtextdomain(Domainname, Dirname) while (0) /* nothing */
|
||||||
|
# define _(String) (String)
|
||||||
|
# define N_(String) (String)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Look in this environment name for the linker to pretend to be */
|
||||||
|
#define EMULATION_ENVIRON "LDEMULATION"
|
||||||
|
/* If in there look for the strings: */
|
||||||
|
|
||||||
|
/* Look in this variable for a target format */
|
||||||
|
#define TARGET_ENVIRON "GNUTARGET"
|
||||||
|
|
||||||
|
/* Input sections which are put in a section of this name are actually
|
||||||
|
discarded. */
|
||||||
|
#define DISCARD_SECTION_NAME "/DISCARD/"
|
||||||
|
|
||||||
|
/* A file name list */
|
||||||
|
typedef struct name_list {
|
||||||
|
const char *name;
|
||||||
|
struct name_list *next;
|
||||||
|
}
|
||||||
|
name_list;
|
||||||
|
|
||||||
|
typedef enum {sort_none, sort_ascending, sort_descending} sort_order;
|
||||||
|
|
||||||
|
/* A wildcard specification. */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
none, by_name, by_alignment, by_name_alignment, by_alignment_name,
|
||||||
|
by_none, by_init_priority
|
||||||
|
} sort_type;
|
||||||
|
|
||||||
|
extern sort_type sort_section;
|
||||||
|
|
||||||
|
struct wildcard_spec {
|
||||||
|
const char *name;
|
||||||
|
struct name_list *exclude_name_list;
|
||||||
|
sort_type sorted;
|
||||||
|
struct flag_info *section_flag_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wildcard_list {
|
||||||
|
struct wildcard_list *next;
|
||||||
|
struct wildcard_spec spec;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct map_symbol_def {
|
||||||
|
struct bfd_link_hash_entry *entry;
|
||||||
|
struct map_symbol_def *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The initial part of fat_user_section_struct has to be idential with
|
||||||
|
lean_user_section_struct. */
|
||||||
|
typedef struct fat_user_section_struct {
|
||||||
|
/* For input sections, when writing a map file: head / tail of a linked
|
||||||
|
list of hash table entries for symbols defined in this section. */
|
||||||
|
struct map_symbol_def *map_symbol_def_head;
|
||||||
|
struct map_symbol_def **map_symbol_def_tail;
|
||||||
|
unsigned long map_symbol_def_count;
|
||||||
|
} fat_section_userdata_type;
|
||||||
|
|
||||||
|
#define get_userdata(x) ((x)->userdata)
|
||||||
|
|
||||||
|
#define BYTE_SIZE (1)
|
||||||
|
#define SHORT_SIZE (2)
|
||||||
|
#define LONG_SIZE (4)
|
||||||
|
#define QUAD_SIZE (8)
|
||||||
|
|
||||||
|
enum endian_enum { ENDIAN_UNSET = 0, ENDIAN_BIG, ENDIAN_LITTLE };
|
||||||
|
|
||||||
|
enum symbolic_enum
|
||||||
|
{
|
||||||
|
symbolic_unset = 0,
|
||||||
|
symbolic,
|
||||||
|
symbolic_functions,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dynamic_list_enum
|
||||||
|
{
|
||||||
|
dynamic_list_unset = 0,
|
||||||
|
dynamic_list_data,
|
||||||
|
dynamic_list
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* 1 => assign space to common symbols even if `relocatable_output'. */
|
||||||
|
bfd_boolean force_common_definition;
|
||||||
|
|
||||||
|
/* 1 => do not assign addresses to common symbols. */
|
||||||
|
bfd_boolean inhibit_common_definition;
|
||||||
|
|
||||||
|
/* If TRUE, build MIPS embedded PIC relocation tables in the output
|
||||||
|
file. */
|
||||||
|
bfd_boolean embedded_relocs;
|
||||||
|
|
||||||
|
/* If TRUE, force generation of a file with a .exe file. */
|
||||||
|
bfd_boolean force_exe_suffix;
|
||||||
|
|
||||||
|
/* If TRUE, generate a cross reference report. */
|
||||||
|
bfd_boolean cref;
|
||||||
|
|
||||||
|
/* If TRUE (which is the default), warn about mismatched input
|
||||||
|
files. */
|
||||||
|
bfd_boolean warn_mismatch;
|
||||||
|
|
||||||
|
/* Warn on attempting to open an incompatible library during a library
|
||||||
|
search. */
|
||||||
|
bfd_boolean warn_search_mismatch;
|
||||||
|
|
||||||
|
/* If non-zero check section addresses, once computed,
|
||||||
|
for overlaps. Relocatable links only check when this is > 0. */
|
||||||
|
signed char check_section_addresses;
|
||||||
|
|
||||||
|
/* If TRUE allow the linking of input files in an unknown architecture
|
||||||
|
assuming that the user knows what they are doing. This was the old
|
||||||
|
behaviour of the linker. The new default behaviour is to reject such
|
||||||
|
input files. */
|
||||||
|
bfd_boolean accept_unknown_input_arch;
|
||||||
|
|
||||||
|
/* If TRUE we'll just print the default output on stdout. */
|
||||||
|
bfd_boolean print_output_format;
|
||||||
|
|
||||||
|
/* Big or little endian as set on command line. */
|
||||||
|
enum endian_enum endian;
|
||||||
|
|
||||||
|
/* -Bsymbolic and -Bsymbolic-functions, as set on command line. */
|
||||||
|
enum symbolic_enum symbolic;
|
||||||
|
|
||||||
|
/* --dynamic-list, --dynamic-list-cpp-new, --dynamic-list-cpp-typeinfo
|
||||||
|
and --dynamic-list FILE, as set on command line. */
|
||||||
|
enum dynamic_list_enum dynamic_list;
|
||||||
|
|
||||||
|
/* Name of runtime interpreter to invoke. */
|
||||||
|
char *interpreter;
|
||||||
|
|
||||||
|
/* Name to give runtime libary from the -soname argument. */
|
||||||
|
char *soname;
|
||||||
|
|
||||||
|
/* Runtime library search path from the -rpath argument. */
|
||||||
|
char *rpath;
|
||||||
|
|
||||||
|
/* Link time runtime library search path from the -rpath-link
|
||||||
|
argument. */
|
||||||
|
char *rpath_link;
|
||||||
|
|
||||||
|
/* Name of shared object whose symbol table should be filtered with
|
||||||
|
this shared object. From the --filter option. */
|
||||||
|
char *filter_shlib;
|
||||||
|
|
||||||
|
/* Name of shared object for whose symbol table this shared object
|
||||||
|
is an auxiliary filter. From the --auxiliary option. */
|
||||||
|
char **auxiliary_filters;
|
||||||
|
|
||||||
|
/* A version symbol to be applied to the symbol names found in the
|
||||||
|
.exports sections. */
|
||||||
|
char *version_exports_section;
|
||||||
|
|
||||||
|
/* Default linker script. */
|
||||||
|
char *default_script;
|
||||||
|
} args_type;
|
||||||
|
|
||||||
|
extern args_type command_line;
|
||||||
|
|
||||||
|
typedef int token_code_type;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bfd_boolean magic_demand_paged;
|
||||||
|
bfd_boolean make_executable;
|
||||||
|
|
||||||
|
/* If TRUE, -shared is supported. */
|
||||||
|
/* ??? A better way to do this is perhaps to define this in the
|
||||||
|
ld_emulation_xfer_struct since this is really a target dependent
|
||||||
|
parameter. */
|
||||||
|
bfd_boolean has_shared;
|
||||||
|
|
||||||
|
/* If TRUE, build constructors. */
|
||||||
|
bfd_boolean build_constructors;
|
||||||
|
|
||||||
|
/* If TRUE, warn about any constructors. */
|
||||||
|
bfd_boolean warn_constructors;
|
||||||
|
|
||||||
|
/* If TRUE, warn about merging common symbols with others. */
|
||||||
|
bfd_boolean warn_common;
|
||||||
|
|
||||||
|
/* If TRUE, only warn once about a particular undefined symbol. */
|
||||||
|
bfd_boolean warn_once;
|
||||||
|
|
||||||
|
/* If TRUE, warn if multiple global-pointers are needed (Alpha
|
||||||
|
only). */
|
||||||
|
bfd_boolean warn_multiple_gp;
|
||||||
|
|
||||||
|
/* If TRUE, warn if the starting address of an output section
|
||||||
|
changes due to the alignment of an input section. */
|
||||||
|
bfd_boolean warn_section_align;
|
||||||
|
|
||||||
|
/* If TRUE, warning messages are fatal */
|
||||||
|
bfd_boolean fatal_warnings;
|
||||||
|
|
||||||
|
sort_order sort_common;
|
||||||
|
|
||||||
|
bfd_boolean text_read_only;
|
||||||
|
|
||||||
|
bfd_boolean stats;
|
||||||
|
|
||||||
|
/* If set, orphan input sections will be mapped to separate output
|
||||||
|
sections. */
|
||||||
|
bfd_boolean unique_orphan_sections;
|
||||||
|
|
||||||
|
/* If set, only search library directories explicitly selected
|
||||||
|
on the command line. */
|
||||||
|
bfd_boolean only_cmd_line_lib_dirs;
|
||||||
|
|
||||||
|
/* If set, numbers and absolute symbols are simply treated as
|
||||||
|
numbers everywhere. */
|
||||||
|
bfd_boolean sane_expr;
|
||||||
|
|
||||||
|
/* If set, code and non-code sections should never be in one segment. */
|
||||||
|
bfd_boolean separate_code;
|
||||||
|
|
||||||
|
/* The rpath separation character. Usually ':'. */
|
||||||
|
char rpath_separator;
|
||||||
|
|
||||||
|
char *map_filename;
|
||||||
|
FILE *map_file;
|
||||||
|
|
||||||
|
unsigned int split_by_reloc;
|
||||||
|
bfd_size_type split_by_file;
|
||||||
|
|
||||||
|
bfd_size_type specified_data_size;
|
||||||
|
|
||||||
|
/* The size of the hash table to use. */
|
||||||
|
unsigned long hash_table_size;
|
||||||
|
|
||||||
|
/* The maximum page size for ELF. */
|
||||||
|
bfd_vma maxpagesize;
|
||||||
|
|
||||||
|
/* The common page size for ELF. */
|
||||||
|
bfd_vma commonpagesize;
|
||||||
|
} ld_config_type;
|
||||||
|
|
||||||
|
extern ld_config_type config;
|
||||||
|
|
||||||
|
extern FILE * saved_script_handle;
|
||||||
|
extern bfd_boolean force_make_executable;
|
||||||
|
|
||||||
|
extern int yyparse (void);
|
||||||
|
extern void add_cref (const char *, bfd *, asection *, bfd_vma);
|
||||||
|
extern bfd_boolean handle_asneeded_cref (bfd *, enum notice_asneeded_action);
|
||||||
|
extern void output_cref (FILE *);
|
||||||
|
extern void check_nocrossrefs (void);
|
||||||
|
extern void ld_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
|
||||||
|
|
||||||
|
/* If gcc >= 2.6, we can give a function name, too. */
|
||||||
|
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6)
|
||||||
|
#define __PRETTY_FUNCTION__ NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef abort
|
||||||
|
#define abort() ld_abort (__FILE__, __LINE__, __PRETTY_FUNCTION__)
|
||||||
|
|
||||||
|
#endif
|
4
contrib/toolchain/binutils/ld/ld.lnk
Normal file
4
contrib/toolchain/binutils/ld/ld.lnk
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
-static -nostdlib --stack 0x200000 -T/kolibrios/contrib/sdk/sources/newlib/app.lds
|
||||||
|
--image-base 0 -L/kolibrios/contrib/sdk/lib -o ld-new deffilep.o ei386pe.o ldcref.o ldctor.o ldemul.o ldexp.o ldfile.o ldgram.o
|
||||||
|
ldlang.o ldlex-wrapper.o ldmain.o ldmisc.o ldver.o ldwrite.o lexsup.o mri.o pe-dll.o
|
||||||
|
-lbfd -liberty -lz -lgcc -lc.dll -lapp
|
704
contrib/toolchain/binutils/ld/ldcref.c
Normal file
704
contrib/toolchain/binutils/ld/ldcref.c
Normal file
@ -0,0 +1,704 @@
|
|||||||
|
/* ldcref.c -- output a cross reference table
|
||||||
|
Copyright 1996-2013 Free Software Foundation, Inc.
|
||||||
|
Written by Ian Lance Taylor <ian@cygnus.com>
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
|
||||||
|
/* This file holds routines that manage the cross reference table.
|
||||||
|
The table is used to generate cross reference reports. It is also
|
||||||
|
used to implement the NOCROSSREFS command in the linker script. */
|
||||||
|
|
||||||
|
#include "sysdep.h"
|
||||||
|
#include "bfd.h"
|
||||||
|
#include "bfdlink.h"
|
||||||
|
#include "libiberty.h"
|
||||||
|
#include "demangle.h"
|
||||||
|
#include "objalloc.h"
|
||||||
|
|
||||||
|
#include "ld.h"
|
||||||
|
#include "ldmain.h"
|
||||||
|
#include "ldmisc.h"
|
||||||
|
#include "ldexp.h"
|
||||||
|
#include "ldlang.h"
|
||||||
|
|
||||||
|
/* We keep an instance of this structure for each reference to a
|
||||||
|
symbol from a given object. */
|
||||||
|
|
||||||
|
struct cref_ref {
|
||||||
|
/* The next reference. */
|
||||||
|
struct cref_ref *next;
|
||||||
|
/* The object. */
|
||||||
|
bfd *abfd;
|
||||||
|
/* True if the symbol is defined. */
|
||||||
|
unsigned int def : 1;
|
||||||
|
/* True if the symbol is common. */
|
||||||
|
unsigned int common : 1;
|
||||||
|
/* True if the symbol is undefined. */
|
||||||
|
unsigned int undef : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* We keep a hash table of symbols. Each entry looks like this. */
|
||||||
|
|
||||||
|
struct cref_hash_entry {
|
||||||
|
struct bfd_hash_entry root;
|
||||||
|
/* The demangled name. */
|
||||||
|
const char *demangled;
|
||||||
|
/* References to and definitions of this symbol. */
|
||||||
|
struct cref_ref *refs;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This is what the hash table looks like. */
|
||||||
|
|
||||||
|
struct cref_hash_table {
|
||||||
|
struct bfd_hash_table root;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Forward declarations. */
|
||||||
|
|
||||||
|
static void output_one_cref (FILE *, struct cref_hash_entry *);
|
||||||
|
static void check_local_sym_xref (lang_input_statement_type *);
|
||||||
|
static bfd_boolean check_nocrossref (struct cref_hash_entry *, void *);
|
||||||
|
static void check_refs (const char *, bfd_boolean, asection *, bfd *,
|
||||||
|
struct lang_nocrossrefs *);
|
||||||
|
static void check_reloc_refs (bfd *, asection *, void *);
|
||||||
|
|
||||||
|
/* Look up an entry in the cref hash table. */
|
||||||
|
|
||||||
|
#define cref_hash_lookup(table, string, create, copy) \
|
||||||
|
((struct cref_hash_entry *) \
|
||||||
|
bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
|
||||||
|
|
||||||
|
/* Traverse the cref hash table. */
|
||||||
|
|
||||||
|
#define cref_hash_traverse(table, func, info) \
|
||||||
|
(bfd_hash_traverse \
|
||||||
|
(&(table)->root, \
|
||||||
|
(bfd_boolean (*) (struct bfd_hash_entry *, void *)) (func), \
|
||||||
|
(info)))
|
||||||
|
|
||||||
|
/* The cref hash table. */
|
||||||
|
|
||||||
|
static struct cref_hash_table cref_table;
|
||||||
|
|
||||||
|
/* Whether the cref hash table has been initialized. */
|
||||||
|
|
||||||
|
static bfd_boolean cref_initialized;
|
||||||
|
|
||||||
|
/* The number of symbols seen so far. */
|
||||||
|
|
||||||
|
static size_t cref_symcount;
|
||||||
|
|
||||||
|
/* Used to take a snapshot of the cref hash table when starting to
|
||||||
|
add syms from an as-needed library. */
|
||||||
|
static struct bfd_hash_entry **old_table;
|
||||||
|
static unsigned int old_size;
|
||||||
|
static unsigned int old_count;
|
||||||
|
static void *old_tab;
|
||||||
|
static void *alloc_mark;
|
||||||
|
static size_t tabsize, entsize, refsize;
|
||||||
|
static size_t old_symcount;
|
||||||
|
|
||||||
|
/* Create an entry in a cref hash table. */
|
||||||
|
|
||||||
|
static struct bfd_hash_entry *
|
||||||
|
cref_hash_newfunc (struct bfd_hash_entry *entry,
|
||||||
|
struct bfd_hash_table *table,
|
||||||
|
const char *string)
|
||||||
|
{
|
||||||
|
struct cref_hash_entry *ret = (struct cref_hash_entry *) entry;
|
||||||
|
|
||||||
|
/* Allocate the structure if it has not already been allocated by a
|
||||||
|
subclass. */
|
||||||
|
if (ret == NULL)
|
||||||
|
ret = ((struct cref_hash_entry *)
|
||||||
|
bfd_hash_allocate (table, sizeof (struct cref_hash_entry)));
|
||||||
|
if (ret == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Call the allocation method of the superclass. */
|
||||||
|
ret = ((struct cref_hash_entry *)
|
||||||
|
bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
|
||||||
|
if (ret != NULL)
|
||||||
|
{
|
||||||
|
/* Set local fields. */
|
||||||
|
ret->demangled = NULL;
|
||||||
|
ret->refs = NULL;
|
||||||
|
|
||||||
|
/* Keep a count of the number of entries created in the hash
|
||||||
|
table. */
|
||||||
|
++cref_symcount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ret->root;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a symbol to the cref hash table. This is called for every
|
||||||
|
global symbol that is seen during the link. */
|
||||||
|
|
||||||
|
void
|
||||||
|
add_cref (const char *name,
|
||||||
|
bfd *abfd,
|
||||||
|
asection *section,
|
||||||
|
bfd_vma value ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
struct cref_hash_entry *h;
|
||||||
|
struct cref_ref *r;
|
||||||
|
|
||||||
|
if (! cref_initialized)
|
||||||
|
{
|
||||||
|
if (!bfd_hash_table_init (&cref_table.root, cref_hash_newfunc,
|
||||||
|
sizeof (struct cref_hash_entry)))
|
||||||
|
einfo (_("%X%P: bfd_hash_table_init of cref table failed: %E\n"));
|
||||||
|
cref_initialized = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
h = cref_hash_lookup (&cref_table, name, TRUE, FALSE);
|
||||||
|
if (h == NULL)
|
||||||
|
einfo (_("%X%P: cref_hash_lookup failed: %E\n"));
|
||||||
|
|
||||||
|
for (r = h->refs; r != NULL; r = r->next)
|
||||||
|
if (r->abfd == abfd)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (r == NULL)
|
||||||
|
{
|
||||||
|
r = (struct cref_ref *) bfd_hash_allocate (&cref_table.root, sizeof *r);
|
||||||
|
if (r == NULL)
|
||||||
|
einfo (_("%X%P: cref alloc failed: %E\n"));
|
||||||
|
r->next = h->refs;
|
||||||
|
h->refs = r;
|
||||||
|
r->abfd = abfd;
|
||||||
|
r->def = FALSE;
|
||||||
|
r->common = FALSE;
|
||||||
|
r->undef = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bfd_is_und_section (section))
|
||||||
|
r->undef = TRUE;
|
||||||
|
else if (bfd_is_com_section (section))
|
||||||
|
r->common = TRUE;
|
||||||
|
else
|
||||||
|
r->def = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called before loading an as-needed library to take a snapshot of
|
||||||
|
the cref hash table, and after we have loaded or found that the
|
||||||
|
library was not needed. */
|
||||||
|
|
||||||
|
bfd_boolean
|
||||||
|
handle_asneeded_cref (bfd *abfd ATTRIBUTE_UNUSED,
|
||||||
|
enum notice_asneeded_action act)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (!cref_initialized)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (act == notice_as_needed)
|
||||||
|
{
|
||||||
|
char *old_ent, *old_ref;
|
||||||
|
|
||||||
|
for (i = 0; i < cref_table.root.size; i++)
|
||||||
|
{
|
||||||
|
struct bfd_hash_entry *p;
|
||||||
|
struct cref_hash_entry *c;
|
||||||
|
struct cref_ref *r;
|
||||||
|
|
||||||
|
for (p = cref_table.root.table[i]; p != NULL; p = p->next)
|
||||||
|
{
|
||||||
|
entsize += cref_table.root.entsize;
|
||||||
|
c = (struct cref_hash_entry *) p;
|
||||||
|
for (r = c->refs; r != NULL; r = r->next)
|
||||||
|
refsize += sizeof (struct cref_ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tabsize = cref_table.root.size * sizeof (struct bfd_hash_entry *);
|
||||||
|
old_tab = xmalloc (tabsize + entsize + refsize);
|
||||||
|
|
||||||
|
alloc_mark = bfd_hash_allocate (&cref_table.root, 1);
|
||||||
|
if (alloc_mark == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
memcpy (old_tab, cref_table.root.table, tabsize);
|
||||||
|
old_ent = (char *) old_tab + tabsize;
|
||||||
|
old_ref = (char *) old_ent + entsize;
|
||||||
|
old_table = cref_table.root.table;
|
||||||
|
old_size = cref_table.root.size;
|
||||||
|
old_count = cref_table.root.count;
|
||||||
|
old_symcount = cref_symcount;
|
||||||
|
|
||||||
|
for (i = 0; i < cref_table.root.size; i++)
|
||||||
|
{
|
||||||
|
struct bfd_hash_entry *p;
|
||||||
|
struct cref_hash_entry *c;
|
||||||
|
struct cref_ref *r;
|
||||||
|
|
||||||
|
for (p = cref_table.root.table[i]; p != NULL; p = p->next)
|
||||||
|
{
|
||||||
|
memcpy (old_ent, p, cref_table.root.entsize);
|
||||||
|
old_ent = (char *) old_ent + cref_table.root.entsize;
|
||||||
|
c = (struct cref_hash_entry *) p;
|
||||||
|
for (r = c->refs; r != NULL; r = r->next)
|
||||||
|
{
|
||||||
|
memcpy (old_ref, r, sizeof (struct cref_ref));
|
||||||
|
old_ref = (char *) old_ref + sizeof (struct cref_ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (act == notice_not_needed)
|
||||||
|
{
|
||||||
|
char *old_ent, *old_ref;
|
||||||
|
|
||||||
|
if (old_tab == NULL)
|
||||||
|
{
|
||||||
|
/* The only way old_tab can be NULL is if the cref hash table
|
||||||
|
had not been initialised when notice_as_needed. */
|
||||||
|
bfd_hash_table_free (&cref_table.root);
|
||||||
|
cref_initialized = FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
old_ent = (char *) old_tab + tabsize;
|
||||||
|
old_ref = (char *) old_ent + entsize;
|
||||||
|
cref_table.root.table = old_table;
|
||||||
|
cref_table.root.size = old_size;
|
||||||
|
cref_table.root.count = old_count;
|
||||||
|
memcpy (cref_table.root.table, old_tab, tabsize);
|
||||||
|
cref_symcount = old_symcount;
|
||||||
|
|
||||||
|
for (i = 0; i < cref_table.root.size; i++)
|
||||||
|
{
|
||||||
|
struct bfd_hash_entry *p;
|
||||||
|
struct cref_hash_entry *c;
|
||||||
|
struct cref_ref *r;
|
||||||
|
|
||||||
|
for (p = cref_table.root.table[i]; p != NULL; p = p->next)
|
||||||
|
{
|
||||||
|
memcpy (p, old_ent, cref_table.root.entsize);
|
||||||
|
old_ent = (char *) old_ent + cref_table.root.entsize;
|
||||||
|
c = (struct cref_hash_entry *) p;
|
||||||
|
for (r = c->refs; r != NULL; r = r->next)
|
||||||
|
{
|
||||||
|
memcpy (r, old_ref, sizeof (struct cref_ref));
|
||||||
|
old_ref = (char *) old_ref + sizeof (struct cref_ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
objalloc_free_block ((struct objalloc *) cref_table.root.memory,
|
||||||
|
alloc_mark);
|
||||||
|
}
|
||||||
|
else if (act != notice_needed)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
free (old_tab);
|
||||||
|
old_tab = NULL;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the addresses of the hash table entries into an array. This
|
||||||
|
is called via cref_hash_traverse. We also fill in the demangled
|
||||||
|
name. */
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
cref_fill_array (struct cref_hash_entry *h, void *data)
|
||||||
|
{
|
||||||
|
struct cref_hash_entry ***pph = (struct cref_hash_entry ***) data;
|
||||||
|
|
||||||
|
ASSERT (h->demangled == NULL);
|
||||||
|
h->demangled = bfd_demangle (link_info.output_bfd, h->root.string,
|
||||||
|
DMGL_ANSI | DMGL_PARAMS);
|
||||||
|
if (h->demangled == NULL)
|
||||||
|
h->demangled = h->root.string;
|
||||||
|
|
||||||
|
**pph = h;
|
||||||
|
|
||||||
|
++*pph;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sort an array of cref hash table entries by name. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
cref_sort_array (const void *a1, const void *a2)
|
||||||
|
{
|
||||||
|
const struct cref_hash_entry * const *p1 =
|
||||||
|
(const struct cref_hash_entry * const *) a1;
|
||||||
|
const struct cref_hash_entry * const *p2 =
|
||||||
|
(const struct cref_hash_entry * const *) a2;
|
||||||
|
|
||||||
|
return strcmp ((*p1)->demangled, (*p2)->demangled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write out the cref table. */
|
||||||
|
|
||||||
|
#define FILECOL (50)
|
||||||
|
|
||||||
|
void
|
||||||
|
output_cref (FILE *fp)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
struct cref_hash_entry **csyms, **csym_fill, **csym, **csym_end;
|
||||||
|
const char *msg;
|
||||||
|
|
||||||
|
fprintf (fp, _("\nCross Reference Table\n\n"));
|
||||||
|
msg = _("Symbol");
|
||||||
|
fprintf (fp, "%s", msg);
|
||||||
|
len = strlen (msg);
|
||||||
|
while (len < FILECOL)
|
||||||
|
{
|
||||||
|
putc (' ', fp);
|
||||||
|
++len;
|
||||||
|
}
|
||||||
|
fprintf (fp, _("File\n"));
|
||||||
|
|
||||||
|
if (! cref_initialized)
|
||||||
|
{
|
||||||
|
fprintf (fp, _("No symbols\n"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
csyms = (struct cref_hash_entry **) xmalloc (cref_symcount * sizeof (*csyms));
|
||||||
|
|
||||||
|
csym_fill = csyms;
|
||||||
|
cref_hash_traverse (&cref_table, cref_fill_array, &csym_fill);
|
||||||
|
ASSERT ((size_t) (csym_fill - csyms) == cref_symcount);
|
||||||
|
|
||||||
|
qsort (csyms, cref_symcount, sizeof (*csyms), cref_sort_array);
|
||||||
|
|
||||||
|
csym_end = csyms + cref_symcount;
|
||||||
|
for (csym = csyms; csym < csym_end; csym++)
|
||||||
|
output_one_cref (fp, *csym);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Output one entry in the cross reference table. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
output_one_cref (FILE *fp, struct cref_hash_entry *h)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
struct bfd_link_hash_entry *hl;
|
||||||
|
struct cref_ref *r;
|
||||||
|
|
||||||
|
hl = bfd_link_hash_lookup (link_info.hash, h->root.string, FALSE,
|
||||||
|
FALSE, TRUE);
|
||||||
|
if (hl == NULL)
|
||||||
|
einfo ("%P: symbol `%T' missing from main hash table\n",
|
||||||
|
h->root.string);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If this symbol is defined in a dynamic object but never
|
||||||
|
referenced by a normal object, then don't print it. */
|
||||||
|
if (hl->type == bfd_link_hash_defined)
|
||||||
|
{
|
||||||
|
if (hl->u.def.section->output_section == NULL)
|
||||||
|
return;
|
||||||
|
if (hl->u.def.section->owner != NULL
|
||||||
|
&& (hl->u.def.section->owner->flags & DYNAMIC) != 0)
|
||||||
|
{
|
||||||
|
for (r = h->refs; r != NULL; r = r->next)
|
||||||
|
if ((r->abfd->flags & DYNAMIC) == 0)
|
||||||
|
break;
|
||||||
|
if (r == NULL)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf (fp, "%s ", h->demangled);
|
||||||
|
len = strlen (h->demangled) + 1;
|
||||||
|
|
||||||
|
for (r = h->refs; r != NULL; r = r->next)
|
||||||
|
{
|
||||||
|
if (r->def)
|
||||||
|
{
|
||||||
|
while (len < FILECOL)
|
||||||
|
{
|
||||||
|
putc (' ', fp);
|
||||||
|
++len;
|
||||||
|
}
|
||||||
|
lfinfo (fp, "%B\n", r->abfd);
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (r = h->refs; r != NULL; r = r->next)
|
||||||
|
{
|
||||||
|
if (r->common)
|
||||||
|
{
|
||||||
|
while (len < FILECOL)
|
||||||
|
{
|
||||||
|
putc (' ', fp);
|
||||||
|
++len;
|
||||||
|
}
|
||||||
|
lfinfo (fp, "%B\n", r->abfd);
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (r = h->refs; r != NULL; r = r->next)
|
||||||
|
{
|
||||||
|
if (! r->def && ! r->common)
|
||||||
|
{
|
||||||
|
while (len < FILECOL)
|
||||||
|
{
|
||||||
|
putc (' ', fp);
|
||||||
|
++len;
|
||||||
|
}
|
||||||
|
lfinfo (fp, "%B\n", r->abfd);
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT (len == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for prohibited cross references. */
|
||||||
|
|
||||||
|
void
|
||||||
|
check_nocrossrefs (void)
|
||||||
|
{
|
||||||
|
if (! cref_initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cref_hash_traverse (&cref_table, check_nocrossref, NULL);
|
||||||
|
|
||||||
|
lang_for_each_file (check_local_sym_xref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for prohibited cross references to local and section symbols. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_local_sym_xref (lang_input_statement_type *statement)
|
||||||
|
{
|
||||||
|
bfd *abfd;
|
||||||
|
asymbol **syms;
|
||||||
|
|
||||||
|
abfd = statement->the_bfd;
|
||||||
|
if (abfd == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!bfd_generic_link_read_symbols (abfd))
|
||||||
|
einfo (_("%B%F: could not read symbols: %E\n"), abfd);
|
||||||
|
|
||||||
|
for (syms = bfd_get_outsymbols (abfd); *syms; ++syms)
|
||||||
|
{
|
||||||
|
asymbol *sym = *syms;
|
||||||
|
if (sym->flags & (BSF_GLOBAL | BSF_WARNING | BSF_INDIRECT | BSF_FILE))
|
||||||
|
continue;
|
||||||
|
if ((sym->flags & (BSF_LOCAL | BSF_SECTION_SYM)) != 0
|
||||||
|
&& sym->section->output_section != NULL)
|
||||||
|
{
|
||||||
|
const char *outsecname, *symname;
|
||||||
|
struct lang_nocrossrefs *ncrs;
|
||||||
|
struct lang_nocrossref *ncr;
|
||||||
|
|
||||||
|
outsecname = sym->section->output_section->name;
|
||||||
|
symname = NULL;
|
||||||
|
if ((sym->flags & BSF_SECTION_SYM) == 0)
|
||||||
|
symname = sym->name;
|
||||||
|
for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
|
||||||
|
for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
|
||||||
|
if (strcmp (ncr->name, outsecname) == 0)
|
||||||
|
check_refs (symname, FALSE, sym->section, abfd, ncrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check one symbol to see if it is a prohibited cross reference. */
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
check_nocrossref (struct cref_hash_entry *h, void *ignore ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
struct bfd_link_hash_entry *hl;
|
||||||
|
asection *defsec;
|
||||||
|
const char *defsecname;
|
||||||
|
struct lang_nocrossrefs *ncrs;
|
||||||
|
struct lang_nocrossref *ncr;
|
||||||
|
struct cref_ref *ref;
|
||||||
|
|
||||||
|
hl = bfd_link_hash_lookup (link_info.hash, h->root.string, FALSE,
|
||||||
|
FALSE, TRUE);
|
||||||
|
if (hl == NULL)
|
||||||
|
{
|
||||||
|
einfo (_("%P: symbol `%T' missing from main hash table\n"),
|
||||||
|
h->root.string);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hl->type != bfd_link_hash_defined
|
||||||
|
&& hl->type != bfd_link_hash_defweak)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
defsec = hl->u.def.section->output_section;
|
||||||
|
if (defsec == NULL)
|
||||||
|
return TRUE;
|
||||||
|
defsecname = bfd_get_section_name (defsec->owner, defsec);
|
||||||
|
|
||||||
|
for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
|
||||||
|
for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
|
||||||
|
if (strcmp (ncr->name, defsecname) == 0)
|
||||||
|
for (ref = h->refs; ref != NULL; ref = ref->next)
|
||||||
|
check_refs (hl->root.string, TRUE, hl->u.def.section,
|
||||||
|
ref->abfd, ncrs);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The struct is used to pass information from check_refs to
|
||||||
|
check_reloc_refs through bfd_map_over_sections. */
|
||||||
|
|
||||||
|
struct check_refs_info {
|
||||||
|
const char *sym_name;
|
||||||
|
asection *defsec;
|
||||||
|
struct lang_nocrossrefs *ncrs;
|
||||||
|
asymbol **asymbols;
|
||||||
|
bfd_boolean global;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This function is called for each symbol defined in a section which
|
||||||
|
prohibits cross references. We need to look through all references
|
||||||
|
to this symbol, and ensure that the references are not from
|
||||||
|
prohibited sections. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_refs (const char *name,
|
||||||
|
bfd_boolean global,
|
||||||
|
asection *sec,
|
||||||
|
bfd *abfd,
|
||||||
|
struct lang_nocrossrefs *ncrs)
|
||||||
|
{
|
||||||
|
struct check_refs_info info;
|
||||||
|
|
||||||
|
/* We need to look through the relocations for this BFD, to see
|
||||||
|
if any of the relocations which refer to this symbol are from
|
||||||
|
a prohibited section. Note that we need to do this even for
|
||||||
|
the BFD in which the symbol is defined, since even a single
|
||||||
|
BFD might contain a prohibited cross reference. */
|
||||||
|
|
||||||
|
if (!bfd_generic_link_read_symbols (abfd))
|
||||||
|
einfo (_("%B%F: could not read symbols: %E\n"), abfd);
|
||||||
|
|
||||||
|
info.sym_name = name;
|
||||||
|
info.global = global;
|
||||||
|
info.defsec = sec;
|
||||||
|
info.ncrs = ncrs;
|
||||||
|
info.asymbols = bfd_get_outsymbols (abfd);
|
||||||
|
bfd_map_over_sections (abfd, check_reloc_refs, &info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is called via bfd_map_over_sections. INFO->SYM_NAME is a symbol
|
||||||
|
defined in INFO->DEFSECNAME. If this section maps into any of the
|
||||||
|
sections listed in INFO->NCRS, other than INFO->DEFSECNAME, then we
|
||||||
|
look through the relocations. If any of the relocations are to
|
||||||
|
INFO->SYM_NAME, then we report a prohibited cross reference error. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_reloc_refs (bfd *abfd, asection *sec, void *iarg)
|
||||||
|
{
|
||||||
|
struct check_refs_info *info = (struct check_refs_info *) iarg;
|
||||||
|
asection *outsec;
|
||||||
|
const char *outsecname;
|
||||||
|
asection *outdefsec;
|
||||||
|
const char *outdefsecname;
|
||||||
|
struct lang_nocrossref *ncr;
|
||||||
|
const char *symname;
|
||||||
|
bfd_boolean global;
|
||||||
|
long relsize;
|
||||||
|
arelent **relpp;
|
||||||
|
long relcount;
|
||||||
|
arelent **p, **pend;
|
||||||
|
|
||||||
|
outsec = sec->output_section;
|
||||||
|
outsecname = bfd_get_section_name (outsec->owner, outsec);
|
||||||
|
|
||||||
|
outdefsec = info->defsec->output_section;
|
||||||
|
outdefsecname = bfd_get_section_name (outdefsec->owner, outdefsec);
|
||||||
|
|
||||||
|
/* The section where the symbol is defined is permitted. */
|
||||||
|
if (strcmp (outsecname, outdefsecname) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (ncr = info->ncrs->list; ncr != NULL; ncr = ncr->next)
|
||||||
|
if (strcmp (outsecname, ncr->name) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (ncr == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* This section is one for which cross references are prohibited.
|
||||||
|
Look through the relocations, and see if any of them are to
|
||||||
|
INFO->SYM_NAME. If INFO->SYMNAME is NULL, check for relocations
|
||||||
|
against the section symbol. If INFO->GLOBAL is TRUE, the
|
||||||
|
definition is global, check for relocations against the global
|
||||||
|
symbols. Otherwise check for relocations against the local and
|
||||||
|
section symbols. */
|
||||||
|
|
||||||
|
symname = info->sym_name;
|
||||||
|
global = info->global;
|
||||||
|
|
||||||
|
relsize = bfd_get_reloc_upper_bound (abfd, sec);
|
||||||
|
if (relsize < 0)
|
||||||
|
einfo (_("%B%F: could not read relocs: %E\n"), abfd);
|
||||||
|
if (relsize == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
relpp = (arelent **) xmalloc (relsize);
|
||||||
|
relcount = bfd_canonicalize_reloc (abfd, sec, relpp, info->asymbols);
|
||||||
|
if (relcount < 0)
|
||||||
|
einfo (_("%B%F: could not read relocs: %E\n"), abfd);
|
||||||
|
|
||||||
|
p = relpp;
|
||||||
|
pend = p + relcount;
|
||||||
|
for (; p < pend && *p != NULL; p++)
|
||||||
|
{
|
||||||
|
arelent *q = *p;
|
||||||
|
|
||||||
|
if (q->sym_ptr_ptr != NULL
|
||||||
|
&& *q->sym_ptr_ptr != NULL
|
||||||
|
&& ((global
|
||||||
|
&& (bfd_is_und_section (bfd_get_section (*q->sym_ptr_ptr))
|
||||||
|
|| bfd_is_com_section (bfd_get_section (*q->sym_ptr_ptr))
|
||||||
|
|| ((*q->sym_ptr_ptr)->flags & (BSF_GLOBAL
|
||||||
|
| BSF_WEAK)) != 0))
|
||||||
|
|| (!global
|
||||||
|
&& ((*q->sym_ptr_ptr)->flags & (BSF_LOCAL
|
||||||
|
| BSF_SECTION_SYM)) != 0
|
||||||
|
&& bfd_get_section (*q->sym_ptr_ptr) == info->defsec))
|
||||||
|
&& (symname != NULL
|
||||||
|
? strcmp (bfd_asymbol_name (*q->sym_ptr_ptr), symname) == 0
|
||||||
|
: ((*q->sym_ptr_ptr)->flags & BSF_SECTION_SYM) != 0))
|
||||||
|
{
|
||||||
|
/* We found a reloc for the symbol. The symbol is defined
|
||||||
|
in OUTSECNAME. This reloc is from a section which is
|
||||||
|
mapped into a section from which references to OUTSECNAME
|
||||||
|
are prohibited. We must report an error. */
|
||||||
|
einfo (_("%X%C: prohibited cross reference from %s to `%T' in %s\n"),
|
||||||
|
abfd, sec, q->address, outsecname,
|
||||||
|
bfd_asymbol_name (*q->sym_ptr_ptr), outdefsecname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free (relpp);
|
||||||
|
}
|
378
contrib/toolchain/binutils/ld/ldctor.c
Normal file
378
contrib/toolchain/binutils/ld/ldctor.c
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
/* ldctor.c -- constructor support routines
|
||||||
|
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||||
|
2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
By Steve Chamberlain <sac@cygnus.com>
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#include "sysdep.h"
|
||||||
|
#include "bfd.h"
|
||||||
|
#include "bfdlink.h"
|
||||||
|
#include "safe-ctype.h"
|
||||||
|
|
||||||
|
#include "ld.h"
|
||||||
|
#include "ldexp.h"
|
||||||
|
#include "ldlang.h"
|
||||||
|
#include "ldmisc.h"
|
||||||
|
#include <ldgram.h>
|
||||||
|
#include "ldmain.h"
|
||||||
|
#include "ldctor.h"
|
||||||
|
|
||||||
|
/* The list of statements needed to handle constructors. These are
|
||||||
|
invoked by the command CONSTRUCTORS in the linker script. */
|
||||||
|
lang_statement_list_type constructor_list;
|
||||||
|
|
||||||
|
/* Whether the constructors should be sorted. Note that this is
|
||||||
|
global for the entire link; we assume that there is only a single
|
||||||
|
CONSTRUCTORS command in the linker script. */
|
||||||
|
bfd_boolean constructors_sorted;
|
||||||
|
|
||||||
|
/* The sets we have seen. */
|
||||||
|
struct set_info *sets;
|
||||||
|
|
||||||
|
/* Add an entry to a set. H is the entry in the linker hash table.
|
||||||
|
RELOC is the relocation to use for an entry in the set. SECTION
|
||||||
|
and VALUE are the value to add. This is called during the first
|
||||||
|
phase of the link, when we are still gathering symbols together.
|
||||||
|
We just record the information now. The ldctor_build_sets
|
||||||
|
function will construct the sets. */
|
||||||
|
|
||||||
|
void
|
||||||
|
ldctor_add_set_entry (struct bfd_link_hash_entry *h,
|
||||||
|
bfd_reloc_code_real_type reloc,
|
||||||
|
const char *name,
|
||||||
|
asection *section,
|
||||||
|
bfd_vma value)
|
||||||
|
{
|
||||||
|
struct set_info *p;
|
||||||
|
struct set_element *e;
|
||||||
|
struct set_element **epp;
|
||||||
|
|
||||||
|
for (p = sets; p != NULL; p = p->next)
|
||||||
|
if (p->h == h)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (p == NULL)
|
||||||
|
{
|
||||||
|
p = (struct set_info *) xmalloc (sizeof (struct set_info));
|
||||||
|
p->next = sets;
|
||||||
|
sets = p;
|
||||||
|
p->h = h;
|
||||||
|
p->reloc = reloc;
|
||||||
|
p->count = 0;
|
||||||
|
p->elements = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (p->reloc != reloc)
|
||||||
|
{
|
||||||
|
einfo (_("%P%X: Different relocs used in set %s\n"),
|
||||||
|
h->root.string);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't permit a set to be constructed from different object
|
||||||
|
file formats. The same reloc may have different results. We
|
||||||
|
actually could sometimes handle this, but the case is
|
||||||
|
unlikely to ever arise. Sometimes constructor symbols are in
|
||||||
|
unusual sections, such as the absolute section--this appears
|
||||||
|
to be the case in Linux a.out--and in such cases we just
|
||||||
|
assume everything is OK. */
|
||||||
|
if (p->elements != NULL
|
||||||
|
&& section->owner != NULL
|
||||||
|
&& p->elements->section->owner != NULL
|
||||||
|
&& strcmp (bfd_get_target (section->owner),
|
||||||
|
bfd_get_target (p->elements->section->owner)) != 0)
|
||||||
|
{
|
||||||
|
einfo (_("%P%X: Different object file formats composing set %s\n"),
|
||||||
|
h->root.string);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
e = (struct set_element *) xmalloc (sizeof (struct set_element));
|
||||||
|
e->next = NULL;
|
||||||
|
e->name = name;
|
||||||
|
e->section = section;
|
||||||
|
e->value = value;
|
||||||
|
|
||||||
|
for (epp = &p->elements; *epp != NULL; epp = &(*epp)->next)
|
||||||
|
;
|
||||||
|
*epp = e;
|
||||||
|
|
||||||
|
++p->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the priority of a g++ global constructor or destructor from the
|
||||||
|
symbol name. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
ctor_prio (const char *name)
|
||||||
|
{
|
||||||
|
/* The name will look something like _GLOBAL_$I$65535$test02__Fv.
|
||||||
|
There might be extra leading underscores, and the $ characters
|
||||||
|
might be something else. The I might be a D. */
|
||||||
|
|
||||||
|
while (*name == '_')
|
||||||
|
++name;
|
||||||
|
|
||||||
|
if (! CONST_STRNEQ (name, "GLOBAL_"))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
name += sizeof "GLOBAL_" - 1;
|
||||||
|
|
||||||
|
if (name[0] != name[2])
|
||||||
|
return -1;
|
||||||
|
if (name[1] != 'I' && name[1] != 'D')
|
||||||
|
return -1;
|
||||||
|
if (! ISDIGIT (name[3]))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return atoi (name + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function is used to sort constructor elements by priority. It
|
||||||
|
is called via qsort. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
ctor_cmp (const void *p1, const void *p2)
|
||||||
|
{
|
||||||
|
const struct set_element * const *pe1 =
|
||||||
|
(const struct set_element * const *) p1;
|
||||||
|
const struct set_element * const *pe2 =
|
||||||
|
(const struct set_element * const *) p2;
|
||||||
|
const char *n1;
|
||||||
|
const char *n2;
|
||||||
|
int prio1;
|
||||||
|
int prio2;
|
||||||
|
|
||||||
|
n1 = (*pe1)->name;
|
||||||
|
if (n1 == NULL)
|
||||||
|
n1 = "";
|
||||||
|
n2 = (*pe2)->name;
|
||||||
|
if (n2 == NULL)
|
||||||
|
n2 = "";
|
||||||
|
|
||||||
|
/* We need to sort in reverse order by priority. When two
|
||||||
|
constructors have the same priority, we should maintain their
|
||||||
|
current relative position. */
|
||||||
|
|
||||||
|
prio1 = ctor_prio (n1);
|
||||||
|
prio2 = ctor_prio (n2);
|
||||||
|
|
||||||
|
/* We sort in reverse order because that is what g++ expects. */
|
||||||
|
if (prio1 < prio2)
|
||||||
|
return 1;
|
||||||
|
else if (prio1 > prio2)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Force a stable sort. */
|
||||||
|
|
||||||
|
if (pe1 < pe2)
|
||||||
|
return -1;
|
||||||
|
else if (pe1 > pe2)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function is called after the first phase of the link and
|
||||||
|
before the second phase. At this point all set information has
|
||||||
|
been gathered. We now put the statements to build the sets
|
||||||
|
themselves into constructor_list. */
|
||||||
|
|
||||||
|
void
|
||||||
|
ldctor_build_sets (void)
|
||||||
|
{
|
||||||
|
static bfd_boolean called;
|
||||||
|
bfd_boolean header_printed;
|
||||||
|
struct set_info *p;
|
||||||
|
|
||||||
|
/* The emulation code may call us directly, but we only want to do
|
||||||
|
this once. */
|
||||||
|
if (called)
|
||||||
|
return;
|
||||||
|
called = TRUE;
|
||||||
|
|
||||||
|
if (constructors_sorted)
|
||||||
|
{
|
||||||
|
for (p = sets; p != NULL; p = p->next)
|
||||||
|
{
|
||||||
|
int c, i;
|
||||||
|
struct set_element *e;
|
||||||
|
struct set_element **array;
|
||||||
|
|
||||||
|
if (p->elements == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
c = 0;
|
||||||
|
for (e = p->elements; e != NULL; e = e->next)
|
||||||
|
++c;
|
||||||
|
|
||||||
|
array = (struct set_element **) xmalloc (c * sizeof *array);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
for (e = p->elements; e != NULL; e = e->next)
|
||||||
|
{
|
||||||
|
array[i] = e;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
qsort (array, c, sizeof *array, ctor_cmp);
|
||||||
|
|
||||||
|
e = array[0];
|
||||||
|
p->elements = e;
|
||||||
|
for (i = 0; i < c - 1; i++)
|
||||||
|
array[i]->next = array[i + 1];
|
||||||
|
array[i]->next = NULL;
|
||||||
|
|
||||||
|
free (array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lang_list_init (&constructor_list);
|
||||||
|
push_stat_ptr (&constructor_list);
|
||||||
|
|
||||||
|
header_printed = FALSE;
|
||||||
|
for (p = sets; p != NULL; p = p->next)
|
||||||
|
{
|
||||||
|
struct set_element *e;
|
||||||
|
reloc_howto_type *howto;
|
||||||
|
int reloc_size, size;
|
||||||
|
|
||||||
|
/* If the symbol is defined, we may have been invoked from
|
||||||
|
collect, and the sets may already have been built, so we do
|
||||||
|
not do anything. */
|
||||||
|
if (p->h->type == bfd_link_hash_defined
|
||||||
|
|| p->h->type == bfd_link_hash_defweak)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* For each set we build:
|
||||||
|
set:
|
||||||
|
.long number_of_elements
|
||||||
|
.long element0
|
||||||
|
...
|
||||||
|
.long elementN
|
||||||
|
.long 0
|
||||||
|
except that we use the right size instead of .long. When
|
||||||
|
generating relocatable output, we generate relocs instead of
|
||||||
|
addresses. */
|
||||||
|
howto = bfd_reloc_type_lookup (link_info.output_bfd, p->reloc);
|
||||||
|
if (howto == NULL)
|
||||||
|
{
|
||||||
|
if (link_info.relocatable)
|
||||||
|
{
|
||||||
|
einfo (_("%P%X: %s does not support reloc %s for set %s\n"),
|
||||||
|
bfd_get_target (link_info.output_bfd),
|
||||||
|
bfd_get_reloc_code_name (p->reloc),
|
||||||
|
p->h->root.string);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this is not a relocatable link, all we need is the
|
||||||
|
size, which we can get from the input BFD. */
|
||||||
|
if (p->elements->section->owner != NULL)
|
||||||
|
howto = bfd_reloc_type_lookup (p->elements->section->owner,
|
||||||
|
p->reloc);
|
||||||
|
if (howto == NULL)
|
||||||
|
{
|
||||||
|
einfo (_("%P%X: %s does not support reloc %s for set %s\n"),
|
||||||
|
bfd_get_target (p->elements->section->owner),
|
||||||
|
bfd_get_reloc_code_name (p->reloc),
|
||||||
|
p->h->root.string);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reloc_size = bfd_get_reloc_size (howto);
|
||||||
|
switch (reloc_size)
|
||||||
|
{
|
||||||
|
case 1: size = BYTE; break;
|
||||||
|
case 2: size = SHORT; break;
|
||||||
|
case 4: size = LONG; break;
|
||||||
|
case 8:
|
||||||
|
if (howto->complain_on_overflow == complain_overflow_signed)
|
||||||
|
size = SQUAD;
|
||||||
|
else
|
||||||
|
size = QUAD;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
einfo (_("%P%X: Unsupported size %d for set %s\n"),
|
||||||
|
bfd_get_reloc_size (howto), p->h->root.string);
|
||||||
|
size = LONG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lang_add_assignment (exp_assign (".",
|
||||||
|
exp_unop (ALIGN_K,
|
||||||
|
exp_intop (reloc_size)),
|
||||||
|
FALSE));
|
||||||
|
lang_add_assignment (exp_assign (p->h->root.string,
|
||||||
|
exp_nameop (NAME, "."),
|
||||||
|
FALSE));
|
||||||
|
lang_add_data (size, exp_intop (p->count));
|
||||||
|
|
||||||
|
for (e = p->elements; e != NULL; e = e->next)
|
||||||
|
{
|
||||||
|
if (config.map_file != NULL)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (! header_printed)
|
||||||
|
{
|
||||||
|
minfo (_("\nSet Symbol\n\n"));
|
||||||
|
header_printed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
minfo ("%s", p->h->root.string);
|
||||||
|
len = strlen (p->h->root.string);
|
||||||
|
|
||||||
|
if (len >= 19)
|
||||||
|
{
|
||||||
|
print_nl ();
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
while (len < 20)
|
||||||
|
{
|
||||||
|
print_space ();
|
||||||
|
++len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e->name != NULL)
|
||||||
|
minfo ("%T\n", e->name);
|
||||||
|
else
|
||||||
|
minfo ("%G\n", e->section->owner, e->section, e->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Need SEC_KEEP for --gc-sections. */
|
||||||
|
if (! bfd_is_abs_section (e->section))
|
||||||
|
e->section->flags |= SEC_KEEP;
|
||||||
|
|
||||||
|
if (link_info.relocatable)
|
||||||
|
lang_add_reloc (p->reloc, howto, e->section, e->name,
|
||||||
|
exp_intop (e->value));
|
||||||
|
else
|
||||||
|
lang_add_data (size, exp_relop (e->section, e->value));
|
||||||
|
}
|
||||||
|
|
||||||
|
lang_add_data (size, exp_intop (0));
|
||||||
|
}
|
||||||
|
|
||||||
|
pop_stat_ptr ();
|
||||||
|
}
|
60
contrib/toolchain/binutils/ld/ldctor.h
Normal file
60
contrib/toolchain/binutils/ld/ldctor.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* ldctor.h - linker constructor support
|
||||||
|
Copyright 1991, 1992, 1993, 1994, 1995, 1998, 2000, 2002, 2003, 2005,
|
||||||
|
2007, 2008 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#ifndef LDCTOR_H
|
||||||
|
#define LDCTOR_H
|
||||||
|
|
||||||
|
/* List of statements needed to handle constructors */
|
||||||
|
extern lang_statement_list_type constructor_list;
|
||||||
|
|
||||||
|
/* Whether the constructors should be sorted. Note that this is
|
||||||
|
global for the entire link; we assume that there is only a single
|
||||||
|
CONSTRUCTORS command in the linker script. */
|
||||||
|
extern bfd_boolean constructors_sorted;
|
||||||
|
|
||||||
|
/* We keep a list of these structures for each set we build. */
|
||||||
|
|
||||||
|
struct set_info {
|
||||||
|
struct set_info *next; /* Next set. */
|
||||||
|
struct bfd_link_hash_entry *h; /* Hash table entry. */
|
||||||
|
bfd_reloc_code_real_type reloc; /* Reloc to use for an entry. */
|
||||||
|
size_t count; /* Number of elements. */
|
||||||
|
struct set_element *elements; /* Elements in set. */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct set_element {
|
||||||
|
struct set_element *next; /* Next element. */
|
||||||
|
const char *name; /* Name in set (may be NULL). */
|
||||||
|
asection *section; /* Section of value in set. */
|
||||||
|
bfd_vma value; /* Value in set. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The sets we have seen. */
|
||||||
|
|
||||||
|
extern struct set_info *sets;
|
||||||
|
|
||||||
|
extern void ldctor_add_set_entry
|
||||||
|
(struct bfd_link_hash_entry *, bfd_reloc_code_real_type, const char *,
|
||||||
|
asection *, bfd_vma);
|
||||||
|
extern void ldctor_build_sets
|
||||||
|
(void);
|
||||||
|
|
||||||
|
#endif
|
6
contrib/toolchain/binutils/ld/ldemul-list.h
Normal file
6
contrib/toolchain/binutils/ld/ldemul-list.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/* This file is automatically generated. DO NOT EDIT! */
|
||||||
|
extern ld_emulation_xfer_type ld_i386pe_emulation;
|
||||||
|
|
||||||
|
#define EMULATION_LIST \
|
||||||
|
&ld_i386pe_emulation, \
|
||||||
|
0
|
352
contrib/toolchain/binutils/ld/ldemul.c
Normal file
352
contrib/toolchain/binutils/ld/ldemul.c
Normal file
@ -0,0 +1,352 @@
|
|||||||
|
/* ldemul.c -- clearing house for ld emulation states
|
||||||
|
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||||
|
2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010, 2011, 2012
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#include "sysdep.h"
|
||||||
|
#include "bfd.h"
|
||||||
|
#include "getopt.h"
|
||||||
|
#include "bfdlink.h"
|
||||||
|
|
||||||
|
#include "ld.h"
|
||||||
|
#include "ldmisc.h"
|
||||||
|
#include "ldexp.h"
|
||||||
|
#include "ldlang.h"
|
||||||
|
#include "ldfile.h"
|
||||||
|
#include "ldemul.h"
|
||||||
|
#include "ldmain.h"
|
||||||
|
#include "ldemul-list.h"
|
||||||
|
|
||||||
|
static ld_emulation_xfer_type *ld_emulation;
|
||||||
|
|
||||||
|
void
|
||||||
|
ldemul_hll (char *name)
|
||||||
|
{
|
||||||
|
ld_emulation->hll (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldemul_syslib (char *name)
|
||||||
|
{
|
||||||
|
ld_emulation->syslib (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldemul_after_parse (void)
|
||||||
|
{
|
||||||
|
ld_emulation->after_parse ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldemul_before_parse (void)
|
||||||
|
{
|
||||||
|
ld_emulation->before_parse ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldemul_after_open (void)
|
||||||
|
{
|
||||||
|
ld_emulation->after_open ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldemul_after_allocation (void)
|
||||||
|
{
|
||||||
|
ld_emulation->after_allocation ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldemul_before_allocation (void)
|
||||||
|
{
|
||||||
|
ld_emulation->before_allocation ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldemul_set_output_arch (void)
|
||||||
|
{
|
||||||
|
ld_emulation->set_output_arch ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldemul_finish (void)
|
||||||
|
{
|
||||||
|
ld_emulation->finish ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldemul_set_symbols (void)
|
||||||
|
{
|
||||||
|
if (ld_emulation->set_symbols)
|
||||||
|
ld_emulation->set_symbols ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldemul_create_output_section_statements (void)
|
||||||
|
{
|
||||||
|
if (ld_emulation->create_output_section_statements)
|
||||||
|
ld_emulation->create_output_section_statements ();
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
ldemul_get_script (int *isfile)
|
||||||
|
{
|
||||||
|
return ld_emulation->get_script (isfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
bfd_boolean
|
||||||
|
ldemul_open_dynamic_archive (const char *arch, search_dirs_type *search,
|
||||||
|
lang_input_statement_type *entry)
|
||||||
|
{
|
||||||
|
if (ld_emulation->open_dynamic_archive)
|
||||||
|
return (*ld_emulation->open_dynamic_archive) (arch, search, entry);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
lang_output_section_statement_type *
|
||||||
|
ldemul_place_orphan (asection *s, const char *name, int constraint)
|
||||||
|
{
|
||||||
|
if (ld_emulation->place_orphan)
|
||||||
|
return (*ld_emulation->place_orphan) (s, name, constraint);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldemul_add_options (int ns, char **shortopts, int nl,
|
||||||
|
struct option **longopts, int nrl,
|
||||||
|
struct option **really_longopts)
|
||||||
|
{
|
||||||
|
if (ld_emulation->add_options)
|
||||||
|
(*ld_emulation->add_options) (ns, shortopts, nl, longopts,
|
||||||
|
nrl, really_longopts);
|
||||||
|
}
|
||||||
|
|
||||||
|
bfd_boolean
|
||||||
|
ldemul_handle_option (int optc)
|
||||||
|
{
|
||||||
|
if (ld_emulation->handle_option)
|
||||||
|
return (*ld_emulation->handle_option) (optc);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bfd_boolean
|
||||||
|
ldemul_parse_args (int argc, char **argv)
|
||||||
|
{
|
||||||
|
/* Try and use the emulation parser if there is one. */
|
||||||
|
if (ld_emulation->parse_args)
|
||||||
|
return (*ld_emulation->parse_args) (argc, argv);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let the emulation code handle an unrecognized file. */
|
||||||
|
|
||||||
|
bfd_boolean
|
||||||
|
ldemul_unrecognized_file (lang_input_statement_type *entry)
|
||||||
|
{
|
||||||
|
if (ld_emulation->unrecognized_file)
|
||||||
|
return (*ld_emulation->unrecognized_file) (entry);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let the emulation code handle a recognized file. */
|
||||||
|
|
||||||
|
bfd_boolean
|
||||||
|
ldemul_recognized_file (lang_input_statement_type *entry)
|
||||||
|
{
|
||||||
|
if (ld_emulation->recognized_file)
|
||||||
|
return (*ld_emulation->recognized_file) (entry);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
ldemul_choose_target (int argc, char **argv)
|
||||||
|
{
|
||||||
|
return ld_emulation->choose_target (argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* The default choose_target function. */
|
||||||
|
|
||||||
|
char *
|
||||||
|
ldemul_default_target (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
char *from_outside = getenv (TARGET_ENVIRON);
|
||||||
|
if (from_outside != (char *) NULL)
|
||||||
|
return from_outside;
|
||||||
|
return ld_emulation->target_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the entry point was not specified as an address, then add the
|
||||||
|
symbol as undefined. This will cause ld to extract an archive
|
||||||
|
element defining the entry if ld is linking against such an archive.
|
||||||
|
|
||||||
|
We don't do this when generating shared libraries unless given -e
|
||||||
|
on the command line, because most shared libs are not designed to
|
||||||
|
be run as an executable. However, some are, eg. glibc ld.so and
|
||||||
|
may rely on the default linker script supplying ENTRY. So we can't
|
||||||
|
remove the ENTRY from the script, but would rather not insert
|
||||||
|
undefined _start syms. */
|
||||||
|
|
||||||
|
void
|
||||||
|
after_parse_default (void)
|
||||||
|
{
|
||||||
|
if (entry_symbol.name != NULL
|
||||||
|
&& (link_info.executable || entry_from_cmdline))
|
||||||
|
{
|
||||||
|
bfd_boolean is_vma = FALSE;
|
||||||
|
|
||||||
|
if (entry_from_cmdline)
|
||||||
|
{
|
||||||
|
const char *send;
|
||||||
|
|
||||||
|
bfd_scan_vma (entry_symbol.name, &send, 0);
|
||||||
|
is_vma = *send == '\0';
|
||||||
|
}
|
||||||
|
if (!is_vma)
|
||||||
|
ldlang_add_undef (entry_symbol.name, entry_from_cmdline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
after_open_default (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
after_allocation_default (void)
|
||||||
|
{
|
||||||
|
lang_relax_sections (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
before_allocation_default (void)
|
||||||
|
{
|
||||||
|
if (!link_info.relocatable)
|
||||||
|
strip_excluded_output_sections ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
finish_default (void)
|
||||||
|
{
|
||||||
|
if (!link_info.relocatable)
|
||||||
|
_bfd_fix_excluded_sec_syms (link_info.output_bfd, &link_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_output_arch_default (void)
|
||||||
|
{
|
||||||
|
/* Set the output architecture and machine if possible. */
|
||||||
|
bfd_set_arch_mach (link_info.output_bfd,
|
||||||
|
ldfile_output_architecture, ldfile_output_machine);
|
||||||
|
|
||||||
|
bfd_emul_set_maxpagesize (output_target, config.maxpagesize);
|
||||||
|
bfd_emul_set_commonpagesize (output_target, config.commonpagesize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
syslib_default (char *ignore ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
info_msg (_("%S SYSLIB ignored\n"), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hll_default (char *ignore ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
info_msg (_("%S HLL ignored\n"), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ld_emulation_xfer_type *ld_emulations[] = { EMULATION_LIST };
|
||||||
|
|
||||||
|
void
|
||||||
|
ldemul_choose_mode (char *target)
|
||||||
|
{
|
||||||
|
ld_emulation_xfer_type **eptr = ld_emulations;
|
||||||
|
/* Ignore "gld" prefix. */
|
||||||
|
if (target[0] == 'g' && target[1] == 'l' && target[2] == 'd')
|
||||||
|
target += 3;
|
||||||
|
for (; *eptr; eptr++)
|
||||||
|
{
|
||||||
|
if (strcmp (target, (*eptr)->emulation_name) == 0)
|
||||||
|
{
|
||||||
|
ld_emulation = *eptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
einfo (_("%P: unrecognised emulation mode: %s\n"), target);
|
||||||
|
einfo (_("Supported emulations: "));
|
||||||
|
ldemul_list_emulations (stderr);
|
||||||
|
einfo ("%F\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldemul_list_emulations (FILE *f)
|
||||||
|
{
|
||||||
|
ld_emulation_xfer_type **eptr = ld_emulations;
|
||||||
|
bfd_boolean first = TRUE;
|
||||||
|
|
||||||
|
for (; *eptr; eptr++)
|
||||||
|
{
|
||||||
|
if (first)
|
||||||
|
first = FALSE;
|
||||||
|
else
|
||||||
|
fprintf (f, " ");
|
||||||
|
fprintf (f, "%s", (*eptr)->emulation_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldemul_list_emulation_options (FILE *f)
|
||||||
|
{
|
||||||
|
ld_emulation_xfer_type **eptr;
|
||||||
|
int options_found = 0;
|
||||||
|
|
||||||
|
for (eptr = ld_emulations; *eptr; eptr++)
|
||||||
|
{
|
||||||
|
ld_emulation_xfer_type *emul = *eptr;
|
||||||
|
|
||||||
|
if (emul->list_options)
|
||||||
|
{
|
||||||
|
fprintf (f, "%s: \n", emul->emulation_name);
|
||||||
|
|
||||||
|
emul->list_options (f);
|
||||||
|
|
||||||
|
options_found = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! options_found)
|
||||||
|
fprintf (f, _(" no emulation specific options.\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ldemul_find_potential_libraries (char *name, lang_input_statement_type *entry)
|
||||||
|
{
|
||||||
|
if (ld_emulation->find_potential_libraries)
|
||||||
|
return ld_emulation->find_potential_libraries (name, entry);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bfd_elf_version_expr *
|
||||||
|
ldemul_new_vers_pattern (struct bfd_elf_version_expr *entry)
|
||||||
|
{
|
||||||
|
if (ld_emulation->new_vers_pattern)
|
||||||
|
entry = (*ld_emulation->new_vers_pattern) (entry);
|
||||||
|
return entry;
|
||||||
|
}
|
209
contrib/toolchain/binutils/ld/ldemul.h
Normal file
209
contrib/toolchain/binutils/ld/ldemul.h
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
/* ld-emul.h - Linker emulation header file
|
||||||
|
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2001,
|
||||||
|
2002, 2003, 2004, 2005, 2007, 2008
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#ifndef LDEMUL_H
|
||||||
|
#define LDEMUL_H
|
||||||
|
|
||||||
|
/* Forward declaration for ldemul_add_options() and others. */
|
||||||
|
struct option;
|
||||||
|
|
||||||
|
extern void ldemul_hll
|
||||||
|
(char *);
|
||||||
|
extern void ldemul_syslib
|
||||||
|
(char *);
|
||||||
|
extern void ldemul_after_parse
|
||||||
|
(void);
|
||||||
|
extern void ldemul_before_parse
|
||||||
|
(void);
|
||||||
|
extern void ldemul_after_open
|
||||||
|
(void);
|
||||||
|
extern void ldemul_after_allocation
|
||||||
|
(void);
|
||||||
|
extern void ldemul_before_allocation
|
||||||
|
(void);
|
||||||
|
extern void ldemul_set_output_arch
|
||||||
|
(void);
|
||||||
|
extern char *ldemul_choose_target
|
||||||
|
(int, char**);
|
||||||
|
extern void ldemul_choose_mode
|
||||||
|
(char *);
|
||||||
|
extern void ldemul_list_emulations
|
||||||
|
(FILE *);
|
||||||
|
extern void ldemul_list_emulation_options
|
||||||
|
(FILE *);
|
||||||
|
extern char *ldemul_get_script
|
||||||
|
(int *isfile);
|
||||||
|
extern void ldemul_finish
|
||||||
|
(void);
|
||||||
|
extern void ldemul_set_symbols
|
||||||
|
(void);
|
||||||
|
extern void ldemul_create_output_section_statements
|
||||||
|
(void);
|
||||||
|
extern lang_output_section_statement_type *ldemul_place_orphan
|
||||||
|
(asection *, const char *, int);
|
||||||
|
extern bfd_boolean ldemul_parse_args
|
||||||
|
(int, char **);
|
||||||
|
extern void ldemul_add_options
|
||||||
|
(int, char **, int, struct option **, int, struct option **);
|
||||||
|
extern bfd_boolean ldemul_handle_option
|
||||||
|
(int);
|
||||||
|
extern bfd_boolean ldemul_unrecognized_file
|
||||||
|
(struct lang_input_statement_struct *);
|
||||||
|
extern bfd_boolean ldemul_recognized_file
|
||||||
|
(struct lang_input_statement_struct *);
|
||||||
|
extern bfd_boolean ldemul_open_dynamic_archive
|
||||||
|
(const char *, struct search_dirs *, struct lang_input_statement_struct *);
|
||||||
|
extern char *ldemul_default_target
|
||||||
|
(int, char**);
|
||||||
|
extern void after_parse_default
|
||||||
|
(void);
|
||||||
|
extern void after_open_default
|
||||||
|
(void);
|
||||||
|
extern void after_allocation_default
|
||||||
|
(void);
|
||||||
|
extern void before_allocation_default
|
||||||
|
(void);
|
||||||
|
extern void finish_default
|
||||||
|
(void);
|
||||||
|
extern void finish_default
|
||||||
|
(void);
|
||||||
|
extern void set_output_arch_default
|
||||||
|
(void);
|
||||||
|
extern void syslib_default
|
||||||
|
(char*);
|
||||||
|
extern void hll_default
|
||||||
|
(char*);
|
||||||
|
extern int ldemul_find_potential_libraries
|
||||||
|
(char *, struct lang_input_statement_struct *);
|
||||||
|
extern struct bfd_elf_version_expr *ldemul_new_vers_pattern
|
||||||
|
(struct bfd_elf_version_expr *);
|
||||||
|
|
||||||
|
typedef struct ld_emulation_xfer_struct {
|
||||||
|
/* Run before parsing the command line and script file.
|
||||||
|
Set the architecture, maybe other things. */
|
||||||
|
void (*before_parse) (void);
|
||||||
|
|
||||||
|
/* Handle the SYSLIB (low level library) script command. */
|
||||||
|
void (*syslib) (char *);
|
||||||
|
|
||||||
|
/* Handle the HLL (high level library) script command. */
|
||||||
|
void (*hll) (char *);
|
||||||
|
|
||||||
|
/* Run after parsing the command line and script file. */
|
||||||
|
void (*after_parse) (void);
|
||||||
|
|
||||||
|
/* Run after opening all input files, and loading the symbols. */
|
||||||
|
void (*after_open) (void);
|
||||||
|
|
||||||
|
/* Run after allocating output sections. */
|
||||||
|
void (*after_allocation) (void);
|
||||||
|
|
||||||
|
/* Set the output architecture and machine if possible. */
|
||||||
|
void (*set_output_arch) (void);
|
||||||
|
|
||||||
|
/* Decide which target name to use. */
|
||||||
|
char * (*choose_target) (int, char**);
|
||||||
|
|
||||||
|
/* Run before allocating output sections. */
|
||||||
|
void (*before_allocation) (void);
|
||||||
|
|
||||||
|
/* Return the appropriate linker script. */
|
||||||
|
char * (*get_script) (int *isfile);
|
||||||
|
|
||||||
|
/* The name of this emulation. */
|
||||||
|
char *emulation_name;
|
||||||
|
|
||||||
|
/* The output format. */
|
||||||
|
char *target_name;
|
||||||
|
|
||||||
|
/* Run after assigning values from the script. */
|
||||||
|
void (*finish) (void);
|
||||||
|
|
||||||
|
/* Create any output sections needed by the target. */
|
||||||
|
void (*create_output_section_statements) (void);
|
||||||
|
|
||||||
|
/* Try to open a dynamic library. ARCH is an architecture name, and
|
||||||
|
is normally the empty string. ENTRY is the lang_input_statement
|
||||||
|
that should be opened. */
|
||||||
|
bfd_boolean (*open_dynamic_archive)
|
||||||
|
(const char *arch, struct search_dirs *,
|
||||||
|
struct lang_input_statement_struct *entry);
|
||||||
|
|
||||||
|
/* Place an orphan section. Return TRUE if it was placed, FALSE if
|
||||||
|
the default action should be taken. This field may be NULL, in
|
||||||
|
which case the default action will always be taken. */
|
||||||
|
lang_output_section_statement_type *(*place_orphan)
|
||||||
|
(asection *, const char *, int);
|
||||||
|
|
||||||
|
/* Run after assigning parsing with the args, but before
|
||||||
|
reading the script. Used to initialize symbols used in the script. */
|
||||||
|
void (*set_symbols) (void);
|
||||||
|
|
||||||
|
/* Parse args which the base linker doesn't understand.
|
||||||
|
Return TRUE if the arg needs no further processing. */
|
||||||
|
bfd_boolean (*parse_args) (int, char **);
|
||||||
|
|
||||||
|
/* Hook to add options to parameters passed by the base linker to
|
||||||
|
getopt_long and getopt_long_only calls. */
|
||||||
|
void (*add_options)
|
||||||
|
(int, char **, int, struct option **, int, struct option **);
|
||||||
|
|
||||||
|
/* Companion to the above to handle an option. Returns TRUE if it is
|
||||||
|
one of our options. */
|
||||||
|
bfd_boolean (*handle_option) (int);
|
||||||
|
|
||||||
|
/* Run to handle files which are not recognized as object files or
|
||||||
|
archives. Return TRUE if the file was handled. */
|
||||||
|
bfd_boolean (*unrecognized_file)
|
||||||
|
(struct lang_input_statement_struct *);
|
||||||
|
|
||||||
|
/* Run to list the command line options which parse_args handles. */
|
||||||
|
void (* list_options) (FILE *);
|
||||||
|
|
||||||
|
/* Run to specially handle files which *are* recognized as object
|
||||||
|
files or archives. Return TRUE if the file was handled. */
|
||||||
|
bfd_boolean (*recognized_file)
|
||||||
|
(struct lang_input_statement_struct *);
|
||||||
|
|
||||||
|
/* Called when looking for libraries in a directory specified
|
||||||
|
via a linker command line option or linker script option.
|
||||||
|
Files that match the pattern "lib*.a" have already been scanned.
|
||||||
|
(For VMS files matching ":lib*.a" have also been scanned). */
|
||||||
|
int (* find_potential_libraries)
|
||||||
|
(char *, struct lang_input_statement_struct *);
|
||||||
|
|
||||||
|
/* Called when adding a new version pattern. PowerPC64-ELF uses
|
||||||
|
this hook to add a pattern matching ".foo" for every "foo". */
|
||||||
|
struct bfd_elf_version_expr * (*new_vers_pattern)
|
||||||
|
(struct bfd_elf_version_expr *);
|
||||||
|
|
||||||
|
} ld_emulation_xfer_type;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
intel_ic960_ld_mode_enum,
|
||||||
|
default_mode_enum,
|
||||||
|
intel_gld960_ld_mode_enum
|
||||||
|
} lang_emulation_mode_enum_type;
|
||||||
|
|
||||||
|
extern ld_emulation_xfer_type *ld_emulations[];
|
||||||
|
|
||||||
|
#endif
|
1357
contrib/toolchain/binutils/ld/ldexp.c
Normal file
1357
contrib/toolchain/binutils/ld/ldexp.c
Normal file
File diff suppressed because it is too large
Load Diff
226
contrib/toolchain/binutils/ld/ldexp.h
Normal file
226
contrib/toolchain/binutils/ld/ldexp.h
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
/* ldexp.h -
|
||||||
|
Copyright 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000, 2001, 2002,
|
||||||
|
2003, 2004, 2005, 2007, 2011, 2012 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#ifndef LDEXP_H
|
||||||
|
#define LDEXP_H
|
||||||
|
|
||||||
|
/* The result of an expression tree */
|
||||||
|
typedef struct {
|
||||||
|
bfd_vma value;
|
||||||
|
char *str;
|
||||||
|
asection *section;
|
||||||
|
bfd_boolean valid_p;
|
||||||
|
} etree_value_type;
|
||||||
|
|
||||||
|
enum node_tree_enum {
|
||||||
|
etree_binary,
|
||||||
|
etree_trinary,
|
||||||
|
etree_unary,
|
||||||
|
etree_name,
|
||||||
|
etree_assign,
|
||||||
|
etree_provide,
|
||||||
|
etree_provided,
|
||||||
|
etree_value,
|
||||||
|
etree_assert,
|
||||||
|
etree_rel
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int node_code;
|
||||||
|
unsigned int lineno;
|
||||||
|
const char *filename;
|
||||||
|
enum node_tree_enum node_class;
|
||||||
|
} node_type;
|
||||||
|
|
||||||
|
typedef union etree_union {
|
||||||
|
node_type type;
|
||||||
|
struct {
|
||||||
|
node_type type;
|
||||||
|
union etree_union *lhs;
|
||||||
|
union etree_union *rhs;
|
||||||
|
} binary;
|
||||||
|
struct {
|
||||||
|
node_type type;
|
||||||
|
union etree_union *cond;
|
||||||
|
union etree_union *lhs;
|
||||||
|
union etree_union *rhs;
|
||||||
|
} trinary;
|
||||||
|
struct {
|
||||||
|
node_type type;
|
||||||
|
const char *dst;
|
||||||
|
union etree_union *src;
|
||||||
|
bfd_boolean defsym;
|
||||||
|
bfd_boolean hidden;
|
||||||
|
} assign;
|
||||||
|
struct {
|
||||||
|
node_type type;
|
||||||
|
union etree_union *child;
|
||||||
|
} unary;
|
||||||
|
struct {
|
||||||
|
node_type type;
|
||||||
|
const char *name;
|
||||||
|
} name;
|
||||||
|
struct {
|
||||||
|
node_type type;
|
||||||
|
bfd_vma value;
|
||||||
|
char *str;
|
||||||
|
} value;
|
||||||
|
struct {
|
||||||
|
node_type type;
|
||||||
|
asection *section;
|
||||||
|
bfd_vma value;
|
||||||
|
} rel;
|
||||||
|
struct {
|
||||||
|
node_type type;
|
||||||
|
union etree_union *child;
|
||||||
|
const char *message;
|
||||||
|
} assert_s;
|
||||||
|
} etree_type;
|
||||||
|
|
||||||
|
/* Expression evaluation control. */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
/* Parsing linker script. Will only return "valid" for expressions
|
||||||
|
that evaluate to a constant. */
|
||||||
|
lang_first_phase_enum,
|
||||||
|
/* Prior to section sizing. */
|
||||||
|
lang_mark_phase_enum,
|
||||||
|
/* During section sizing. */
|
||||||
|
lang_allocating_phase_enum,
|
||||||
|
/* During assignment of symbol values when relaxation in progress. */
|
||||||
|
lang_assigning_phase_enum,
|
||||||
|
/* Final assignment of symbol values. */
|
||||||
|
lang_final_phase_enum
|
||||||
|
} lang_phase_type;
|
||||||
|
|
||||||
|
union lang_statement_union;
|
||||||
|
|
||||||
|
enum phase_enum {
|
||||||
|
/* We step through the first four states here as we see the
|
||||||
|
associated linker script tokens. */
|
||||||
|
exp_dataseg_none,
|
||||||
|
exp_dataseg_align_seen,
|
||||||
|
exp_dataseg_relro_seen,
|
||||||
|
exp_dataseg_end_seen,
|
||||||
|
/* The last three states are final, and affect the value returned
|
||||||
|
by DATA_SEGMENT_ALIGN. */
|
||||||
|
exp_dataseg_relro_adjust,
|
||||||
|
exp_dataseg_adjust,
|
||||||
|
exp_dataseg_done
|
||||||
|
};
|
||||||
|
|
||||||
|
enum relro_enum {
|
||||||
|
exp_dataseg_relro_none,
|
||||||
|
exp_dataseg_relro_start,
|
||||||
|
exp_dataseg_relro_end,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ldexp_control {
|
||||||
|
/* Modify expression evaluation depending on this. */
|
||||||
|
lang_phase_type phase;
|
||||||
|
|
||||||
|
/* Principally used for diagnostics. */
|
||||||
|
bfd_boolean assigning_to_dot;
|
||||||
|
/* If evaluating an assignment, the destination. Cleared if an
|
||||||
|
etree_name NAME matches this, to signal a self-assignment.
|
||||||
|
Note that an etree_name DEFINED does not clear this field, nor
|
||||||
|
does the false branch of a trinary expression. */
|
||||||
|
const char *assign_name;
|
||||||
|
|
||||||
|
/* Working results. */
|
||||||
|
etree_value_type result;
|
||||||
|
bfd_vma dot;
|
||||||
|
|
||||||
|
/* Current dot and section passed to ldexp folder. */
|
||||||
|
bfd_vma *dotp;
|
||||||
|
asection *section;
|
||||||
|
|
||||||
|
/* State machine and results for DATASEG. */
|
||||||
|
struct {
|
||||||
|
enum phase_enum phase;
|
||||||
|
|
||||||
|
bfd_vma base, min_base, relro_end, end, pagesize, maxpagesize;
|
||||||
|
|
||||||
|
enum relro_enum relro;
|
||||||
|
|
||||||
|
union lang_statement_union *relro_start_stat;
|
||||||
|
union lang_statement_union *relro_end_stat;
|
||||||
|
} dataseg;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct ldexp_control expld;
|
||||||
|
|
||||||
|
/* A maps from a segment name to a base address. */
|
||||||
|
typedef struct segment_struct {
|
||||||
|
/* The next segment in the linked list. */
|
||||||
|
struct segment_struct *next;
|
||||||
|
/* The name of the sgement. */
|
||||||
|
const char *name;
|
||||||
|
/* The base address for the segment. */
|
||||||
|
bfd_vma value;
|
||||||
|
/* True if a SEGMENT_START directive corresponding to this segment
|
||||||
|
has been seen. */
|
||||||
|
bfd_boolean used;
|
||||||
|
} segment_type;
|
||||||
|
|
||||||
|
/* The segments specified by the user on the command-line. */
|
||||||
|
extern segment_type *segments;
|
||||||
|
|
||||||
|
typedef struct _fill_type fill_type;
|
||||||
|
|
||||||
|
etree_type *exp_intop
|
||||||
|
(bfd_vma);
|
||||||
|
etree_type *exp_bigintop
|
||||||
|
(bfd_vma, char *);
|
||||||
|
etree_type *exp_relop
|
||||||
|
(asection *, bfd_vma);
|
||||||
|
void exp_fold_tree
|
||||||
|
(etree_type *, asection *, bfd_vma *);
|
||||||
|
void exp_fold_tree_no_dot
|
||||||
|
(etree_type *);
|
||||||
|
etree_type *exp_binop
|
||||||
|
(int, etree_type *, etree_type *);
|
||||||
|
etree_type *exp_trinop
|
||||||
|
(int,etree_type *, etree_type *, etree_type *);
|
||||||
|
etree_type *exp_unop
|
||||||
|
(int, etree_type *);
|
||||||
|
etree_type *exp_nameop
|
||||||
|
(int, const char *);
|
||||||
|
etree_type *exp_assign
|
||||||
|
(const char *, etree_type *, bfd_boolean);
|
||||||
|
etree_type *exp_defsym
|
||||||
|
(const char *, etree_type *);
|
||||||
|
etree_type *exp_provide
|
||||||
|
(const char *, etree_type *, bfd_boolean);
|
||||||
|
etree_type *exp_assert
|
||||||
|
(etree_type *, const char *);
|
||||||
|
void exp_print_tree
|
||||||
|
(etree_type *);
|
||||||
|
bfd_vma exp_get_vma
|
||||||
|
(etree_type *, bfd_vma, char *);
|
||||||
|
int exp_get_value_int
|
||||||
|
(etree_type *, int, char *);
|
||||||
|
fill_type *exp_get_fill
|
||||||
|
(etree_type *, fill_type *, char *);
|
||||||
|
bfd_vma exp_get_abs_int
|
||||||
|
(etree_type *, int, char *);
|
||||||
|
|
||||||
|
#endif
|
672
contrib/toolchain/binutils/ld/ldfile.c
Normal file
672
contrib/toolchain/binutils/ld/ldfile.c
Normal file
@ -0,0 +1,672 @@
|
|||||||
|
/* Linker file opening and searching.
|
||||||
|
Copyright 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000, 2001, 2002,
|
||||||
|
2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#include "sysdep.h"
|
||||||
|
#include "bfd.h"
|
||||||
|
#include "bfdlink.h"
|
||||||
|
#include "safe-ctype.h"
|
||||||
|
#include "ld.h"
|
||||||
|
#include "ldmisc.h"
|
||||||
|
#include "ldexp.h"
|
||||||
|
#include "ldlang.h"
|
||||||
|
#include "ldfile.h"
|
||||||
|
#include "ldmain.h"
|
||||||
|
#include <ldgram.h>
|
||||||
|
#include "ldlex.h"
|
||||||
|
#include "ldemul.h"
|
||||||
|
#include "libiberty.h"
|
||||||
|
#include "filenames.h"
|
||||||
|
#ifdef ENABLE_PLUGINS
|
||||||
|
#include "plugin-api.h"
|
||||||
|
#include "plugin.h"
|
||||||
|
#endif /* ENABLE_PLUGINS */
|
||||||
|
|
||||||
|
bfd_boolean ldfile_assumed_script = FALSE;
|
||||||
|
const char * ldfile_output_machine_name = "";
|
||||||
|
unsigned long ldfile_output_machine;
|
||||||
|
enum bfd_architecture ldfile_output_architecture;
|
||||||
|
search_dirs_type * search_head;
|
||||||
|
|
||||||
|
#ifdef VMS
|
||||||
|
static char * slash = "";
|
||||||
|
#else
|
||||||
|
#if defined (_WIN32) && ! defined (__CYGWIN32__)
|
||||||
|
static char * slash = "\\";
|
||||||
|
#else
|
||||||
|
static char * slash = "/";
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct search_arch
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
struct search_arch *next;
|
||||||
|
} search_arch_type;
|
||||||
|
|
||||||
|
static search_dirs_type **search_tail_ptr = &search_head;
|
||||||
|
static search_arch_type *search_arch_head;
|
||||||
|
static search_arch_type **search_arch_tail_ptr = &search_arch_head;
|
||||||
|
|
||||||
|
/* Test whether a pathname, after canonicalization, is the same or a
|
||||||
|
sub-directory of the sysroot directory. */
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
is_sysrooted_pathname (const char *name)
|
||||||
|
{
|
||||||
|
char *realname;
|
||||||
|
int len;
|
||||||
|
bfd_boolean result;
|
||||||
|
|
||||||
|
if (ld_canon_sysroot == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
realname = lrealpath (name);
|
||||||
|
len = strlen (realname);
|
||||||
|
result = FALSE;
|
||||||
|
if (len > ld_canon_sysroot_len
|
||||||
|
&& IS_DIR_SEPARATOR (realname[ld_canon_sysroot_len]))
|
||||||
|
{
|
||||||
|
realname[ld_canon_sysroot_len] = '\0';
|
||||||
|
result = FILENAME_CMP (ld_canon_sysroot, realname) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
free (realname);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adds NAME to the library search path.
|
||||||
|
Makes a copy of NAME using xmalloc(). */
|
||||||
|
|
||||||
|
void
|
||||||
|
ldfile_add_library_path (const char *name, bfd_boolean cmdline)
|
||||||
|
{
|
||||||
|
search_dirs_type *new_dirs;
|
||||||
|
|
||||||
|
if (!cmdline && config.only_cmd_line_lib_dirs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
new_dirs = (search_dirs_type *) xmalloc (sizeof (search_dirs_type));
|
||||||
|
new_dirs->next = NULL;
|
||||||
|
new_dirs->cmdline = cmdline;
|
||||||
|
*search_tail_ptr = new_dirs;
|
||||||
|
search_tail_ptr = &new_dirs->next;
|
||||||
|
|
||||||
|
/* If a directory is marked as honoring sysroot, prepend the sysroot path
|
||||||
|
now. */
|
||||||
|
if (name[0] == '=')
|
||||||
|
new_dirs->name = concat (ld_sysroot, name + 1, (const char *) NULL);
|
||||||
|
else
|
||||||
|
new_dirs->name = xstrdup (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to open a BFD for a lang_input_statement. */
|
||||||
|
|
||||||
|
bfd_boolean
|
||||||
|
ldfile_try_open_bfd (const char *attempt,
|
||||||
|
lang_input_statement_type *entry)
|
||||||
|
{
|
||||||
|
entry->the_bfd = bfd_openr (attempt, entry->target);
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
{
|
||||||
|
if (entry->the_bfd == NULL)
|
||||||
|
info_msg (_("attempt to open %s failed\n"), attempt);
|
||||||
|
else
|
||||||
|
info_msg (_("attempt to open %s succeeded\n"), attempt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->the_bfd == NULL)
|
||||||
|
{
|
||||||
|
if (bfd_get_error () == bfd_error_invalid_target)
|
||||||
|
einfo (_("%F%P: invalid BFD target `%s'\n"), entry->target);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Linker needs to decompress sections. */
|
||||||
|
entry->the_bfd->flags |= BFD_DECOMPRESS;
|
||||||
|
|
||||||
|
/* If we are searching for this file, see if the architecture is
|
||||||
|
compatible with the output file. If it isn't, keep searching.
|
||||||
|
If we can't open the file as an object file, stop the search
|
||||||
|
here. If we are statically linking, ensure that we don't link
|
||||||
|
a dynamic object.
|
||||||
|
|
||||||
|
In the code below, it's OK to exit early if the check fails,
|
||||||
|
closing the checked BFD and returning FALSE, but if the BFD
|
||||||
|
checks out compatible, do not exit early returning TRUE, or
|
||||||
|
the plugins will not get a chance to claim the file. */
|
||||||
|
|
||||||
|
if (entry->flags.search_dirs || !entry->flags.dynamic)
|
||||||
|
{
|
||||||
|
bfd *check;
|
||||||
|
|
||||||
|
if (bfd_check_format (entry->the_bfd, bfd_archive))
|
||||||
|
check = bfd_openr_next_archived_file (entry->the_bfd, NULL);
|
||||||
|
else
|
||||||
|
check = entry->the_bfd;
|
||||||
|
|
||||||
|
if (check != NULL)
|
||||||
|
{
|
||||||
|
if (! bfd_check_format (check, bfd_object))
|
||||||
|
{
|
||||||
|
if (check == entry->the_bfd
|
||||||
|
&& entry->flags.search_dirs
|
||||||
|
&& bfd_get_error () == bfd_error_file_not_recognized
|
||||||
|
&& ! ldemul_unrecognized_file (entry))
|
||||||
|
{
|
||||||
|
int token, skip = 0;
|
||||||
|
char *arg, *arg1, *arg2, *arg3;
|
||||||
|
extern FILE *yyin;
|
||||||
|
|
||||||
|
/* Try to interpret the file as a linker script. */
|
||||||
|
ldfile_open_command_file (attempt);
|
||||||
|
|
||||||
|
ldfile_assumed_script = TRUE;
|
||||||
|
parser_input = input_selected;
|
||||||
|
ldlex_both ();
|
||||||
|
token = INPUT_SCRIPT;
|
||||||
|
while (token != 0)
|
||||||
|
{
|
||||||
|
switch (token)
|
||||||
|
{
|
||||||
|
case OUTPUT_FORMAT:
|
||||||
|
if ((token = yylex ()) != '(')
|
||||||
|
continue;
|
||||||
|
if ((token = yylex ()) != NAME)
|
||||||
|
continue;
|
||||||
|
arg1 = yylval.name;
|
||||||
|
arg2 = NULL;
|
||||||
|
arg3 = NULL;
|
||||||
|
token = yylex ();
|
||||||
|
if (token == ',')
|
||||||
|
{
|
||||||
|
if ((token = yylex ()) != NAME)
|
||||||
|
{
|
||||||
|
free (arg1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
arg2 = yylval.name;
|
||||||
|
if ((token = yylex ()) != ','
|
||||||
|
|| (token = yylex ()) != NAME)
|
||||||
|
{
|
||||||
|
free (arg1);
|
||||||
|
free (arg2);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
arg3 = yylval.name;
|
||||||
|
token = yylex ();
|
||||||
|
}
|
||||||
|
if (token == ')')
|
||||||
|
{
|
||||||
|
switch (command_line.endian)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case ENDIAN_UNSET:
|
||||||
|
arg = arg1; break;
|
||||||
|
case ENDIAN_BIG:
|
||||||
|
arg = arg2 ? arg2 : arg1; break;
|
||||||
|
case ENDIAN_LITTLE:
|
||||||
|
arg = arg3 ? arg3 : arg1; break;
|
||||||
|
}
|
||||||
|
if (strcmp (arg, lang_get_output_target ()) != 0)
|
||||||
|
skip = 1;
|
||||||
|
}
|
||||||
|
free (arg1);
|
||||||
|
if (arg2) free (arg2);
|
||||||
|
if (arg3) free (arg3);
|
||||||
|
break;
|
||||||
|
case NAME:
|
||||||
|
case LNAME:
|
||||||
|
case VERS_IDENTIFIER:
|
||||||
|
case VERS_TAG:
|
||||||
|
free (yylval.name);
|
||||||
|
break;
|
||||||
|
case INT:
|
||||||
|
if (yylval.bigint.str)
|
||||||
|
free (yylval.bigint.str);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
token = yylex ();
|
||||||
|
}
|
||||||
|
ldlex_popstate ();
|
||||||
|
ldfile_assumed_script = FALSE;
|
||||||
|
fclose (yyin);
|
||||||
|
yyin = NULL;
|
||||||
|
if (skip)
|
||||||
|
{
|
||||||
|
if (command_line.warn_search_mismatch)
|
||||||
|
einfo (_("%P: skipping incompatible %s "
|
||||||
|
"when searching for %s\n"),
|
||||||
|
attempt, entry->local_sym_name);
|
||||||
|
bfd_close (entry->the_bfd);
|
||||||
|
entry->the_bfd = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goto success;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!entry->flags.dynamic && (entry->the_bfd->flags & DYNAMIC) != 0)
|
||||||
|
{
|
||||||
|
einfo (_("%F%P: attempted static link of dynamic object `%s'\n"),
|
||||||
|
attempt);
|
||||||
|
bfd_close (entry->the_bfd);
|
||||||
|
entry->the_bfd = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->flags.search_dirs
|
||||||
|
&& !bfd_arch_get_compatible (check, link_info.output_bfd,
|
||||||
|
command_line.accept_unknown_input_arch)
|
||||||
|
/* XCOFF archives can have 32 and 64 bit objects. */
|
||||||
|
&& ! (bfd_get_flavour (check) == bfd_target_xcoff_flavour
|
||||||
|
&& bfd_get_flavour (link_info.output_bfd) == bfd_target_xcoff_flavour
|
||||||
|
&& bfd_check_format (entry->the_bfd, bfd_archive)))
|
||||||
|
{
|
||||||
|
if (command_line.warn_search_mismatch)
|
||||||
|
einfo (_("%P: skipping incompatible %s "
|
||||||
|
"when searching for %s\n"),
|
||||||
|
attempt, entry->local_sym_name);
|
||||||
|
bfd_close (entry->the_bfd);
|
||||||
|
entry->the_bfd = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
success:
|
||||||
|
#ifdef ENABLE_PLUGINS
|
||||||
|
/* If plugins are active, they get first chance to claim
|
||||||
|
any successfully-opened input file. We skip archives
|
||||||
|
here; the plugin wants us to offer it the individual
|
||||||
|
members when we enumerate them, not the whole file. We
|
||||||
|
also ignore corefiles, because that's just weird. It is
|
||||||
|
a needed side-effect of calling bfd_check_format with
|
||||||
|
bfd_object that it sets the bfd's arch and mach, which
|
||||||
|
will be needed when and if we want to bfd_create a new
|
||||||
|
one using this one as a template. */
|
||||||
|
if (bfd_check_format (entry->the_bfd, bfd_object)
|
||||||
|
&& plugin_active_plugins_p ()
|
||||||
|
&& !no_more_claiming)
|
||||||
|
{
|
||||||
|
int fd = open (attempt, O_RDONLY | O_BINARY);
|
||||||
|
if (fd >= 0)
|
||||||
|
{
|
||||||
|
struct ld_plugin_input_file file;
|
||||||
|
|
||||||
|
file.name = attempt;
|
||||||
|
file.offset = 0;
|
||||||
|
file.filesize = lseek (fd, 0, SEEK_END);
|
||||||
|
file.fd = fd;
|
||||||
|
plugin_maybe_claim (&file, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* ENABLE_PLUGINS */
|
||||||
|
|
||||||
|
/* It opened OK, the format checked out, and the plugins have had
|
||||||
|
their chance to claim it, so this is success. */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Search for and open the file specified by ENTRY. If it is an
|
||||||
|
archive, use ARCH, LIB and SUFFIX to modify the file name. */
|
||||||
|
|
||||||
|
bfd_boolean
|
||||||
|
ldfile_open_file_search (const char *arch,
|
||||||
|
lang_input_statement_type *entry,
|
||||||
|
const char *lib,
|
||||||
|
const char *suffix)
|
||||||
|
{
|
||||||
|
search_dirs_type *search;
|
||||||
|
|
||||||
|
/* If this is not an archive, try to open it in the current
|
||||||
|
directory first. */
|
||||||
|
if (! entry->flags.maybe_archive)
|
||||||
|
{
|
||||||
|
if (entry->flags.sysrooted && IS_ABSOLUTE_PATH (entry->filename))
|
||||||
|
{
|
||||||
|
char *name = concat (ld_sysroot, entry->filename,
|
||||||
|
(const char *) NULL);
|
||||||
|
if (ldfile_try_open_bfd (name, entry))
|
||||||
|
{
|
||||||
|
entry->filename = name;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
free (name);
|
||||||
|
}
|
||||||
|
else if (ldfile_try_open_bfd (entry->filename, entry))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (IS_ABSOLUTE_PATH (entry->filename))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (search = search_head; search != NULL; search = search->next)
|
||||||
|
{
|
||||||
|
char *string;
|
||||||
|
|
||||||
|
if (entry->flags.dynamic && ! link_info.relocatable)
|
||||||
|
{
|
||||||
|
if (ldemul_open_dynamic_archive (arch, search, entry))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->flags.maybe_archive)
|
||||||
|
string = concat (search->name, slash, lib, entry->filename,
|
||||||
|
arch, suffix, (const char *) NULL);
|
||||||
|
else
|
||||||
|
string = concat (search->name, slash, entry->filename,
|
||||||
|
(const char *) 0);
|
||||||
|
|
||||||
|
if (ldfile_try_open_bfd (string, entry))
|
||||||
|
{
|
||||||
|
entry->filename = string;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
free (string);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open the input file specified by ENTRY.
|
||||||
|
PR 4437: Do not stop on the first missing file, but
|
||||||
|
continue processing other input files in case there
|
||||||
|
are more errors to report. */
|
||||||
|
|
||||||
|
void
|
||||||
|
ldfile_open_file (lang_input_statement_type *entry)
|
||||||
|
{
|
||||||
|
if (entry->the_bfd != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
printf("%s %s\n", __FUNCTION__, entry->filename);
|
||||||
|
|
||||||
|
if (! entry->flags.search_dirs)
|
||||||
|
{
|
||||||
|
if (ldfile_try_open_bfd (entry->filename, entry))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (filename_cmp (entry->filename, entry->local_sym_name) != 0)
|
||||||
|
einfo (_("%P: cannot find %s (%s): %E\n"),
|
||||||
|
entry->filename, entry->local_sym_name);
|
||||||
|
else
|
||||||
|
einfo (_("%P: cannot find %s: %E\n"), entry->local_sym_name);
|
||||||
|
|
||||||
|
entry->flags.missing_file = TRUE;
|
||||||
|
input_flags.missing_file = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
search_arch_type *arch;
|
||||||
|
bfd_boolean found = FALSE;
|
||||||
|
|
||||||
|
/* Try to open <filename><suffix> or lib<filename><suffix>.a */
|
||||||
|
for (arch = search_arch_head; arch != NULL; arch = arch->next)
|
||||||
|
{
|
||||||
|
found = ldfile_open_file_search (arch->name, entry, "lib", ".a");
|
||||||
|
if (found)
|
||||||
|
break;
|
||||||
|
#ifdef VMS
|
||||||
|
found = ldfile_open_file_search (arch->name, entry, ":lib", ".a");
|
||||||
|
if (found)
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
found = ldemul_find_potential_libraries (arch->name, entry);
|
||||||
|
if (found)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have found the file, we don't need to search directories
|
||||||
|
again. */
|
||||||
|
if (found)
|
||||||
|
entry->flags.search_dirs = FALSE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (entry->flags.sysrooted
|
||||||
|
&& ld_sysroot
|
||||||
|
&& IS_ABSOLUTE_PATH (entry->local_sym_name))
|
||||||
|
einfo (_("%P: cannot find %s inside %s\n"),
|
||||||
|
entry->local_sym_name, ld_sysroot);
|
||||||
|
else
|
||||||
|
einfo (_("%P: cannot find %s\n"), entry->local_sym_name);
|
||||||
|
entry->flags.missing_file = TRUE;
|
||||||
|
input_flags.missing_file = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to open NAME. */
|
||||||
|
|
||||||
|
static FILE *
|
||||||
|
try_open (const char *name, bfd_boolean *sysrooted)
|
||||||
|
{
|
||||||
|
FILE *result;
|
||||||
|
|
||||||
|
result = fopen (name, "r");
|
||||||
|
|
||||||
|
if (result != NULL)
|
||||||
|
*sysrooted = is_sysrooted_pathname (name);
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
{
|
||||||
|
if (result == NULL)
|
||||||
|
info_msg (_("cannot find script file %s\n"), name);
|
||||||
|
else
|
||||||
|
info_msg (_("opened script file %s\n"), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return TRUE iff directory DIR contains an "ldscripts" subdirectory. */
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
check_for_scripts_dir (char *dir)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
struct stat s;
|
||||||
|
bfd_boolean res;
|
||||||
|
|
||||||
|
buf = concat (dir, "/ldscripts", (const char *) NULL);
|
||||||
|
res = stat (buf, &s) == 0 && S_ISDIR (s.st_mode);
|
||||||
|
free (buf);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the default directory for finding script files.
|
||||||
|
We look for the "ldscripts" directory in:
|
||||||
|
|
||||||
|
SCRIPTDIR (passed from Makefile)
|
||||||
|
(adjusted according to the current location of the binary)
|
||||||
|
the dir where this program is (for using it from the build tree). */
|
||||||
|
|
||||||
|
static char *
|
||||||
|
find_scripts_dir (void)
|
||||||
|
{
|
||||||
|
char *dir;
|
||||||
|
|
||||||
|
dir = make_relative_prefix (program_name, BINDIR, SCRIPTDIR);
|
||||||
|
if (dir)
|
||||||
|
{
|
||||||
|
if (check_for_scripts_dir (dir))
|
||||||
|
return dir;
|
||||||
|
free (dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = make_relative_prefix (program_name, TOOLBINDIR, SCRIPTDIR);
|
||||||
|
if (dir)
|
||||||
|
{
|
||||||
|
if (check_for_scripts_dir (dir))
|
||||||
|
return dir;
|
||||||
|
free (dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look for "ldscripts" in the dir where our binary is. */
|
||||||
|
dir = make_relative_prefix (program_name, ".", ".");
|
||||||
|
if (dir)
|
||||||
|
{
|
||||||
|
if (check_for_scripts_dir (dir))
|
||||||
|
return dir;
|
||||||
|
free (dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If DEFAULT_ONLY is false, try to open NAME; if that fails, look for
|
||||||
|
it in directories specified with -L, then in the default script
|
||||||
|
directory. If DEFAULT_ONLY is true, the search is restricted to
|
||||||
|
the default script location. */
|
||||||
|
|
||||||
|
static FILE *
|
||||||
|
ldfile_find_command_file (const char *name,
|
||||||
|
bfd_boolean default_only,
|
||||||
|
bfd_boolean *sysrooted)
|
||||||
|
{
|
||||||
|
search_dirs_type *search;
|
||||||
|
FILE *result = NULL;
|
||||||
|
char *path;
|
||||||
|
static search_dirs_type *script_search;
|
||||||
|
|
||||||
|
if (!default_only)
|
||||||
|
{
|
||||||
|
/* First try raw name. */
|
||||||
|
result = try_open (name, sysrooted);
|
||||||
|
if (result != NULL)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!script_search)
|
||||||
|
{
|
||||||
|
char *script_dir = find_scripts_dir ();
|
||||||
|
if (script_dir)
|
||||||
|
{
|
||||||
|
search_dirs_type **save_tail_ptr = search_tail_ptr;
|
||||||
|
search_tail_ptr = &script_search;
|
||||||
|
ldfile_add_library_path (script_dir, TRUE);
|
||||||
|
search_tail_ptr = save_tail_ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Temporarily append script_search to the path list so that the
|
||||||
|
paths specified with -L will be searched first. */
|
||||||
|
*search_tail_ptr = script_search;
|
||||||
|
|
||||||
|
/* Try now prefixes. */
|
||||||
|
for (search = default_only ? script_search : search_head;
|
||||||
|
search != NULL;
|
||||||
|
search = search->next)
|
||||||
|
{
|
||||||
|
path = concat (search->name, slash, name, (const char *) NULL);
|
||||||
|
result = try_open (path, sysrooted);
|
||||||
|
free (path);
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore the original path list. */
|
||||||
|
*search_tail_ptr = NULL;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open command file NAME. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ldfile_open_command_file_1 (const char *name, bfd_boolean default_only)
|
||||||
|
{
|
||||||
|
FILE *ldlex_input_stack;
|
||||||
|
bfd_boolean sysrooted;
|
||||||
|
|
||||||
|
ldlex_input_stack = ldfile_find_command_file (name, default_only, &sysrooted);
|
||||||
|
|
||||||
|
if (ldlex_input_stack == NULL)
|
||||||
|
{
|
||||||
|
bfd_set_error (bfd_error_system_call);
|
||||||
|
einfo (_("%P%F: cannot open linker script file %s: %E\n"), name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lex_push_file (ldlex_input_stack, name, sysrooted);
|
||||||
|
|
||||||
|
lineno = 1;
|
||||||
|
|
||||||
|
saved_script_handle = ldlex_input_stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open command file NAME in the current directory, -L directories,
|
||||||
|
the default script location, in that order. */
|
||||||
|
|
||||||
|
void
|
||||||
|
ldfile_open_command_file (const char *name)
|
||||||
|
{
|
||||||
|
ldfile_open_command_file_1 (name, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open command file NAME at the default script location. */
|
||||||
|
|
||||||
|
void
|
||||||
|
ldfile_open_default_command_file (const char *name)
|
||||||
|
{
|
||||||
|
ldfile_open_command_file_1 (name, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldfile_add_arch (const char *in_name)
|
||||||
|
{
|
||||||
|
char *name = xstrdup (in_name);
|
||||||
|
search_arch_type *new_arch = (search_arch_type *)
|
||||||
|
xmalloc (sizeof (search_arch_type));
|
||||||
|
|
||||||
|
ldfile_output_machine_name = in_name;
|
||||||
|
|
||||||
|
new_arch->name = name;
|
||||||
|
new_arch->next = NULL;
|
||||||
|
while (*name)
|
||||||
|
{
|
||||||
|
*name = TOLOWER (*name);
|
||||||
|
name++;
|
||||||
|
}
|
||||||
|
*search_arch_tail_ptr = new_arch;
|
||||||
|
search_arch_tail_ptr = &new_arch->next;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the output architecture. */
|
||||||
|
|
||||||
|
void
|
||||||
|
ldfile_set_output_arch (const char *string, enum bfd_architecture defarch)
|
||||||
|
{
|
||||||
|
const bfd_arch_info_type *arch = bfd_scan_arch (string);
|
||||||
|
|
||||||
|
if (arch)
|
||||||
|
{
|
||||||
|
ldfile_output_architecture = arch->arch;
|
||||||
|
ldfile_output_machine = arch->mach;
|
||||||
|
ldfile_output_machine_name = arch->printable_name;
|
||||||
|
}
|
||||||
|
else if (defarch != bfd_arch_unknown)
|
||||||
|
ldfile_output_architecture = defarch;
|
||||||
|
else
|
||||||
|
einfo (_("%P%F: cannot represent machine `%s'\n"), string);
|
||||||
|
}
|
62
contrib/toolchain/binutils/ld/ldfile.h
Normal file
62
contrib/toolchain/binutils/ld/ldfile.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/* ldfile.h -
|
||||||
|
Copyright 1991, 1992, 1993, 1994, 1995, 2000, 2002, 2003, 2004, 2005,
|
||||||
|
2007, 2012 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#ifndef LDFILE_H
|
||||||
|
#define LDFILE_H
|
||||||
|
|
||||||
|
extern bfd_boolean ldfile_assumed_script;
|
||||||
|
extern unsigned long ldfile_output_machine;
|
||||||
|
extern enum bfd_architecture ldfile_output_architecture;
|
||||||
|
extern const char *ldfile_output_machine_name;
|
||||||
|
|
||||||
|
/* Structure used to hold the list of directories to search for
|
||||||
|
libraries. */
|
||||||
|
|
||||||
|
typedef struct search_dirs {
|
||||||
|
/* Next directory on list. */
|
||||||
|
struct search_dirs *next;
|
||||||
|
/* Name of directory. */
|
||||||
|
const char *name;
|
||||||
|
/* TRUE if this is from the command line. */
|
||||||
|
bfd_boolean cmdline;
|
||||||
|
} search_dirs_type;
|
||||||
|
|
||||||
|
extern search_dirs_type *search_head;
|
||||||
|
|
||||||
|
extern void ldfile_add_arch
|
||||||
|
(const char *);
|
||||||
|
extern void ldfile_add_library_path
|
||||||
|
(const char *, bfd_boolean cmdline);
|
||||||
|
extern void ldfile_open_command_file
|
||||||
|
(const char *name);
|
||||||
|
extern void ldfile_open_default_command_file
|
||||||
|
(const char *name);
|
||||||
|
extern void ldfile_open_file
|
||||||
|
(struct lang_input_statement_struct *);
|
||||||
|
extern bfd_boolean ldfile_try_open_bfd
|
||||||
|
(const char *, struct lang_input_statement_struct *);
|
||||||
|
extern void ldfile_set_output_arch
|
||||||
|
(const char *, enum bfd_architecture);
|
||||||
|
extern bfd_boolean ldfile_open_file_search
|
||||||
|
(const char *arch, struct lang_input_statement_struct *,
|
||||||
|
const char *lib, const char *suffix);
|
||||||
|
|
||||||
|
#endif
|
4717
contrib/toolchain/binutils/ld/ldgram.c
Normal file
4717
contrib/toolchain/binutils/ld/ldgram.c
Normal file
File diff suppressed because it is too large
Load Diff
347
contrib/toolchain/binutils/ld/ldgram.h
Normal file
347
contrib/toolchain/binutils/ld/ldgram.h
Normal file
@ -0,0 +1,347 @@
|
|||||||
|
/* A Bison parser, made by GNU Bison 2.3. */
|
||||||
|
|
||||||
|
/* Skeleton interface for Bison's Yacc-like parsers in C
|
||||||
|
|
||||||
|
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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, 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., 51 Franklin Street, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
/* As a special exception, you may create a larger work that contains
|
||||||
|
part or all of the Bison parser skeleton and distribute that work
|
||||||
|
under terms of your choice, so long as that work isn't itself a
|
||||||
|
parser generator using the skeleton or a modified version thereof
|
||||||
|
as a parser skeleton. Alternatively, if you modify or redistribute
|
||||||
|
the parser skeleton itself, you may (at your option) remove this
|
||||||
|
special exception, which will cause the skeleton and the resulting
|
||||||
|
Bison output files to be licensed under the GNU General Public
|
||||||
|
License without this special exception.
|
||||||
|
|
||||||
|
This special exception was added by the Free Software Foundation in
|
||||||
|
version 2.2 of Bison. */
|
||||||
|
|
||||||
|
/* Tokens. */
|
||||||
|
#ifndef YYTOKENTYPE
|
||||||
|
# define YYTOKENTYPE
|
||||||
|
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
||||||
|
know about them. */
|
||||||
|
enum yytokentype {
|
||||||
|
INT = 258,
|
||||||
|
NAME = 259,
|
||||||
|
LNAME = 260,
|
||||||
|
OREQ = 261,
|
||||||
|
ANDEQ = 262,
|
||||||
|
RSHIFTEQ = 263,
|
||||||
|
LSHIFTEQ = 264,
|
||||||
|
DIVEQ = 265,
|
||||||
|
MULTEQ = 266,
|
||||||
|
MINUSEQ = 267,
|
||||||
|
PLUSEQ = 268,
|
||||||
|
OROR = 269,
|
||||||
|
ANDAND = 270,
|
||||||
|
NE = 271,
|
||||||
|
EQ = 272,
|
||||||
|
GE = 273,
|
||||||
|
LE = 274,
|
||||||
|
RSHIFT = 275,
|
||||||
|
LSHIFT = 276,
|
||||||
|
UNARY = 277,
|
||||||
|
END = 278,
|
||||||
|
ALIGN_K = 279,
|
||||||
|
BLOCK = 280,
|
||||||
|
BIND = 281,
|
||||||
|
QUAD = 282,
|
||||||
|
SQUAD = 283,
|
||||||
|
LONG = 284,
|
||||||
|
SHORT = 285,
|
||||||
|
BYTE = 286,
|
||||||
|
SECTIONS = 287,
|
||||||
|
PHDRS = 288,
|
||||||
|
INSERT_K = 289,
|
||||||
|
AFTER = 290,
|
||||||
|
BEFORE = 291,
|
||||||
|
DATA_SEGMENT_ALIGN = 292,
|
||||||
|
DATA_SEGMENT_RELRO_END = 293,
|
||||||
|
DATA_SEGMENT_END = 294,
|
||||||
|
SORT_BY_NAME = 295,
|
||||||
|
SORT_BY_ALIGNMENT = 296,
|
||||||
|
SORT_NONE = 297,
|
||||||
|
SORT_BY_INIT_PRIORITY = 298,
|
||||||
|
SIZEOF_HEADERS = 299,
|
||||||
|
OUTPUT_FORMAT = 300,
|
||||||
|
FORCE_COMMON_ALLOCATION = 301,
|
||||||
|
OUTPUT_ARCH = 302,
|
||||||
|
INHIBIT_COMMON_ALLOCATION = 303,
|
||||||
|
SEGMENT_START = 304,
|
||||||
|
INCLUDE = 305,
|
||||||
|
MEMORY = 306,
|
||||||
|
REGION_ALIAS = 307,
|
||||||
|
LD_FEATURE = 308,
|
||||||
|
NOLOAD = 309,
|
||||||
|
DSECT = 310,
|
||||||
|
COPY = 311,
|
||||||
|
INFO = 312,
|
||||||
|
OVERLAY = 313,
|
||||||
|
DEFINED = 314,
|
||||||
|
TARGET_K = 315,
|
||||||
|
SEARCH_DIR = 316,
|
||||||
|
MAP = 317,
|
||||||
|
ENTRY = 318,
|
||||||
|
NEXT = 319,
|
||||||
|
SIZEOF = 320,
|
||||||
|
ALIGNOF = 321,
|
||||||
|
ADDR = 322,
|
||||||
|
LOADADDR = 323,
|
||||||
|
MAX_K = 324,
|
||||||
|
MIN_K = 325,
|
||||||
|
STARTUP = 326,
|
||||||
|
HLL = 327,
|
||||||
|
SYSLIB = 328,
|
||||||
|
FLOAT = 329,
|
||||||
|
NOFLOAT = 330,
|
||||||
|
NOCROSSREFS = 331,
|
||||||
|
ORIGIN = 332,
|
||||||
|
FILL = 333,
|
||||||
|
LENGTH = 334,
|
||||||
|
CREATE_OBJECT_SYMBOLS = 335,
|
||||||
|
INPUT = 336,
|
||||||
|
GROUP = 337,
|
||||||
|
OUTPUT = 338,
|
||||||
|
CONSTRUCTORS = 339,
|
||||||
|
ALIGNMOD = 340,
|
||||||
|
AT = 341,
|
||||||
|
SUBALIGN = 342,
|
||||||
|
HIDDEN = 343,
|
||||||
|
PROVIDE = 344,
|
||||||
|
PROVIDE_HIDDEN = 345,
|
||||||
|
AS_NEEDED = 346,
|
||||||
|
CHIP = 347,
|
||||||
|
LIST = 348,
|
||||||
|
SECT = 349,
|
||||||
|
ABSOLUTE = 350,
|
||||||
|
LOAD = 351,
|
||||||
|
NEWLINE = 352,
|
||||||
|
ENDWORD = 353,
|
||||||
|
ORDER = 354,
|
||||||
|
NAMEWORD = 355,
|
||||||
|
ASSERT_K = 356,
|
||||||
|
LOG2CEIL = 357,
|
||||||
|
FORMAT = 358,
|
||||||
|
PUBLIC = 359,
|
||||||
|
DEFSYMEND = 360,
|
||||||
|
BASE = 361,
|
||||||
|
ALIAS = 362,
|
||||||
|
TRUNCATE = 363,
|
||||||
|
REL = 364,
|
||||||
|
INPUT_SCRIPT = 365,
|
||||||
|
INPUT_MRI_SCRIPT = 366,
|
||||||
|
INPUT_DEFSYM = 367,
|
||||||
|
CASE = 368,
|
||||||
|
EXTERN = 369,
|
||||||
|
START = 370,
|
||||||
|
VERS_TAG = 371,
|
||||||
|
VERS_IDENTIFIER = 372,
|
||||||
|
GLOBAL = 373,
|
||||||
|
LOCAL = 374,
|
||||||
|
VERSIONK = 375,
|
||||||
|
INPUT_VERSION_SCRIPT = 376,
|
||||||
|
KEEP = 377,
|
||||||
|
ONLY_IF_RO = 378,
|
||||||
|
ONLY_IF_RW = 379,
|
||||||
|
SPECIAL = 380,
|
||||||
|
INPUT_SECTION_FLAGS = 381,
|
||||||
|
ALIGN_WITH_INPUT = 382,
|
||||||
|
EXCLUDE_FILE = 383,
|
||||||
|
CONSTANT = 384,
|
||||||
|
INPUT_DYNAMIC_LIST = 385
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
/* Tokens. */
|
||||||
|
#define INT 258
|
||||||
|
#define NAME 259
|
||||||
|
#define LNAME 260
|
||||||
|
#define OREQ 261
|
||||||
|
#define ANDEQ 262
|
||||||
|
#define RSHIFTEQ 263
|
||||||
|
#define LSHIFTEQ 264
|
||||||
|
#define DIVEQ 265
|
||||||
|
#define MULTEQ 266
|
||||||
|
#define MINUSEQ 267
|
||||||
|
#define PLUSEQ 268
|
||||||
|
#define OROR 269
|
||||||
|
#define ANDAND 270
|
||||||
|
#define NE 271
|
||||||
|
#define EQ 272
|
||||||
|
#define GE 273
|
||||||
|
#define LE 274
|
||||||
|
#define RSHIFT 275
|
||||||
|
#define LSHIFT 276
|
||||||
|
#define UNARY 277
|
||||||
|
#define END 278
|
||||||
|
#define ALIGN_K 279
|
||||||
|
#define BLOCK 280
|
||||||
|
#define BIND 281
|
||||||
|
#define QUAD 282
|
||||||
|
#define SQUAD 283
|
||||||
|
#define LONG 284
|
||||||
|
#define SHORT 285
|
||||||
|
#define BYTE 286
|
||||||
|
#define SECTIONS 287
|
||||||
|
#define PHDRS 288
|
||||||
|
#define INSERT_K 289
|
||||||
|
#define AFTER 290
|
||||||
|
#define BEFORE 291
|
||||||
|
#define DATA_SEGMENT_ALIGN 292
|
||||||
|
#define DATA_SEGMENT_RELRO_END 293
|
||||||
|
#define DATA_SEGMENT_END 294
|
||||||
|
#define SORT_BY_NAME 295
|
||||||
|
#define SORT_BY_ALIGNMENT 296
|
||||||
|
#define SORT_NONE 297
|
||||||
|
#define SORT_BY_INIT_PRIORITY 298
|
||||||
|
#define SIZEOF_HEADERS 299
|
||||||
|
#define OUTPUT_FORMAT 300
|
||||||
|
#define FORCE_COMMON_ALLOCATION 301
|
||||||
|
#define OUTPUT_ARCH 302
|
||||||
|
#define INHIBIT_COMMON_ALLOCATION 303
|
||||||
|
#define SEGMENT_START 304
|
||||||
|
#define INCLUDE 305
|
||||||
|
#define MEMORY 306
|
||||||
|
#define REGION_ALIAS 307
|
||||||
|
#define LD_FEATURE 308
|
||||||
|
#define NOLOAD 309
|
||||||
|
#define DSECT 310
|
||||||
|
#define COPY 311
|
||||||
|
#define INFO 312
|
||||||
|
#define OVERLAY 313
|
||||||
|
#define DEFINED 314
|
||||||
|
#define TARGET_K 315
|
||||||
|
#define SEARCH_DIR 316
|
||||||
|
#define MAP 317
|
||||||
|
#define ENTRY 318
|
||||||
|
#define NEXT 319
|
||||||
|
#define SIZEOF 320
|
||||||
|
#define ALIGNOF 321
|
||||||
|
#define ADDR 322
|
||||||
|
#define LOADADDR 323
|
||||||
|
#define MAX_K 324
|
||||||
|
#define MIN_K 325
|
||||||
|
#define STARTUP 326
|
||||||
|
#define HLL 327
|
||||||
|
#define SYSLIB 328
|
||||||
|
#define FLOAT 329
|
||||||
|
#define NOFLOAT 330
|
||||||
|
#define NOCROSSREFS 331
|
||||||
|
#define ORIGIN 332
|
||||||
|
#define FILL 333
|
||||||
|
#define LENGTH 334
|
||||||
|
#define CREATE_OBJECT_SYMBOLS 335
|
||||||
|
#define INPUT 336
|
||||||
|
#define GROUP 337
|
||||||
|
#define OUTPUT 338
|
||||||
|
#define CONSTRUCTORS 339
|
||||||
|
#define ALIGNMOD 340
|
||||||
|
#define AT 341
|
||||||
|
#define SUBALIGN 342
|
||||||
|
#define HIDDEN 343
|
||||||
|
#define PROVIDE 344
|
||||||
|
#define PROVIDE_HIDDEN 345
|
||||||
|
#define AS_NEEDED 346
|
||||||
|
#define CHIP 347
|
||||||
|
#define LIST 348
|
||||||
|
#define SECT 349
|
||||||
|
#define ABSOLUTE 350
|
||||||
|
#define LOAD 351
|
||||||
|
#define NEWLINE 352
|
||||||
|
#define ENDWORD 353
|
||||||
|
#define ORDER 354
|
||||||
|
#define NAMEWORD 355
|
||||||
|
#define ASSERT_K 356
|
||||||
|
#define LOG2CEIL 357
|
||||||
|
#define FORMAT 358
|
||||||
|
#define PUBLIC 359
|
||||||
|
#define DEFSYMEND 360
|
||||||
|
#define BASE 361
|
||||||
|
#define ALIAS 362
|
||||||
|
#define TRUNCATE 363
|
||||||
|
#define REL 364
|
||||||
|
#define INPUT_SCRIPT 365
|
||||||
|
#define INPUT_MRI_SCRIPT 366
|
||||||
|
#define INPUT_DEFSYM 367
|
||||||
|
#define CASE 368
|
||||||
|
#define EXTERN 369
|
||||||
|
#define START 370
|
||||||
|
#define VERS_TAG 371
|
||||||
|
#define VERS_IDENTIFIER 372
|
||||||
|
#define GLOBAL 373
|
||||||
|
#define LOCAL 374
|
||||||
|
#define VERSIONK 375
|
||||||
|
#define INPUT_VERSION_SCRIPT 376
|
||||||
|
#define KEEP 377
|
||||||
|
#define ONLY_IF_RO 378
|
||||||
|
#define ONLY_IF_RW 379
|
||||||
|
#define SPECIAL 380
|
||||||
|
#define INPUT_SECTION_FLAGS 381
|
||||||
|
#define ALIGN_WITH_INPUT 382
|
||||||
|
#define EXCLUDE_FILE 383
|
||||||
|
#define CONSTANT 384
|
||||||
|
#define INPUT_DYNAMIC_LIST 385
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||||
|
typedef union YYSTYPE
|
||||||
|
#line 60 "ldgram.y"
|
||||||
|
{
|
||||||
|
bfd_vma integer;
|
||||||
|
struct big_int
|
||||||
|
{
|
||||||
|
bfd_vma integer;
|
||||||
|
char *str;
|
||||||
|
} bigint;
|
||||||
|
fill_type *fill;
|
||||||
|
char *name;
|
||||||
|
const char *cname;
|
||||||
|
struct wildcard_spec wildcard;
|
||||||
|
struct wildcard_list *wildcard_list;
|
||||||
|
struct name_list *name_list;
|
||||||
|
struct flag_info_list *flag_info_list;
|
||||||
|
struct flag_info *flag_info;
|
||||||
|
int token;
|
||||||
|
union etree_union *etree;
|
||||||
|
struct phdr_info
|
||||||
|
{
|
||||||
|
bfd_boolean filehdr;
|
||||||
|
bfd_boolean phdrs;
|
||||||
|
union etree_union *at;
|
||||||
|
union etree_union *flags;
|
||||||
|
} phdr;
|
||||||
|
struct lang_nocrossref *nocrossref;
|
||||||
|
struct lang_output_section_phdr_list *section_phdr;
|
||||||
|
struct bfd_elf_version_deps *deflist;
|
||||||
|
struct bfd_elf_version_expr *versyms;
|
||||||
|
struct bfd_elf_version_tree *versnode;
|
||||||
|
}
|
||||||
|
/* Line 1529 of yacc.c. */
|
||||||
|
#line 340 "ldgram.h"
|
||||||
|
YYSTYPE;
|
||||||
|
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||||
|
# define YYSTYPE_IS_DECLARED 1
|
||||||
|
# define YYSTYPE_IS_TRIVIAL 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern YYSTYPE yylval;
|
||||||
|
|
8066
contrib/toolchain/binutils/ld/ldlang.c
Normal file
8066
contrib/toolchain/binutils/ld/ldlang.c
Normal file
File diff suppressed because it is too large
Load Diff
663
contrib/toolchain/binutils/ld/ldlang.h
Normal file
663
contrib/toolchain/binutils/ld/ldlang.h
Normal file
@ -0,0 +1,663 @@
|
|||||||
|
/* ldlang.h - linker command language support
|
||||||
|
Copyright 1991-2013 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#ifndef LDLANG_H
|
||||||
|
#define LDLANG_H
|
||||||
|
|
||||||
|
#define DEFAULT_MEMORY_REGION "*default*"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
lang_input_file_is_l_enum,
|
||||||
|
lang_input_file_is_symbols_only_enum,
|
||||||
|
lang_input_file_is_marker_enum,
|
||||||
|
lang_input_file_is_fake_enum,
|
||||||
|
lang_input_file_is_search_file_enum,
|
||||||
|
lang_input_file_is_file_enum
|
||||||
|
} lang_input_file_enum_type;
|
||||||
|
|
||||||
|
struct _fill_type
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
unsigned char data[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct statement_list
|
||||||
|
{
|
||||||
|
union lang_statement_union * head;
|
||||||
|
union lang_statement_union ** tail;
|
||||||
|
} lang_statement_list_type;
|
||||||
|
|
||||||
|
typedef struct memory_region_name_struct
|
||||||
|
{
|
||||||
|
const char * name;
|
||||||
|
struct memory_region_name_struct * next;
|
||||||
|
} lang_memory_region_name;
|
||||||
|
|
||||||
|
typedef struct memory_region_struct
|
||||||
|
{
|
||||||
|
lang_memory_region_name name_list;
|
||||||
|
struct memory_region_struct *next;
|
||||||
|
bfd_vma origin;
|
||||||
|
bfd_size_type length;
|
||||||
|
bfd_vma current;
|
||||||
|
union lang_statement_union *last_os;
|
||||||
|
flagword flags;
|
||||||
|
flagword not_flags;
|
||||||
|
bfd_boolean had_full_message;
|
||||||
|
} lang_memory_region_type;
|
||||||
|
|
||||||
|
enum statement_enum
|
||||||
|
{
|
||||||
|
lang_output_section_statement_enum,
|
||||||
|
lang_assignment_statement_enum,
|
||||||
|
lang_input_statement_enum,
|
||||||
|
lang_address_statement_enum,
|
||||||
|
lang_wild_statement_enum,
|
||||||
|
lang_input_section_enum,
|
||||||
|
lang_object_symbols_statement_enum,
|
||||||
|
lang_fill_statement_enum,
|
||||||
|
lang_data_statement_enum,
|
||||||
|
lang_reloc_statement_enum,
|
||||||
|
lang_target_statement_enum,
|
||||||
|
lang_output_statement_enum,
|
||||||
|
lang_padding_statement_enum,
|
||||||
|
lang_group_statement_enum,
|
||||||
|
lang_insert_statement_enum,
|
||||||
|
lang_constructors_statement_enum
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct lang_statement_header_struct
|
||||||
|
{
|
||||||
|
union lang_statement_union *next;
|
||||||
|
enum statement_enum type;
|
||||||
|
} lang_statement_header_type;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
lang_statement_header_type header;
|
||||||
|
union etree_union *exp;
|
||||||
|
} lang_assignment_statement_type;
|
||||||
|
|
||||||
|
typedef struct lang_target_statement_struct
|
||||||
|
{
|
||||||
|
lang_statement_header_type header;
|
||||||
|
const char *target;
|
||||||
|
} lang_target_statement_type;
|
||||||
|
|
||||||
|
typedef struct lang_output_statement_struct
|
||||||
|
{
|
||||||
|
lang_statement_header_type header;
|
||||||
|
const char *name;
|
||||||
|
} lang_output_statement_type;
|
||||||
|
|
||||||
|
/* Section types specified in a linker script. */
|
||||||
|
|
||||||
|
enum section_type
|
||||||
|
{
|
||||||
|
normal_section,
|
||||||
|
overlay_section,
|
||||||
|
noload_section,
|
||||||
|
noalloc_section
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This structure holds a list of program headers describing
|
||||||
|
segments in which this section should be placed. */
|
||||||
|
|
||||||
|
typedef struct lang_output_section_phdr_list
|
||||||
|
{
|
||||||
|
struct lang_output_section_phdr_list *next;
|
||||||
|
const char *name;
|
||||||
|
bfd_boolean used;
|
||||||
|
} lang_output_section_phdr_list;
|
||||||
|
|
||||||
|
typedef struct lang_output_section_statement_struct
|
||||||
|
{
|
||||||
|
lang_statement_header_type header;
|
||||||
|
lang_statement_list_type children;
|
||||||
|
struct lang_output_section_statement_struct *next;
|
||||||
|
struct lang_output_section_statement_struct *prev;
|
||||||
|
const char *name;
|
||||||
|
asection *bfd_section;
|
||||||
|
lang_memory_region_type *region;
|
||||||
|
lang_memory_region_type *lma_region;
|
||||||
|
fill_type *fill;
|
||||||
|
union etree_union *addr_tree;
|
||||||
|
union etree_union *load_base;
|
||||||
|
|
||||||
|
/* If non-null, an expression to evaluate after setting the section's
|
||||||
|
size. The expression is evaluated inside REGION (above) with '.'
|
||||||
|
set to the end of the section. Used in the last overlay section
|
||||||
|
to move '.' past all the overlaid sections. */
|
||||||
|
union etree_union *update_dot_tree;
|
||||||
|
|
||||||
|
lang_output_section_phdr_list *phdrs;
|
||||||
|
|
||||||
|
unsigned int block_value;
|
||||||
|
int subsection_alignment; /* Alignment of components. */
|
||||||
|
int section_alignment; /* Alignment of start of section. */
|
||||||
|
int constraint;
|
||||||
|
flagword flags;
|
||||||
|
enum section_type sectype;
|
||||||
|
unsigned int processed_vma : 1;
|
||||||
|
unsigned int processed_lma : 1;
|
||||||
|
unsigned int all_input_readonly : 1;
|
||||||
|
/* If this section should be ignored. */
|
||||||
|
unsigned int ignored : 1;
|
||||||
|
/* If this section should update "dot". Prevents section being ignored. */
|
||||||
|
unsigned int update_dot : 1;
|
||||||
|
/* If this section is after assignment to _end. */
|
||||||
|
unsigned int after_end : 1;
|
||||||
|
/* If this section uses the alignment of its input sections. */
|
||||||
|
unsigned int align_lma_with_input : 1;
|
||||||
|
} lang_output_section_statement_type;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
lang_statement_header_type header;
|
||||||
|
} lang_common_statement_type;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
lang_statement_header_type header;
|
||||||
|
} lang_object_symbols_statement_type;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
lang_statement_header_type header;
|
||||||
|
fill_type *fill;
|
||||||
|
int size;
|
||||||
|
asection *output_section;
|
||||||
|
} lang_fill_statement_type;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
lang_statement_header_type header;
|
||||||
|
unsigned int type;
|
||||||
|
union etree_union *exp;
|
||||||
|
bfd_vma value;
|
||||||
|
asection *output_section;
|
||||||
|
bfd_vma output_offset;
|
||||||
|
} lang_data_statement_type;
|
||||||
|
|
||||||
|
/* Generate a reloc in the output file. */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
lang_statement_header_type header;
|
||||||
|
|
||||||
|
/* Reloc to generate. */
|
||||||
|
bfd_reloc_code_real_type reloc;
|
||||||
|
|
||||||
|
/* Reloc howto structure. */
|
||||||
|
reloc_howto_type *howto;
|
||||||
|
|
||||||
|
/* Section to generate reloc against.
|
||||||
|
Exactly one of section and name must be NULL. */
|
||||||
|
asection *section;
|
||||||
|
|
||||||
|
/* Name of symbol to generate reloc against.
|
||||||
|
Exactly one of section and name must be NULL. */
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
/* Expression for addend. */
|
||||||
|
union etree_union *addend_exp;
|
||||||
|
|
||||||
|
/* Resolved addend. */
|
||||||
|
bfd_vma addend_value;
|
||||||
|
|
||||||
|
/* Output section where reloc should be performed. */
|
||||||
|
asection *output_section;
|
||||||
|
|
||||||
|
/* Offset within output section. */
|
||||||
|
bfd_vma output_offset;
|
||||||
|
} lang_reloc_statement_type;
|
||||||
|
|
||||||
|
struct lang_input_statement_flags
|
||||||
|
{
|
||||||
|
/* 1 means this file was specified in a -l option. */
|
||||||
|
unsigned int maybe_archive : 1;
|
||||||
|
|
||||||
|
/* 1 means search a set of directories for this file. */
|
||||||
|
unsigned int search_dirs : 1;
|
||||||
|
|
||||||
|
/* 1 means this was found when processing a script in the sysroot. */
|
||||||
|
unsigned int sysrooted : 1;
|
||||||
|
|
||||||
|
/* 1 means this is base file of incremental load.
|
||||||
|
Do not load this file's text or data.
|
||||||
|
Also default text_start to after this file's bss. */
|
||||||
|
unsigned int just_syms : 1;
|
||||||
|
|
||||||
|
/* Whether to search for this entry as a dynamic archive. */
|
||||||
|
unsigned int dynamic : 1;
|
||||||
|
|
||||||
|
/* Set if a DT_NEEDED tag should be added not just for the dynamic library
|
||||||
|
explicitly given by this entry but also for any dynamic libraries in
|
||||||
|
this entry's needed list. */
|
||||||
|
unsigned int add_DT_NEEDED_for_dynamic : 1;
|
||||||
|
|
||||||
|
/* Set if this entry should cause a DT_NEEDED tag only when some
|
||||||
|
regular file references its symbols (ie. --as-needed is in effect). */
|
||||||
|
unsigned int add_DT_NEEDED_for_regular : 1;
|
||||||
|
|
||||||
|
/* Whether to include the entire contents of an archive. */
|
||||||
|
unsigned int whole_archive : 1;
|
||||||
|
|
||||||
|
/* Set when bfd opening is successful. */
|
||||||
|
unsigned int loaded : 1;
|
||||||
|
|
||||||
|
unsigned int real : 1;
|
||||||
|
|
||||||
|
/* Set if the file does not exist. */
|
||||||
|
unsigned int missing_file : 1;
|
||||||
|
|
||||||
|
#ifdef ENABLE_PLUGINS
|
||||||
|
/* Set if the file was claimed by a plugin. */
|
||||||
|
unsigned int claimed : 1;
|
||||||
|
|
||||||
|
/* Set if the file was claimed from an archive. */
|
||||||
|
unsigned int claim_archive : 1;
|
||||||
|
|
||||||
|
/* Set if reloading an --as-needed lib. */
|
||||||
|
unsigned int reload : 1;
|
||||||
|
#endif /* ENABLE_PLUGINS */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct lang_input_statement_struct
|
||||||
|
{
|
||||||
|
lang_statement_header_type header;
|
||||||
|
/* Name of this file. */
|
||||||
|
const char *filename;
|
||||||
|
/* Name to use for the symbol giving address of text start.
|
||||||
|
Usually the same as filename, but for a file spec'd with
|
||||||
|
-l this is the -l switch itself rather than the filename. */
|
||||||
|
const char *local_sym_name;
|
||||||
|
|
||||||
|
bfd *the_bfd;
|
||||||
|
|
||||||
|
struct flag_info *section_flag_list;
|
||||||
|
|
||||||
|
/* Point to the next file - whatever it is, wanders up and down
|
||||||
|
archives */
|
||||||
|
union lang_statement_union *next;
|
||||||
|
|
||||||
|
/* Point to the next file, but skips archive contents. */
|
||||||
|
union lang_statement_union *next_real_file;
|
||||||
|
|
||||||
|
const char *target;
|
||||||
|
|
||||||
|
struct lang_input_statement_flags flags;
|
||||||
|
} lang_input_statement_type;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
lang_statement_header_type header;
|
||||||
|
asection *section;
|
||||||
|
} lang_input_section_type;
|
||||||
|
|
||||||
|
typedef struct lang_wild_statement_struct lang_wild_statement_type;
|
||||||
|
|
||||||
|
typedef void (*callback_t) (lang_wild_statement_type *, struct wildcard_list *,
|
||||||
|
asection *, struct flag_info *,
|
||||||
|
lang_input_statement_type *, void *);
|
||||||
|
|
||||||
|
typedef void (*walk_wild_section_handler_t) (lang_wild_statement_type *,
|
||||||
|
lang_input_statement_type *,
|
||||||
|
callback_t callback,
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
typedef bfd_boolean (*lang_match_sec_type_func) (bfd *, const asection *,
|
||||||
|
bfd *, const asection *);
|
||||||
|
|
||||||
|
/* Binary search tree structure to efficiently sort sections by
|
||||||
|
name. */
|
||||||
|
typedef struct lang_section_bst
|
||||||
|
{
|
||||||
|
asection *section;
|
||||||
|
struct lang_section_bst *left;
|
||||||
|
struct lang_section_bst *right;
|
||||||
|
} lang_section_bst_type;
|
||||||
|
|
||||||
|
struct lang_wild_statement_struct
|
||||||
|
{
|
||||||
|
lang_statement_header_type header;
|
||||||
|
const char *filename;
|
||||||
|
bfd_boolean filenames_sorted;
|
||||||
|
struct wildcard_list *section_list;
|
||||||
|
bfd_boolean keep_sections;
|
||||||
|
lang_statement_list_type children;
|
||||||
|
|
||||||
|
walk_wild_section_handler_t walk_wild_section_handler;
|
||||||
|
struct wildcard_list *handler_data[4];
|
||||||
|
lang_section_bst_type *tree;
|
||||||
|
struct flag_info *section_flag_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct lang_address_statement_struct
|
||||||
|
{
|
||||||
|
lang_statement_header_type header;
|
||||||
|
const char *section_name;
|
||||||
|
union etree_union *address;
|
||||||
|
const segment_type *segment;
|
||||||
|
} lang_address_statement_type;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
lang_statement_header_type header;
|
||||||
|
bfd_vma output_offset;
|
||||||
|
bfd_size_type size;
|
||||||
|
asection *output_section;
|
||||||
|
fill_type *fill;
|
||||||
|
} lang_padding_statement_type;
|
||||||
|
|
||||||
|
/* A group statement collects a set of libraries together. The
|
||||||
|
libraries are searched multiple times, until no new undefined
|
||||||
|
symbols are found. The effect is to search a group of libraries as
|
||||||
|
though they were a single library. */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
lang_statement_header_type header;
|
||||||
|
lang_statement_list_type children;
|
||||||
|
} lang_group_statement_type;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
lang_statement_header_type header;
|
||||||
|
const char *where;
|
||||||
|
bfd_boolean is_before;
|
||||||
|
} lang_insert_statement_type;
|
||||||
|
|
||||||
|
typedef union lang_statement_union
|
||||||
|
{
|
||||||
|
lang_statement_header_type header;
|
||||||
|
lang_wild_statement_type wild_statement;
|
||||||
|
lang_data_statement_type data_statement;
|
||||||
|
lang_reloc_statement_type reloc_statement;
|
||||||
|
lang_address_statement_type address_statement;
|
||||||
|
lang_output_section_statement_type output_section_statement;
|
||||||
|
lang_assignment_statement_type assignment_statement;
|
||||||
|
lang_input_statement_type input_statement;
|
||||||
|
lang_target_statement_type target_statement;
|
||||||
|
lang_output_statement_type output_statement;
|
||||||
|
lang_input_section_type input_section;
|
||||||
|
lang_common_statement_type common_statement;
|
||||||
|
lang_object_symbols_statement_type object_symbols_statement;
|
||||||
|
lang_fill_statement_type fill_statement;
|
||||||
|
lang_padding_statement_type padding_statement;
|
||||||
|
lang_group_statement_type group_statement;
|
||||||
|
lang_insert_statement_type insert_statement;
|
||||||
|
} lang_statement_union_type;
|
||||||
|
|
||||||
|
/* This structure holds information about a program header, from the
|
||||||
|
PHDRS command in the linker script. */
|
||||||
|
|
||||||
|
struct lang_phdr
|
||||||
|
{
|
||||||
|
struct lang_phdr *next;
|
||||||
|
const char *name;
|
||||||
|
unsigned long type;
|
||||||
|
bfd_boolean filehdr;
|
||||||
|
bfd_boolean phdrs;
|
||||||
|
etree_type *at;
|
||||||
|
etree_type *flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This structure is used to hold a list of sections which may not
|
||||||
|
cross reference each other. */
|
||||||
|
|
||||||
|
typedef struct lang_nocrossref
|
||||||
|
{
|
||||||
|
struct lang_nocrossref *next;
|
||||||
|
const char *name;
|
||||||
|
} lang_nocrossref_type;
|
||||||
|
|
||||||
|
/* The list of nocrossref lists. */
|
||||||
|
|
||||||
|
struct lang_nocrossrefs
|
||||||
|
{
|
||||||
|
struct lang_nocrossrefs *next;
|
||||||
|
lang_nocrossref_type *list;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This structure is used to hold a list of input section names which
|
||||||
|
will not match an output section in the linker script. */
|
||||||
|
|
||||||
|
struct unique_sections
|
||||||
|
{
|
||||||
|
struct unique_sections *next;
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This structure records symbols for which we need to keep track of
|
||||||
|
definedness for use in the DEFINED () test. */
|
||||||
|
|
||||||
|
struct lang_definedness_hash_entry
|
||||||
|
{
|
||||||
|
struct bfd_hash_entry root;
|
||||||
|
int iteration;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Used by place_orphan to keep track of orphan sections and statements. */
|
||||||
|
|
||||||
|
struct orphan_save
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
flagword flags;
|
||||||
|
lang_output_section_statement_type *os;
|
||||||
|
asection **section;
|
||||||
|
lang_statement_union_type **stmt;
|
||||||
|
lang_output_section_statement_type **os_tail;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct lang_phdr *lang_phdr_list;
|
||||||
|
extern struct lang_nocrossrefs *nocrossref_list;
|
||||||
|
extern const char *output_target;
|
||||||
|
extern lang_output_section_statement_type *abs_output_section;
|
||||||
|
extern lang_statement_list_type lang_output_section_statement;
|
||||||
|
extern struct lang_input_statement_flags input_flags;
|
||||||
|
extern bfd_boolean lang_has_input_file;
|
||||||
|
extern etree_type *base;
|
||||||
|
extern lang_statement_list_type *stat_ptr;
|
||||||
|
extern bfd_boolean delete_output_file_on_failure;
|
||||||
|
|
||||||
|
extern struct bfd_sym_chain entry_symbol;
|
||||||
|
extern const char *entry_section;
|
||||||
|
extern bfd_boolean entry_from_cmdline;
|
||||||
|
extern lang_statement_list_type file_chain;
|
||||||
|
extern lang_statement_list_type input_file_chain;
|
||||||
|
|
||||||
|
extern int lang_statement_iteration;
|
||||||
|
|
||||||
|
extern void lang_init
|
||||||
|
(void);
|
||||||
|
extern void lang_finish
|
||||||
|
(void);
|
||||||
|
extern lang_memory_region_type * lang_memory_region_lookup
|
||||||
|
(const char * const, bfd_boolean);
|
||||||
|
extern void lang_memory_region_alias
|
||||||
|
(const char *, const char *);
|
||||||
|
extern void lang_map
|
||||||
|
(void);
|
||||||
|
extern void lang_set_flags
|
||||||
|
(lang_memory_region_type *, const char *, int);
|
||||||
|
extern void lang_add_output
|
||||||
|
(const char *, int from_script);
|
||||||
|
extern lang_output_section_statement_type *lang_enter_output_section_statement
|
||||||
|
(const char *, etree_type *, enum section_type, etree_type *, etree_type *,
|
||||||
|
etree_type *, int, int);
|
||||||
|
extern void lang_final
|
||||||
|
(void);
|
||||||
|
extern void lang_relax_sections
|
||||||
|
(bfd_boolean);
|
||||||
|
extern void lang_process
|
||||||
|
(void);
|
||||||
|
extern void lang_section_start
|
||||||
|
(const char *, union etree_union *, const segment_type *);
|
||||||
|
extern void lang_add_entry
|
||||||
|
(const char *, bfd_boolean);
|
||||||
|
extern void lang_default_entry
|
||||||
|
(const char *);
|
||||||
|
extern void lang_add_target
|
||||||
|
(const char *);
|
||||||
|
extern void lang_add_wild
|
||||||
|
(struct wildcard_spec *, struct wildcard_list *, bfd_boolean);
|
||||||
|
extern void lang_add_map
|
||||||
|
(const char *);
|
||||||
|
extern void lang_add_fill
|
||||||
|
(fill_type *);
|
||||||
|
extern lang_assignment_statement_type *lang_add_assignment
|
||||||
|
(union etree_union *);
|
||||||
|
extern void lang_add_attribute
|
||||||
|
(enum statement_enum);
|
||||||
|
extern void lang_startup
|
||||||
|
(const char *);
|
||||||
|
extern void lang_float
|
||||||
|
(bfd_boolean);
|
||||||
|
extern void lang_leave_output_section_statement
|
||||||
|
(fill_type *, const char *, lang_output_section_phdr_list *,
|
||||||
|
const char *);
|
||||||
|
extern void lang_statement_append
|
||||||
|
(lang_statement_list_type *, lang_statement_union_type *,
|
||||||
|
lang_statement_union_type **);
|
||||||
|
extern void lang_for_each_input_file
|
||||||
|
(void (*dothis) (lang_input_statement_type *));
|
||||||
|
extern void lang_for_each_file
|
||||||
|
(void (*dothis) (lang_input_statement_type *));
|
||||||
|
extern void lang_reset_memory_regions
|
||||||
|
(void);
|
||||||
|
extern void lang_do_assignments
|
||||||
|
(lang_phase_type);
|
||||||
|
extern asection *section_for_dot
|
||||||
|
(void);
|
||||||
|
|
||||||
|
#define LANG_FOR_EACH_INPUT_STATEMENT(statement) \
|
||||||
|
lang_input_statement_type *statement; \
|
||||||
|
for (statement = (lang_input_statement_type *) file_chain.head; \
|
||||||
|
statement != (lang_input_statement_type *) NULL; \
|
||||||
|
statement = (lang_input_statement_type *) statement->next) \
|
||||||
|
|
||||||
|
#define lang_output_section_find(NAME) \
|
||||||
|
lang_output_section_statement_lookup (NAME, 0, FALSE)
|
||||||
|
|
||||||
|
extern void lang_process
|
||||||
|
(void);
|
||||||
|
extern void ldlang_add_file
|
||||||
|
(lang_input_statement_type *);
|
||||||
|
extern lang_output_section_statement_type *lang_output_section_find_by_flags
|
||||||
|
(const asection *, lang_output_section_statement_type **,
|
||||||
|
lang_match_sec_type_func);
|
||||||
|
extern lang_output_section_statement_type *lang_insert_orphan
|
||||||
|
(asection *, const char *, int, lang_output_section_statement_type *,
|
||||||
|
struct orphan_save *, etree_type *, lang_statement_list_type *);
|
||||||
|
extern lang_input_statement_type *lang_add_input_file
|
||||||
|
(const char *, lang_input_file_enum_type, const char *);
|
||||||
|
extern void lang_add_keepsyms_file
|
||||||
|
(const char *);
|
||||||
|
extern lang_output_section_statement_type *lang_output_section_statement_lookup
|
||||||
|
(const char *, int, bfd_boolean);
|
||||||
|
extern lang_output_section_statement_type *next_matching_output_section_statement
|
||||||
|
(lang_output_section_statement_type *, int);
|
||||||
|
extern void ldlang_add_undef
|
||||||
|
(const char *const, bfd_boolean);
|
||||||
|
extern void lang_add_output_format
|
||||||
|
(const char *, const char *, const char *, int);
|
||||||
|
extern void lang_list_init
|
||||||
|
(lang_statement_list_type *);
|
||||||
|
extern void push_stat_ptr
|
||||||
|
(lang_statement_list_type *);
|
||||||
|
extern void pop_stat_ptr
|
||||||
|
(void);
|
||||||
|
extern void lang_add_data
|
||||||
|
(int type, union etree_union *);
|
||||||
|
extern void lang_add_reloc
|
||||||
|
(bfd_reloc_code_real_type, reloc_howto_type *, asection *, const char *,
|
||||||
|
union etree_union *);
|
||||||
|
extern void lang_for_each_statement
|
||||||
|
(void (*) (lang_statement_union_type *));
|
||||||
|
extern void lang_for_each_statement_worker
|
||||||
|
(void (*) (lang_statement_union_type *), lang_statement_union_type *);
|
||||||
|
extern void *stat_alloc
|
||||||
|
(size_t);
|
||||||
|
extern void strip_excluded_output_sections
|
||||||
|
(void);
|
||||||
|
extern void dprint_statement
|
||||||
|
(lang_statement_union_type *, int);
|
||||||
|
extern void lang_size_sections
|
||||||
|
(bfd_boolean *, bfd_boolean);
|
||||||
|
extern void one_lang_size_sections_pass
|
||||||
|
(bfd_boolean *, bfd_boolean);
|
||||||
|
extern void lang_add_insert
|
||||||
|
(const char *, int);
|
||||||
|
extern void lang_enter_group
|
||||||
|
(void);
|
||||||
|
extern void lang_leave_group
|
||||||
|
(void);
|
||||||
|
extern void lang_add_section
|
||||||
|
(lang_statement_list_type *, asection *,
|
||||||
|
struct flag_info *, lang_output_section_statement_type *);
|
||||||
|
extern void lang_new_phdr
|
||||||
|
(const char *, etree_type *, bfd_boolean, bfd_boolean, etree_type *,
|
||||||
|
etree_type *);
|
||||||
|
extern void lang_add_nocrossref
|
||||||
|
(lang_nocrossref_type *);
|
||||||
|
extern void lang_enter_overlay
|
||||||
|
(etree_type *, etree_type *);
|
||||||
|
extern void lang_enter_overlay_section
|
||||||
|
(const char *);
|
||||||
|
extern void lang_leave_overlay_section
|
||||||
|
(fill_type *, lang_output_section_phdr_list *);
|
||||||
|
extern void lang_leave_overlay
|
||||||
|
(etree_type *, int, fill_type *, const char *,
|
||||||
|
lang_output_section_phdr_list *, const char *);
|
||||||
|
|
||||||
|
extern struct bfd_elf_version_expr *lang_new_vers_pattern
|
||||||
|
(struct bfd_elf_version_expr *, const char *, const char *, bfd_boolean);
|
||||||
|
extern struct bfd_elf_version_tree *lang_new_vers_node
|
||||||
|
(struct bfd_elf_version_expr *, struct bfd_elf_version_expr *);
|
||||||
|
extern struct bfd_elf_version_deps *lang_add_vers_depend
|
||||||
|
(struct bfd_elf_version_deps *, const char *);
|
||||||
|
extern void lang_register_vers_node
|
||||||
|
(const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *);
|
||||||
|
extern void lang_append_dynamic_list (struct bfd_elf_version_expr *);
|
||||||
|
extern void lang_append_dynamic_list_cpp_typeinfo (void);
|
||||||
|
extern void lang_append_dynamic_list_cpp_new (void);
|
||||||
|
extern void lang_add_unique
|
||||||
|
(const char *);
|
||||||
|
extern const char *lang_get_output_target
|
||||||
|
(void);
|
||||||
|
extern void lang_track_definedness (const char *);
|
||||||
|
extern int lang_symbol_definition_iteration (const char *);
|
||||||
|
extern void lang_update_definedness
|
||||||
|
(const char *, struct bfd_link_hash_entry *);
|
||||||
|
|
||||||
|
extern void add_excluded_libs (const char *);
|
||||||
|
extern bfd_boolean load_symbols
|
||||||
|
(lang_input_statement_type *, lang_statement_list_type *);
|
||||||
|
|
||||||
|
extern bfd_boolean
|
||||||
|
ldlang_override_segment_assignment
|
||||||
|
(struct bfd_link_info *, bfd *, asection *, asection *, bfd_boolean);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
lang_ld_feature (char *);
|
||||||
|
|
||||||
|
#endif
|
26
contrib/toolchain/binutils/ld/ldlex-wrapper.c
Normal file
26
contrib/toolchain/binutils/ld/ldlex-wrapper.c
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/* Copyright 2012 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
/* The flex output (ldlex.c) includes stdio.h before any of the C code
|
||||||
|
in ldlex.l. Make sure we include sysdep.h first, so that config.h
|
||||||
|
can select the correct value of things like _FILE_OFFSET_BITS and
|
||||||
|
_LARGE_FILES. */
|
||||||
|
|
||||||
|
#include "sysdep.h"
|
||||||
|
#include "ldlex.c"
|
4348
contrib/toolchain/binutils/ld/ldlex.c
Normal file
4348
contrib/toolchain/binutils/ld/ldlex.c
Normal file
File diff suppressed because it is too large
Load Diff
181
contrib/toolchain/binutils/ld/ldlex.h
Normal file
181
contrib/toolchain/binutils/ld/ldlex.h
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
/* ldlex.h -
|
||||||
|
Copyright 1991, 1992, 1993, 1994, 1995, 1997, 2000, 2003, 2005, 2006,
|
||||||
|
2007, 2012 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#ifndef LDLEX_H
|
||||||
|
#define LDLEX_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* Codes used for the long options with no short synonyms. 150 isn't
|
||||||
|
special; it's just an arbitrary non-ASCII char value. */
|
||||||
|
enum option_values
|
||||||
|
{
|
||||||
|
OPTION_ASSERT = 150,
|
||||||
|
OPTION_CALL_SHARED,
|
||||||
|
OPTION_CREF,
|
||||||
|
OPTION_DEFSYM,
|
||||||
|
OPTION_DEMANGLE,
|
||||||
|
OPTION_DYNAMIC_LINKER,
|
||||||
|
OPTION_SYSROOT,
|
||||||
|
OPTION_EB,
|
||||||
|
OPTION_EL,
|
||||||
|
OPTION_EMBEDDED_RELOCS,
|
||||||
|
OPTION_EXPORT_DYNAMIC,
|
||||||
|
OPTION_NO_EXPORT_DYNAMIC,
|
||||||
|
OPTION_HELP,
|
||||||
|
OPTION_IGNORE,
|
||||||
|
OPTION_MAP,
|
||||||
|
OPTION_NO_DEMANGLE,
|
||||||
|
OPTION_NO_KEEP_MEMORY,
|
||||||
|
OPTION_NO_WARN_MISMATCH,
|
||||||
|
OPTION_NO_WARN_SEARCH_MISMATCH,
|
||||||
|
OPTION_NOINHIBIT_EXEC,
|
||||||
|
OPTION_NON_SHARED,
|
||||||
|
OPTION_NO_WHOLE_ARCHIVE,
|
||||||
|
OPTION_OFORMAT,
|
||||||
|
OPTION_RELAX,
|
||||||
|
OPTION_NO_RELAX,
|
||||||
|
OPTION_RETAIN_SYMBOLS_FILE,
|
||||||
|
OPTION_RPATH,
|
||||||
|
OPTION_RPATH_LINK,
|
||||||
|
OPTION_SHARED,
|
||||||
|
OPTION_SONAME,
|
||||||
|
OPTION_SORT_COMMON,
|
||||||
|
OPTION_SORT_SECTION,
|
||||||
|
OPTION_STATS,
|
||||||
|
OPTION_SYMBOLIC,
|
||||||
|
OPTION_SYMBOLIC_FUNCTIONS,
|
||||||
|
OPTION_TASK_LINK,
|
||||||
|
OPTION_TBSS,
|
||||||
|
OPTION_TDATA,
|
||||||
|
OPTION_TTEXT,
|
||||||
|
OPTION_TTEXT_SEGMENT,
|
||||||
|
OPTION_TRODATA_SEGMENT,
|
||||||
|
OPTION_TLDATA_SEGMENT,
|
||||||
|
OPTION_TRADITIONAL_FORMAT,
|
||||||
|
OPTION_UR,
|
||||||
|
OPTION_VERBOSE,
|
||||||
|
OPTION_VERSION,
|
||||||
|
OPTION_VERSION_SCRIPT,
|
||||||
|
OPTION_VERSION_EXPORTS_SECTION,
|
||||||
|
OPTION_DYNAMIC_LIST,
|
||||||
|
OPTION_DYNAMIC_LIST_CPP_NEW,
|
||||||
|
OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
|
||||||
|
OPTION_DYNAMIC_LIST_DATA,
|
||||||
|
OPTION_WARN_COMMON,
|
||||||
|
OPTION_WARN_CONSTRUCTORS,
|
||||||
|
OPTION_WARN_FATAL,
|
||||||
|
OPTION_NO_WARN_FATAL,
|
||||||
|
OPTION_WARN_MULTIPLE_GP,
|
||||||
|
OPTION_WARN_ONCE,
|
||||||
|
OPTION_WARN_SECTION_ALIGN,
|
||||||
|
OPTION_SPLIT_BY_RELOC,
|
||||||
|
OPTION_SPLIT_BY_FILE ,
|
||||||
|
OPTION_WHOLE_ARCHIVE,
|
||||||
|
OPTION_ADD_DT_NEEDED_FOR_DYNAMIC,
|
||||||
|
OPTION_NO_ADD_DT_NEEDED_FOR_DYNAMIC,
|
||||||
|
OPTION_ADD_DT_NEEDED_FOR_REGULAR,
|
||||||
|
OPTION_NO_ADD_DT_NEEDED_FOR_REGULAR,
|
||||||
|
OPTION_WRAP,
|
||||||
|
OPTION_FORCE_EXE_SUFFIX,
|
||||||
|
OPTION_GC_SECTIONS,
|
||||||
|
OPTION_NO_GC_SECTIONS,
|
||||||
|
OPTION_PRINT_GC_SECTIONS,
|
||||||
|
OPTION_NO_PRINT_GC_SECTIONS,
|
||||||
|
OPTION_HASH_SIZE,
|
||||||
|
OPTION_CHECK_SECTIONS,
|
||||||
|
OPTION_NO_CHECK_SECTIONS,
|
||||||
|
OPTION_NO_UNDEFINED,
|
||||||
|
OPTION_INIT,
|
||||||
|
OPTION_FINI,
|
||||||
|
OPTION_SECTION_START,
|
||||||
|
OPTION_UNIQUE,
|
||||||
|
OPTION_TARGET_HELP,
|
||||||
|
OPTION_ALLOW_SHLIB_UNDEFINED,
|
||||||
|
OPTION_NO_ALLOW_SHLIB_UNDEFINED,
|
||||||
|
OPTION_ALLOW_MULTIPLE_DEFINITION,
|
||||||
|
OPTION_NO_UNDEFINED_VERSION,
|
||||||
|
OPTION_DEFAULT_SYMVER,
|
||||||
|
OPTION_DEFAULT_IMPORTED_SYMVER,
|
||||||
|
OPTION_DISCARD_NONE,
|
||||||
|
OPTION_SPARE_DYNAMIC_TAGS,
|
||||||
|
OPTION_NO_DEFINE_COMMON,
|
||||||
|
OPTION_NOSTDLIB,
|
||||||
|
OPTION_NO_OMAGIC,
|
||||||
|
OPTION_STRIP_DISCARDED,
|
||||||
|
OPTION_NO_STRIP_DISCARDED,
|
||||||
|
OPTION_ACCEPT_UNKNOWN_INPUT_ARCH,
|
||||||
|
OPTION_NO_ACCEPT_UNKNOWN_INPUT_ARCH,
|
||||||
|
OPTION_PIE,
|
||||||
|
OPTION_UNRESOLVED_SYMBOLS,
|
||||||
|
OPTION_WARN_UNRESOLVED_SYMBOLS,
|
||||||
|
OPTION_ERROR_UNRESOLVED_SYMBOLS,
|
||||||
|
OPTION_WARN_SHARED_TEXTREL,
|
||||||
|
OPTION_WARN_ALTERNATE_EM,
|
||||||
|
OPTION_REDUCE_MEMORY_OVERHEADS,
|
||||||
|
#ifdef ENABLE_PLUGINS
|
||||||
|
OPTION_PLUGIN,
|
||||||
|
OPTION_PLUGIN_OPT,
|
||||||
|
#endif /* ENABLE_PLUGINS */
|
||||||
|
OPTION_DEFAULT_SCRIPT,
|
||||||
|
OPTION_PRINT_OUTPUT_FORMAT,
|
||||||
|
OPTION_IGNORE_UNRESOLVED_SYMBOL,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The initial parser states. */
|
||||||
|
typedef enum input_enum {
|
||||||
|
input_selected, /* We've set the initial state. */
|
||||||
|
input_script,
|
||||||
|
input_mri_script,
|
||||||
|
input_version_script,
|
||||||
|
input_dynamic_list,
|
||||||
|
input_defsym
|
||||||
|
} input_type;
|
||||||
|
|
||||||
|
extern input_type parser_input;
|
||||||
|
|
||||||
|
extern unsigned int lineno;
|
||||||
|
extern const char *lex_string;
|
||||||
|
|
||||||
|
/* In ldlex.l. */
|
||||||
|
extern int yylex (void);
|
||||||
|
extern void lex_push_file (FILE *, const char *, unsigned int);
|
||||||
|
extern void lex_redirect (const char *, const char *, unsigned int);
|
||||||
|
extern void ldlex_script (void);
|
||||||
|
extern void ldlex_mri_script (void);
|
||||||
|
extern void ldlex_version_script (void);
|
||||||
|
extern void ldlex_version_file (void);
|
||||||
|
extern void ldlex_defsym (void);
|
||||||
|
extern void ldlex_expression (void);
|
||||||
|
extern void ldlex_both (void);
|
||||||
|
extern void ldlex_command (void);
|
||||||
|
extern void ldlex_popstate (void);
|
||||||
|
extern const char* ldlex_filename (void);
|
||||||
|
|
||||||
|
/* In lexsup.c. */
|
||||||
|
extern int lex_input (void);
|
||||||
|
extern void lex_unput (int);
|
||||||
|
#ifndef yywrap
|
||||||
|
extern int yywrap (void);
|
||||||
|
#endif
|
||||||
|
extern void parse_args (unsigned, char **);
|
||||||
|
|
||||||
|
#endif
|
1480
contrib/toolchain/binutils/ld/ldmain.c
Normal file
1480
contrib/toolchain/binutils/ld/ldmain.c
Normal file
File diff suppressed because it is too large
Load Diff
62
contrib/toolchain/binutils/ld/ldmain.h
Normal file
62
contrib/toolchain/binutils/ld/ldmain.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/* ldmain.h -
|
||||||
|
Copyright 1991-2013 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#ifndef LDMAIN_H
|
||||||
|
#define LDMAIN_H
|
||||||
|
|
||||||
|
extern char *program_name;
|
||||||
|
extern const char *ld_sysroot;
|
||||||
|
extern char *ld_canon_sysroot;
|
||||||
|
extern int ld_canon_sysroot_len;
|
||||||
|
extern FILE *saved_script_handle;
|
||||||
|
extern FILE *previous_script_handle;
|
||||||
|
extern bfd_boolean force_make_executable;
|
||||||
|
extern char *default_target;
|
||||||
|
extern bfd_boolean trace_files;
|
||||||
|
extern bfd_boolean verbose;
|
||||||
|
extern bfd_boolean version_printed;
|
||||||
|
extern bfd_boolean demangling;
|
||||||
|
extern int g_switch_value;
|
||||||
|
extern const char *output_filename;
|
||||||
|
extern struct bfd_link_info link_info;
|
||||||
|
extern int overflow_cutoff_limit;
|
||||||
|
|
||||||
|
#define RELAXATION_DISABLED_BY_DEFAULT \
|
||||||
|
(link_info.disable_target_specific_optimizations < 0)
|
||||||
|
#define RELAXATION_DISABLED_BY_USER \
|
||||||
|
(link_info.disable_target_specific_optimizations > 1)
|
||||||
|
#define RELAXATION_ENABLED \
|
||||||
|
(link_info.disable_target_specific_optimizations == 0 \
|
||||||
|
|| link_info.disable_target_specific_optimizations == 1)
|
||||||
|
#define RELAXATION_ENABLED_BY_USER \
|
||||||
|
(link_info.disable_target_specific_optimizations == 0)
|
||||||
|
#define TARGET_ENABLE_RELAXATION \
|
||||||
|
do { link_info.disable_target_specific_optimizations = 1; } while (0)
|
||||||
|
#define DISABLE_RELAXATION \
|
||||||
|
do { link_info.disable_target_specific_optimizations = 2; } while (0)
|
||||||
|
#define ENABLE_RELAXATION \
|
||||||
|
do { link_info.disable_target_specific_optimizations = 0; } while (0)
|
||||||
|
|
||||||
|
extern void add_ysym (const char *);
|
||||||
|
extern void add_wrap (const char *);
|
||||||
|
extern void add_ignoresym (struct bfd_link_info *, const char *);
|
||||||
|
extern void add_keepsyms_file (const char *);
|
||||||
|
|
||||||
|
#endif
|
530
contrib/toolchain/binutils/ld/ldmisc.c
Normal file
530
contrib/toolchain/binutils/ld/ldmisc.c
Normal file
@ -0,0 +1,530 @@
|
|||||||
|
/* ldmisc.c
|
||||||
|
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||||
|
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011, 2012, 2013
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
Written by Steve Chamberlain of Cygnus Support.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#include "sysdep.h"
|
||||||
|
#include "bfd.h"
|
||||||
|
#include "bfdlink.h"
|
||||||
|
#include "libiberty.h"
|
||||||
|
#include "filenames.h"
|
||||||
|
#include "demangle.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "ld.h"
|
||||||
|
#include "ldmisc.h"
|
||||||
|
#include "ldexp.h"
|
||||||
|
#include "ldlang.h"
|
||||||
|
#include <ldgram.h>
|
||||||
|
#include "ldlex.h"
|
||||||
|
#include "ldmain.h"
|
||||||
|
#include "ldfile.h"
|
||||||
|
#include "elf-bfd.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
%% literal %
|
||||||
|
%A section name from a section
|
||||||
|
%B filename from a bfd
|
||||||
|
%C clever filename:linenumber with function
|
||||||
|
%D like %C, but no function name
|
||||||
|
%E current bfd error or errno
|
||||||
|
%F error is fatal
|
||||||
|
%G like %D, but only function name
|
||||||
|
%H like %C but in addition emit section+offset
|
||||||
|
%I filename from a lang_input_statement_type
|
||||||
|
%P print program name
|
||||||
|
%R info about a relent
|
||||||
|
%S print script file and linenumber from etree_type.
|
||||||
|
%T symbol name
|
||||||
|
%V hex bfd_vma
|
||||||
|
%W hex bfd_vma with 0x with no leading zeros taking up 8 spaces
|
||||||
|
%X no object output, fail return
|
||||||
|
%d integer, like printf
|
||||||
|
%ld long, like printf
|
||||||
|
%lu unsigned long, like printf
|
||||||
|
%p native (host) void* pointer, like printf
|
||||||
|
%s arbitrary string, like printf
|
||||||
|
%u integer, like printf
|
||||||
|
%v hex bfd_vma, no leading zeros
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
|
||||||
|
{
|
||||||
|
bfd_boolean fatal = FALSE;
|
||||||
|
|
||||||
|
while (*fmt != '\0')
|
||||||
|
{
|
||||||
|
const char *str = fmt;
|
||||||
|
while (*fmt != '%' && *fmt != '\0')
|
||||||
|
fmt++;
|
||||||
|
if (fmt != str)
|
||||||
|
if (fwrite (str, 1, fmt - str, fp))
|
||||||
|
{
|
||||||
|
/* Ignore. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*fmt == '%')
|
||||||
|
{
|
||||||
|
fmt++;
|
||||||
|
switch (*fmt++)
|
||||||
|
{
|
||||||
|
case '%':
|
||||||
|
/* literal % */
|
||||||
|
putc ('%', fp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'X':
|
||||||
|
/* no object output, fail return */
|
||||||
|
config.make_executable = FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'V':
|
||||||
|
/* hex bfd_vma */
|
||||||
|
{
|
||||||
|
bfd_vma value = va_arg (arg, bfd_vma);
|
||||||
|
fprintf_vma (fp, value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
/* hex bfd_vma, no leading zeros */
|
||||||
|
{
|
||||||
|
char buf[100];
|
||||||
|
char *p = buf;
|
||||||
|
bfd_vma value = va_arg (arg, bfd_vma);
|
||||||
|
sprintf_vma (p, value);
|
||||||
|
while (*p == '0')
|
||||||
|
p++;
|
||||||
|
if (!*p)
|
||||||
|
p--;
|
||||||
|
fputs (p, fp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'W':
|
||||||
|
/* hex bfd_vma with 0x with no leading zeroes taking up
|
||||||
|
8 spaces. */
|
||||||
|
{
|
||||||
|
char buf[100];
|
||||||
|
bfd_vma value;
|
||||||
|
char *p;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
value = va_arg (arg, bfd_vma);
|
||||||
|
sprintf_vma (buf, value);
|
||||||
|
for (p = buf; *p == '0'; ++p)
|
||||||
|
;
|
||||||
|
if (*p == '\0')
|
||||||
|
--p;
|
||||||
|
len = strlen (p);
|
||||||
|
while (len < 8)
|
||||||
|
{
|
||||||
|
putc (' ', fp);
|
||||||
|
++len;
|
||||||
|
}
|
||||||
|
fprintf (fp, "0x%s", p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'T':
|
||||||
|
/* Symbol name. */
|
||||||
|
{
|
||||||
|
const char *name = va_arg (arg, const char *);
|
||||||
|
|
||||||
|
if (name == NULL || *name == 0)
|
||||||
|
{
|
||||||
|
fprintf (fp, _("no symbol"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (demangling)
|
||||||
|
{
|
||||||
|
char *demangled;
|
||||||
|
|
||||||
|
demangled = bfd_demangle (link_info.output_bfd, name,
|
||||||
|
DMGL_ANSI | DMGL_PARAMS);
|
||||||
|
if (demangled != NULL)
|
||||||
|
{
|
||||||
|
fprintf (fp, "%s", demangled);
|
||||||
|
free (demangled);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf (fp, "%s", name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'A':
|
||||||
|
/* section name from a section */
|
||||||
|
{
|
||||||
|
asection *sec = va_arg (arg, asection *);
|
||||||
|
bfd *abfd = sec->owner;
|
||||||
|
const char *group = NULL;
|
||||||
|
struct coff_comdat_info *ci;
|
||||||
|
|
||||||
|
fprintf (fp, "%s", sec->name);
|
||||||
|
if (abfd != NULL
|
||||||
|
&& bfd_get_flavour (abfd) == bfd_target_elf_flavour
|
||||||
|
&& elf_next_in_group (sec) != NULL
|
||||||
|
&& (sec->flags & SEC_GROUP) == 0)
|
||||||
|
group = elf_group_name (sec);
|
||||||
|
else if (abfd != NULL
|
||||||
|
&& bfd_get_flavour (abfd) == bfd_target_coff_flavour
|
||||||
|
&& (ci = bfd_coff_get_comdat_section (sec->owner,
|
||||||
|
sec)) != NULL)
|
||||||
|
group = ci->name;
|
||||||
|
if (group != NULL)
|
||||||
|
fprintf (fp, "[%s]", group);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'B':
|
||||||
|
/* filename from a bfd */
|
||||||
|
{
|
||||||
|
bfd *abfd = va_arg (arg, bfd *);
|
||||||
|
|
||||||
|
if (abfd == NULL)
|
||||||
|
fprintf (fp, "%s generated", program_name);
|
||||||
|
else if (abfd->my_archive)
|
||||||
|
fprintf (fp, "%s(%s)", abfd->my_archive->filename,
|
||||||
|
abfd->filename);
|
||||||
|
else
|
||||||
|
fprintf (fp, "%s", abfd->filename);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'F':
|
||||||
|
/* Error is fatal. */
|
||||||
|
fatal = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'P':
|
||||||
|
/* Print program name. */
|
||||||
|
fprintf (fp, "%s", program_name);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'E':
|
||||||
|
/* current bfd error or errno */
|
||||||
|
fprintf (fp, "%s", bfd_errmsg (bfd_get_error ()));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'I':
|
||||||
|
/* filename from a lang_input_statement_type */
|
||||||
|
{
|
||||||
|
lang_input_statement_type *i;
|
||||||
|
|
||||||
|
i = va_arg (arg, lang_input_statement_type *);
|
||||||
|
if (bfd_my_archive (i->the_bfd) != NULL)
|
||||||
|
fprintf (fp, "(%s)",
|
||||||
|
bfd_get_filename (bfd_my_archive (i->the_bfd)));
|
||||||
|
fprintf (fp, "%s", i->local_sym_name);
|
||||||
|
if (bfd_my_archive (i->the_bfd) == NULL
|
||||||
|
&& filename_cmp (i->local_sym_name, i->filename) != 0)
|
||||||
|
fprintf (fp, " (%s)", i->filename);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'S':
|
||||||
|
/* Print script file and linenumber. */
|
||||||
|
{
|
||||||
|
etree_type node;
|
||||||
|
etree_type *tp = va_arg (arg, etree_type *);
|
||||||
|
|
||||||
|
if (tp == NULL)
|
||||||
|
{
|
||||||
|
tp = &node;
|
||||||
|
tp->type.filename = ldlex_filename ();
|
||||||
|
tp->type.lineno = lineno;
|
||||||
|
}
|
||||||
|
if (tp->type.filename != NULL)
|
||||||
|
fprintf (fp, "%s:%u", tp->type.filename, tp->type.lineno);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'R':
|
||||||
|
/* Print all that's interesting about a relent. */
|
||||||
|
{
|
||||||
|
arelent *relent = va_arg (arg, arelent *);
|
||||||
|
|
||||||
|
lfinfo (fp, "%s+0x%v (type %s)",
|
||||||
|
(*(relent->sym_ptr_ptr))->name,
|
||||||
|
relent->addend,
|
||||||
|
relent->howto->name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
case 'D':
|
||||||
|
case 'G':
|
||||||
|
case 'H':
|
||||||
|
/* Clever filename:linenumber with function name if possible.
|
||||||
|
The arguments are a BFD, a section, and an offset. */
|
||||||
|
{
|
||||||
|
static bfd *last_bfd;
|
||||||
|
static char *last_file = NULL;
|
||||||
|
static char *last_function = NULL;
|
||||||
|
bfd *abfd;
|
||||||
|
asection *section;
|
||||||
|
bfd_vma offset;
|
||||||
|
asymbol **asymbols = NULL;
|
||||||
|
const char *filename;
|
||||||
|
const char *functionname;
|
||||||
|
unsigned int linenumber;
|
||||||
|
bfd_boolean discard_last;
|
||||||
|
bfd_boolean done;
|
||||||
|
|
||||||
|
abfd = va_arg (arg, bfd *);
|
||||||
|
section = va_arg (arg, asection *);
|
||||||
|
offset = va_arg (arg, bfd_vma);
|
||||||
|
|
||||||
|
if (abfd != NULL)
|
||||||
|
{
|
||||||
|
if (!bfd_generic_link_read_symbols (abfd))
|
||||||
|
einfo (_("%B%F: could not read symbols: %E\n"), abfd);
|
||||||
|
|
||||||
|
asymbols = bfd_get_outsymbols (abfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The GNU Coding Standard requires that error messages
|
||||||
|
be of the form:
|
||||||
|
|
||||||
|
source-file-name:lineno: message
|
||||||
|
|
||||||
|
We do not always have a line number available so if
|
||||||
|
we cannot find them we print out the section name and
|
||||||
|
offset instead. */
|
||||||
|
discard_last = TRUE;
|
||||||
|
if (abfd != NULL
|
||||||
|
&& bfd_find_nearest_line (abfd, section, asymbols, offset,
|
||||||
|
&filename, &functionname,
|
||||||
|
&linenumber))
|
||||||
|
{
|
||||||
|
if (functionname != NULL
|
||||||
|
&& (fmt[-1] == 'C' || fmt[-1] == 'H'))
|
||||||
|
{
|
||||||
|
/* Detect the case where we are printing out a
|
||||||
|
message for the same function as the last
|
||||||
|
call to vinfo ("%C"). In this situation do
|
||||||
|
not print out the ABFD filename or the
|
||||||
|
function name again. Note - we do still
|
||||||
|
print out the source filename, as this will
|
||||||
|
allow programs that parse the linker's output
|
||||||
|
(eg emacs) to correctly locate multiple
|
||||||
|
errors in the same source file. */
|
||||||
|
if (last_bfd == NULL
|
||||||
|
|| last_file == NULL
|
||||||
|
|| last_function == NULL
|
||||||
|
|| last_bfd != abfd
|
||||||
|
|| (filename != NULL
|
||||||
|
&& filename_cmp (last_file, filename) != 0)
|
||||||
|
|| strcmp (last_function, functionname) != 0)
|
||||||
|
{
|
||||||
|
lfinfo (fp, _("%B: In function `%T':\n"),
|
||||||
|
abfd, functionname);
|
||||||
|
|
||||||
|
last_bfd = abfd;
|
||||||
|
if (last_file != NULL)
|
||||||
|
free (last_file);
|
||||||
|
last_file = NULL;
|
||||||
|
if (filename)
|
||||||
|
last_file = xstrdup (filename);
|
||||||
|
if (last_function != NULL)
|
||||||
|
free (last_function);
|
||||||
|
last_function = xstrdup (functionname);
|
||||||
|
}
|
||||||
|
discard_last = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
lfinfo (fp, "%B:", abfd);
|
||||||
|
|
||||||
|
if (filename != NULL)
|
||||||
|
fprintf (fp, "%s:", filename);
|
||||||
|
|
||||||
|
done = fmt[-1] != 'H';
|
||||||
|
if (functionname != NULL && fmt[-1] == 'G')
|
||||||
|
lfinfo (fp, "%T", functionname);
|
||||||
|
else if (filename != NULL && linenumber != 0)
|
||||||
|
fprintf (fp, "%u%s", linenumber, done ? "" : ":");
|
||||||
|
else
|
||||||
|
done = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lfinfo (fp, "%B:", abfd);
|
||||||
|
done = FALSE;
|
||||||
|
}
|
||||||
|
if (!done)
|
||||||
|
lfinfo (fp, "(%A+0x%v)", section, offset);
|
||||||
|
|
||||||
|
if (discard_last)
|
||||||
|
{
|
||||||
|
last_bfd = NULL;
|
||||||
|
if (last_file != NULL)
|
||||||
|
{
|
||||||
|
free (last_file);
|
||||||
|
last_file = NULL;
|
||||||
|
}
|
||||||
|
if (last_function != NULL)
|
||||||
|
{
|
||||||
|
free (last_function);
|
||||||
|
last_function = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
/* native (host) void* pointer, like printf */
|
||||||
|
fprintf (fp, "%p", va_arg (arg, void *));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
/* arbitrary string, like printf */
|
||||||
|
fprintf (fp, "%s", va_arg (arg, char *));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
/* integer, like printf */
|
||||||
|
fprintf (fp, "%d", va_arg (arg, int));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
/* unsigned integer, like printf */
|
||||||
|
fprintf (fp, "%u", va_arg (arg, unsigned int));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'l':
|
||||||
|
if (*fmt == 'd')
|
||||||
|
{
|
||||||
|
fprintf (fp, "%ld", va_arg (arg, long));
|
||||||
|
++fmt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (*fmt == 'u')
|
||||||
|
{
|
||||||
|
fprintf (fp, "%lu", va_arg (arg, unsigned long));
|
||||||
|
++fmt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Fall thru */
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf (fp, "%%%c", fmt[-1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_warning && config.fatal_warnings)
|
||||||
|
config.make_executable = FALSE;
|
||||||
|
|
||||||
|
if (fatal)
|
||||||
|
xexit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Format info message and print on stdout. */
|
||||||
|
|
||||||
|
/* (You would think this should be called just "info", but then you
|
||||||
|
would be hosed by LynxOS, which defines that name in its libc.) */
|
||||||
|
|
||||||
|
void
|
||||||
|
info_msg (const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list arg;
|
||||||
|
|
||||||
|
va_start (arg, fmt);
|
||||||
|
vfinfo (stdout, fmt, arg, FALSE);
|
||||||
|
va_end (arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ('e' for error.) Format info message and print on stderr. */
|
||||||
|
|
||||||
|
void
|
||||||
|
einfo (const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list arg;
|
||||||
|
|
||||||
|
fflush (stdout);
|
||||||
|
va_start (arg, fmt);
|
||||||
|
vfinfo (stderr, fmt, arg, TRUE);
|
||||||
|
va_end (arg);
|
||||||
|
fflush (stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
info_assert (const char *file, unsigned int line)
|
||||||
|
{
|
||||||
|
einfo (_("%F%P: internal error %s %d\n"), file, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ('m' for map) Format info message and print on map. */
|
||||||
|
|
||||||
|
void
|
||||||
|
minfo (const char *fmt, ...)
|
||||||
|
{
|
||||||
|
if (config.map_file != NULL)
|
||||||
|
{
|
||||||
|
va_list arg;
|
||||||
|
|
||||||
|
va_start (arg, fmt);
|
||||||
|
vfinfo (config.map_file, fmt, arg, FALSE);
|
||||||
|
va_end (arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
lfinfo (FILE *file, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list arg;
|
||||||
|
|
||||||
|
va_start (arg, fmt);
|
||||||
|
vfinfo (file, fmt, arg, FALSE);
|
||||||
|
va_end (arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Functions to print the link map. */
|
||||||
|
|
||||||
|
void
|
||||||
|
print_space (void)
|
||||||
|
{
|
||||||
|
fprintf (config.map_file, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_nl (void)
|
||||||
|
{
|
||||||
|
fprintf (config.map_file, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A more or less friendly abort message. In ld.h abort is defined to
|
||||||
|
call this function. */
|
||||||
|
|
||||||
|
void
|
||||||
|
ld_abort (const char *file, int line, const char *fn)
|
||||||
|
{
|
||||||
|
if (fn != NULL)
|
||||||
|
einfo (_("%P: internal error: aborting at %s line %d in %s\n"),
|
||||||
|
file, line, fn);
|
||||||
|
else
|
||||||
|
einfo (_("%P: internal error: aborting at %s line %d\n"),
|
||||||
|
file, line);
|
||||||
|
einfo (_("%P%F: please report this bug\n"));
|
||||||
|
xexit (1);
|
||||||
|
}
|
45
contrib/toolchain/binutils/ld/ldmisc.h
Normal file
45
contrib/toolchain/binutils/ld/ldmisc.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/* ldmisc.h -
|
||||||
|
Copyright 1991, 1992, 1993, 1994, 1996, 1997, 2001, 2003, 2004, 2005, 2007
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#ifndef LDMISC_H
|
||||||
|
#define LDMISC_H
|
||||||
|
|
||||||
|
extern void vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning);
|
||||||
|
extern void einfo (const char *, ...);
|
||||||
|
extern void minfo (const char *, ...);
|
||||||
|
extern void info_msg (const char *, ...);
|
||||||
|
extern void lfinfo (FILE *, const char *, ...);
|
||||||
|
extern void info_assert (const char *, unsigned int);
|
||||||
|
extern void yyerror (const char *);
|
||||||
|
extern void *xmalloc (size_t);
|
||||||
|
extern void *xrealloc (void *, size_t);
|
||||||
|
extern void xexit (int);
|
||||||
|
|
||||||
|
#define ASSERT(x) \
|
||||||
|
do { if (!(x)) info_assert(__FILE__,__LINE__); } while (0)
|
||||||
|
|
||||||
|
#define FAIL() \
|
||||||
|
do { info_assert(__FILE__,__LINE__); } while (0)
|
||||||
|
|
||||||
|
extern void print_space (void);
|
||||||
|
extern void print_nl (void);
|
||||||
|
|
||||||
|
#endif
|
61
contrib/toolchain/binutils/ld/ldver.c
Normal file
61
contrib/toolchain/binutils/ld/ldver.c
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/* ldver.c -- Print linker version.
|
||||||
|
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000, 2001, 2002,
|
||||||
|
2003, 2005, 2007, 2008, 2009, 2010, 2011, 2012, 2013
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#include "sysdep.h"
|
||||||
|
#include "bfd.h"
|
||||||
|
#include "bfdver.h"
|
||||||
|
|
||||||
|
#include "ld.h"
|
||||||
|
#include "ldver.h"
|
||||||
|
#include "ldexp.h"
|
||||||
|
#include "ldlang.h"
|
||||||
|
#include "ldfile.h"
|
||||||
|
#include "ldemul.h"
|
||||||
|
#include "ldmain.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
ldversion (int noisy)
|
||||||
|
{
|
||||||
|
/* Output for noisy == 2 is intended to follow the GNU standards. */
|
||||||
|
fprintf (stdout, _("GNU ld %s\n"), BFD_VERSION_STRING);
|
||||||
|
|
||||||
|
if (noisy & 2)
|
||||||
|
{
|
||||||
|
printf (_("Copyright 2013 Free Software Foundation, Inc.\n"));
|
||||||
|
printf (_("\
|
||||||
|
This program is free software; you may redistribute it under the terms of\n\
|
||||||
|
the GNU General Public License version 3 or (at your option) a later version.\n\
|
||||||
|
This program has absolutely no warranty.\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (noisy & 1)
|
||||||
|
{
|
||||||
|
ld_emulation_xfer_type **ptr = ld_emulations;
|
||||||
|
|
||||||
|
printf (_(" Supported emulations:\n"));
|
||||||
|
while (*ptr)
|
||||||
|
{
|
||||||
|
printf (" %s\n", (*ptr)->emulation_name);
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
contrib/toolchain/binutils/ld/ldver.h
Normal file
22
contrib/toolchain/binutils/ld/ldver.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/* ldver.h -- Header file for ldver.c.
|
||||||
|
Copyright 1991, 1992, 1993, 1996, 2001, 2003, 2005, 2007
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
void ldversion (int);
|
593
contrib/toolchain/binutils/ld/ldwrite.c
Normal file
593
contrib/toolchain/binutils/ld/ldwrite.c
Normal file
@ -0,0 +1,593 @@
|
|||||||
|
/* ldwrite.c -- write out the linked file
|
||||||
|
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002,
|
||||||
|
2003, 2004, 2005, 2006, 2007, 2008, 2010, 2012
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
Written by Steve Chamberlain sac@cygnus.com
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#include "sysdep.h"
|
||||||
|
#include "bfd.h"
|
||||||
|
#include "bfdlink.h"
|
||||||
|
#include "libiberty.h"
|
||||||
|
#include "safe-ctype.h"
|
||||||
|
|
||||||
|
#include "ld.h"
|
||||||
|
#include "ldexp.h"
|
||||||
|
#include "ldlang.h"
|
||||||
|
#include "ldwrite.h"
|
||||||
|
#include "ldmisc.h"
|
||||||
|
#include <ldgram.h>
|
||||||
|
#include "ldmain.h"
|
||||||
|
|
||||||
|
/* Build link_order structures for the BFD linker. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
build_link_order (lang_statement_union_type *statement)
|
||||||
|
{
|
||||||
|
switch (statement->header.type)
|
||||||
|
{
|
||||||
|
case lang_data_statement_enum:
|
||||||
|
{
|
||||||
|
asection *output_section;
|
||||||
|
struct bfd_link_order *link_order;
|
||||||
|
bfd_vma value;
|
||||||
|
bfd_boolean big_endian = FALSE;
|
||||||
|
|
||||||
|
output_section = statement->data_statement.output_section;
|
||||||
|
ASSERT (output_section->owner == link_info.output_bfd);
|
||||||
|
|
||||||
|
if (!((output_section->flags & SEC_HAS_CONTENTS) != 0
|
||||||
|
|| ((output_section->flags & SEC_LOAD) != 0
|
||||||
|
&& (output_section->flags & SEC_THREAD_LOCAL))))
|
||||||
|
break;
|
||||||
|
|
||||||
|
link_order = bfd_new_link_order (link_info.output_bfd, output_section);
|
||||||
|
if (link_order == NULL)
|
||||||
|
einfo (_("%P%F: bfd_new_link_order failed\n"));
|
||||||
|
|
||||||
|
link_order->type = bfd_data_link_order;
|
||||||
|
link_order->offset = statement->data_statement.output_offset;
|
||||||
|
link_order->u.data.contents = (bfd_byte *) xmalloc (QUAD_SIZE);
|
||||||
|
|
||||||
|
value = statement->data_statement.value;
|
||||||
|
|
||||||
|
/* If the endianness of the output BFD is not known, then we
|
||||||
|
base the endianness of the data on the first input file.
|
||||||
|
By convention, the bfd_put routines for an unknown
|
||||||
|
endianness are big endian, so we must swap here if the
|
||||||
|
input file is little endian. */
|
||||||
|
if (bfd_big_endian (link_info.output_bfd))
|
||||||
|
big_endian = TRUE;
|
||||||
|
else if (bfd_little_endian (link_info.output_bfd))
|
||||||
|
big_endian = FALSE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bfd_boolean swap;
|
||||||
|
|
||||||
|
swap = FALSE;
|
||||||
|
if (command_line.endian == ENDIAN_BIG)
|
||||||
|
big_endian = TRUE;
|
||||||
|
else if (command_line.endian == ENDIAN_LITTLE)
|
||||||
|
{
|
||||||
|
big_endian = FALSE;
|
||||||
|
swap = TRUE;
|
||||||
|
}
|
||||||
|
else if (command_line.endian == ENDIAN_UNSET)
|
||||||
|
{
|
||||||
|
big_endian = TRUE;
|
||||||
|
{
|
||||||
|
LANG_FOR_EACH_INPUT_STATEMENT (s)
|
||||||
|
{
|
||||||
|
if (s->the_bfd != NULL)
|
||||||
|
{
|
||||||
|
if (bfd_little_endian (s->the_bfd))
|
||||||
|
{
|
||||||
|
big_endian = FALSE;
|
||||||
|
swap = TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (swap)
|
||||||
|
{
|
||||||
|
bfd_byte buffer[8];
|
||||||
|
|
||||||
|
switch (statement->data_statement.type)
|
||||||
|
{
|
||||||
|
case QUAD:
|
||||||
|
case SQUAD:
|
||||||
|
if (sizeof (bfd_vma) >= QUAD_SIZE)
|
||||||
|
{
|
||||||
|
bfd_putl64 (value, buffer);
|
||||||
|
value = bfd_getb64 (buffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Fall through. */
|
||||||
|
case LONG:
|
||||||
|
bfd_putl32 (value, buffer);
|
||||||
|
value = bfd_getb32 (buffer);
|
||||||
|
break;
|
||||||
|
case SHORT:
|
||||||
|
bfd_putl16 (value, buffer);
|
||||||
|
value = bfd_getb16 (buffer);
|
||||||
|
break;
|
||||||
|
case BYTE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT (output_section->owner == link_info.output_bfd);
|
||||||
|
switch (statement->data_statement.type)
|
||||||
|
{
|
||||||
|
case QUAD:
|
||||||
|
case SQUAD:
|
||||||
|
if (sizeof (bfd_vma) >= QUAD_SIZE)
|
||||||
|
bfd_put_64 (link_info.output_bfd, value,
|
||||||
|
link_order->u.data.contents);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bfd_vma high;
|
||||||
|
|
||||||
|
if (statement->data_statement.type == QUAD)
|
||||||
|
high = 0;
|
||||||
|
else if ((value & 0x80000000) == 0)
|
||||||
|
high = 0;
|
||||||
|
else
|
||||||
|
high = (bfd_vma) -1;
|
||||||
|
bfd_put_32 (link_info.output_bfd, high,
|
||||||
|
(link_order->u.data.contents
|
||||||
|
+ (big_endian ? 0 : 4)));
|
||||||
|
bfd_put_32 (link_info.output_bfd, value,
|
||||||
|
(link_order->u.data.contents
|
||||||
|
+ (big_endian ? 4 : 0)));
|
||||||
|
}
|
||||||
|
link_order->size = QUAD_SIZE;
|
||||||
|
break;
|
||||||
|
case LONG:
|
||||||
|
bfd_put_32 (link_info.output_bfd, value,
|
||||||
|
link_order->u.data.contents);
|
||||||
|
link_order->size = LONG_SIZE;
|
||||||
|
break;
|
||||||
|
case SHORT:
|
||||||
|
bfd_put_16 (link_info.output_bfd, value,
|
||||||
|
link_order->u.data.contents);
|
||||||
|
link_order->size = SHORT_SIZE;
|
||||||
|
break;
|
||||||
|
case BYTE:
|
||||||
|
bfd_put_8 (link_info.output_bfd, value,
|
||||||
|
link_order->u.data.contents);
|
||||||
|
link_order->size = BYTE_SIZE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
link_order->u.data.size = link_order->size;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case lang_reloc_statement_enum:
|
||||||
|
{
|
||||||
|
lang_reloc_statement_type *rs;
|
||||||
|
asection *output_section;
|
||||||
|
struct bfd_link_order *link_order;
|
||||||
|
|
||||||
|
rs = &statement->reloc_statement;
|
||||||
|
|
||||||
|
output_section = rs->output_section;
|
||||||
|
ASSERT (output_section->owner == link_info.output_bfd);
|
||||||
|
|
||||||
|
if (!((output_section->flags & SEC_HAS_CONTENTS) != 0
|
||||||
|
|| ((output_section->flags & SEC_LOAD) != 0
|
||||||
|
&& (output_section->flags & SEC_THREAD_LOCAL))))
|
||||||
|
break;
|
||||||
|
|
||||||
|
link_order = bfd_new_link_order (link_info.output_bfd, output_section);
|
||||||
|
if (link_order == NULL)
|
||||||
|
einfo (_("%P%F: bfd_new_link_order failed\n"));
|
||||||
|
|
||||||
|
link_order->offset = rs->output_offset;
|
||||||
|
link_order->size = bfd_get_reloc_size (rs->howto);
|
||||||
|
|
||||||
|
link_order->u.reloc.p = (struct bfd_link_order_reloc *)
|
||||||
|
xmalloc (sizeof (struct bfd_link_order_reloc));
|
||||||
|
|
||||||
|
link_order->u.reloc.p->reloc = rs->reloc;
|
||||||
|
link_order->u.reloc.p->addend = rs->addend_value;
|
||||||
|
|
||||||
|
if (rs->name == NULL)
|
||||||
|
{
|
||||||
|
link_order->type = bfd_section_reloc_link_order;
|
||||||
|
if (rs->section->owner == link_info.output_bfd)
|
||||||
|
link_order->u.reloc.p->u.section = rs->section;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
link_order->u.reloc.p->u.section = rs->section->output_section;
|
||||||
|
link_order->u.reloc.p->addend += rs->section->output_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
link_order->type = bfd_symbol_reloc_link_order;
|
||||||
|
link_order->u.reloc.p->u.name = rs->name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case lang_input_section_enum:
|
||||||
|
{
|
||||||
|
/* Create a new link_order in the output section with this
|
||||||
|
attached */
|
||||||
|
asection *i = statement->input_section.section;
|
||||||
|
|
||||||
|
if (i->sec_info_type != SEC_INFO_TYPE_JUST_SYMS
|
||||||
|
&& (i->flags & SEC_EXCLUDE) == 0)
|
||||||
|
{
|
||||||
|
asection *output_section = i->output_section;
|
||||||
|
struct bfd_link_order *link_order;
|
||||||
|
|
||||||
|
ASSERT (output_section->owner == link_info.output_bfd);
|
||||||
|
|
||||||
|
if (!((output_section->flags & SEC_HAS_CONTENTS) != 0
|
||||||
|
|| ((output_section->flags & SEC_LOAD) != 0
|
||||||
|
&& (output_section->flags & SEC_THREAD_LOCAL))))
|
||||||
|
break;
|
||||||
|
|
||||||
|
link_order = bfd_new_link_order (link_info.output_bfd,
|
||||||
|
output_section);
|
||||||
|
|
||||||
|
if ((i->flags & SEC_NEVER_LOAD) != 0
|
||||||
|
&& (i->flags & SEC_DEBUGGING) == 0)
|
||||||
|
{
|
||||||
|
/* We've got a never load section inside one which is
|
||||||
|
going to be output, we'll change it into a fill. */
|
||||||
|
link_order->type = bfd_data_link_order;
|
||||||
|
link_order->u.data.contents = (unsigned char *) "";
|
||||||
|
link_order->u.data.size = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
link_order->type = bfd_indirect_link_order;
|
||||||
|
link_order->u.indirect.section = i;
|
||||||
|
ASSERT (i->output_section == output_section);
|
||||||
|
}
|
||||||
|
link_order->size = i->size;
|
||||||
|
link_order->offset = i->output_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case lang_padding_statement_enum:
|
||||||
|
/* Make a new link_order with the right filler */
|
||||||
|
{
|
||||||
|
asection *output_section;
|
||||||
|
struct bfd_link_order *link_order;
|
||||||
|
|
||||||
|
output_section = statement->padding_statement.output_section;
|
||||||
|
ASSERT (statement->padding_statement.output_section->owner
|
||||||
|
== link_info.output_bfd);
|
||||||
|
|
||||||
|
if (!((output_section->flags & SEC_HAS_CONTENTS) != 0
|
||||||
|
|| ((output_section->flags & SEC_LOAD) != 0
|
||||||
|
&& (output_section->flags & SEC_THREAD_LOCAL))))
|
||||||
|
break;
|
||||||
|
|
||||||
|
link_order = bfd_new_link_order (link_info.output_bfd,
|
||||||
|
output_section);
|
||||||
|
link_order->type = bfd_data_link_order;
|
||||||
|
link_order->size = statement->padding_statement.size;
|
||||||
|
link_order->offset = statement->padding_statement.output_offset;
|
||||||
|
link_order->u.data.contents = statement->padding_statement.fill->data;
|
||||||
|
link_order->u.data.size = statement->padding_statement.fill->size;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* All the other ones fall through */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return true if NAME is the name of an unsplittable section. These
|
||||||
|
are the stabs strings, dwarf strings. */
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
unsplittable_name (const char *name)
|
||||||
|
{
|
||||||
|
if (CONST_STRNEQ (name, ".stab"))
|
||||||
|
{
|
||||||
|
/* There are several stab like string sections. We pattern match on
|
||||||
|
".stab...str" */
|
||||||
|
unsigned len = strlen (name);
|
||||||
|
if (strcmp (&name[len-3], "str") == 0)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else if (strcmp (name, "$GDB_STRINGS$") == 0)
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wander around the input sections, make sure that
|
||||||
|
we'll never try and create an output section with more relocs
|
||||||
|
than will fit.. Do this by always assuming the worst case, and
|
||||||
|
creating new output sections with all the right bits. */
|
||||||
|
#define TESTIT 1
|
||||||
|
static asection *
|
||||||
|
clone_section (bfd *abfd, asection *s, const char *name, int *count)
|
||||||
|
{
|
||||||
|
char *tname;
|
||||||
|
char *sname;
|
||||||
|
unsigned int len;
|
||||||
|
asection *n;
|
||||||
|
struct bfd_link_hash_entry *h;
|
||||||
|
|
||||||
|
/* Invent a section name from the section name and a dotted numeric
|
||||||
|
suffix. */
|
||||||
|
len = strlen (name);
|
||||||
|
tname = (char *) xmalloc (len + 1);
|
||||||
|
memcpy (tname, name, len + 1);
|
||||||
|
/* Remove a dotted number suffix, from a previous split link. */
|
||||||
|
while (len && ISDIGIT (tname[len-1]))
|
||||||
|
len--;
|
||||||
|
if (len > 1 && tname[len-1] == '.')
|
||||||
|
/* It was a dotted number. */
|
||||||
|
tname[len-1] = 0;
|
||||||
|
|
||||||
|
/* We want to use the whole of the original section name for the
|
||||||
|
split name, but coff can be restricted to 8 character names. */
|
||||||
|
if (bfd_family_coff (abfd) && strlen (tname) > 5)
|
||||||
|
{
|
||||||
|
/* Some section names cannot be truncated, as the name is
|
||||||
|
used to locate some other section. */
|
||||||
|
if (CONST_STRNEQ (name, ".stab")
|
||||||
|
|| strcmp (name, "$GDB_SYMBOLS$") == 0)
|
||||||
|
{
|
||||||
|
einfo (_ ("%F%P: cannot create split section name for %s\n"), name);
|
||||||
|
/* Silence gcc warnings. einfo exits, so we never reach here. */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
tname[5] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sname = bfd_get_unique_section_name (abfd, tname, count)) == NULL
|
||||||
|
|| (n = bfd_make_section_anyway (abfd, sname)) == NULL
|
||||||
|
|| (h = bfd_link_hash_lookup (link_info.hash,
|
||||||
|
sname, TRUE, TRUE, FALSE)) == NULL)
|
||||||
|
{
|
||||||
|
einfo (_("%F%P: clone section failed: %E\n"));
|
||||||
|
/* Silence gcc warnings. einfo exits, so we never reach here. */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
free (tname);
|
||||||
|
|
||||||
|
/* Set up section symbol. */
|
||||||
|
h->type = bfd_link_hash_defined;
|
||||||
|
h->u.def.value = 0;
|
||||||
|
h->u.def.section = n;
|
||||||
|
|
||||||
|
n->flags = s->flags;
|
||||||
|
n->vma = s->vma;
|
||||||
|
n->user_set_vma = s->user_set_vma;
|
||||||
|
n->lma = s->lma;
|
||||||
|
n->size = 0;
|
||||||
|
n->output_offset = s->output_offset;
|
||||||
|
n->output_section = n;
|
||||||
|
n->orelocation = 0;
|
||||||
|
n->reloc_count = 0;
|
||||||
|
n->alignment_power = s->alignment_power;
|
||||||
|
|
||||||
|
bfd_copy_private_section_data (abfd, s, abfd, n);
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if TESTING
|
||||||
|
static void
|
||||||
|
ds (asection *s)
|
||||||
|
{
|
||||||
|
struct bfd_link_order *l = s->map_head.link_order;
|
||||||
|
printf ("vma %x size %x\n", s->vma, s->size);
|
||||||
|
while (l)
|
||||||
|
{
|
||||||
|
if (l->type == bfd_indirect_link_order)
|
||||||
|
{
|
||||||
|
printf ("%8x %s\n", l->offset, l->u.indirect.section->owner->filename);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf (_("%8x something else\n"), l->offset);
|
||||||
|
}
|
||||||
|
l = l->next;
|
||||||
|
}
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
dump (char *s, asection *a1, asection *a2)
|
||||||
|
{
|
||||||
|
printf ("%s\n", s);
|
||||||
|
ds (a1);
|
||||||
|
ds (a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sanity_check (bfd *abfd)
|
||||||
|
{
|
||||||
|
asection *s;
|
||||||
|
for (s = abfd->sections; s; s = s->next)
|
||||||
|
{
|
||||||
|
struct bfd_link_order *p;
|
||||||
|
bfd_vma prev = 0;
|
||||||
|
for (p = s->map_head.link_order; p; p = p->next)
|
||||||
|
{
|
||||||
|
if (p->offset > 100000)
|
||||||
|
abort ();
|
||||||
|
if (p->offset < prev)
|
||||||
|
abort ();
|
||||||
|
prev = p->offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define sanity_check(a)
|
||||||
|
#define dump(a, b, c)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
split_sections (bfd *abfd, struct bfd_link_info *info)
|
||||||
|
{
|
||||||
|
asection *original_sec;
|
||||||
|
int nsecs = abfd->section_count;
|
||||||
|
sanity_check (abfd);
|
||||||
|
/* Look through all the original sections. */
|
||||||
|
for (original_sec = abfd->sections;
|
||||||
|
original_sec && nsecs;
|
||||||
|
original_sec = original_sec->next, nsecs--)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
unsigned int lines = 0;
|
||||||
|
unsigned int relocs = 0;
|
||||||
|
bfd_size_type sec_size = 0;
|
||||||
|
struct bfd_link_order *l;
|
||||||
|
struct bfd_link_order *p;
|
||||||
|
bfd_vma vma = original_sec->vma;
|
||||||
|
asection *cursor = original_sec;
|
||||||
|
|
||||||
|
/* Count up the relocations and line entries to see if anything
|
||||||
|
would be too big to fit. Accumulate section size too. */
|
||||||
|
for (l = NULL, p = cursor->map_head.link_order; p != NULL; p = l->next)
|
||||||
|
{
|
||||||
|
unsigned int thislines = 0;
|
||||||
|
unsigned int thisrelocs = 0;
|
||||||
|
bfd_size_type thissize = 0;
|
||||||
|
if (p->type == bfd_indirect_link_order)
|
||||||
|
{
|
||||||
|
asection *sec;
|
||||||
|
|
||||||
|
sec = p->u.indirect.section;
|
||||||
|
|
||||||
|
if (info->strip == strip_none
|
||||||
|
|| info->strip == strip_some)
|
||||||
|
thislines = sec->lineno_count;
|
||||||
|
|
||||||
|
if (info->relocatable)
|
||||||
|
thisrelocs = sec->reloc_count;
|
||||||
|
|
||||||
|
thissize = sec->size;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (info->relocatable
|
||||||
|
&& (p->type == bfd_section_reloc_link_order
|
||||||
|
|| p->type == bfd_symbol_reloc_link_order))
|
||||||
|
thisrelocs++;
|
||||||
|
|
||||||
|
if (l != NULL
|
||||||
|
&& (thisrelocs + relocs >= config.split_by_reloc
|
||||||
|
|| thislines + lines >= config.split_by_reloc
|
||||||
|
|| (thissize + sec_size >= config.split_by_file))
|
||||||
|
&& !unsplittable_name (cursor->name))
|
||||||
|
{
|
||||||
|
/* Create a new section and put this link order and the
|
||||||
|
following link orders into it. */
|
||||||
|
bfd_vma shift_offset;
|
||||||
|
asection *n;
|
||||||
|
|
||||||
|
n = clone_section (abfd, cursor, original_sec->name, &count);
|
||||||
|
|
||||||
|
/* Attach the link orders to the new section and snip
|
||||||
|
them off from the old section. */
|
||||||
|
n->map_head.link_order = p;
|
||||||
|
n->map_tail.link_order = cursor->map_tail.link_order;
|
||||||
|
cursor->map_tail.link_order = l;
|
||||||
|
l->next = NULL;
|
||||||
|
l = p;
|
||||||
|
|
||||||
|
/* Change the size of the original section and
|
||||||
|
update the vma of the new one. */
|
||||||
|
|
||||||
|
dump ("before snip", cursor, n);
|
||||||
|
|
||||||
|
shift_offset = p->offset;
|
||||||
|
n->size = cursor->size - shift_offset;
|
||||||
|
cursor->size = shift_offset;
|
||||||
|
|
||||||
|
vma += shift_offset;
|
||||||
|
n->lma = n->vma = vma;
|
||||||
|
|
||||||
|
/* Run down the chain and change the output section to
|
||||||
|
the right one, update the offsets too. */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p->offset -= shift_offset;
|
||||||
|
if (p->type == bfd_indirect_link_order)
|
||||||
|
{
|
||||||
|
p->u.indirect.section->output_section = n;
|
||||||
|
p->u.indirect.section->output_offset = p->offset;
|
||||||
|
}
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
while (p);
|
||||||
|
|
||||||
|
dump ("after snip", cursor, n);
|
||||||
|
cursor = n;
|
||||||
|
relocs = thisrelocs;
|
||||||
|
lines = thislines;
|
||||||
|
sec_size = thissize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
l = p;
|
||||||
|
relocs += thisrelocs;
|
||||||
|
lines += thislines;
|
||||||
|
sec_size += thissize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sanity_check (abfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call BFD to write out the linked file. */
|
||||||
|
|
||||||
|
void
|
||||||
|
ldwrite (void)
|
||||||
|
{
|
||||||
|
/* Reset error indicator, which can typically something like invalid
|
||||||
|
format from opening up the .o files. */
|
||||||
|
bfd_set_error (bfd_error_no_error);
|
||||||
|
lang_for_each_statement (build_link_order);
|
||||||
|
|
||||||
|
if (config.split_by_reloc != (unsigned) -1
|
||||||
|
|| config.split_by_file != (bfd_size_type) -1)
|
||||||
|
split_sections (link_info.output_bfd, &link_info);
|
||||||
|
if (!bfd_final_link (link_info.output_bfd, &link_info))
|
||||||
|
{
|
||||||
|
/* If there was an error recorded, print it out. Otherwise assume
|
||||||
|
an appropriate error message like unknown symbol was printed
|
||||||
|
out. */
|
||||||
|
|
||||||
|
if (bfd_get_error () != bfd_error_no_error)
|
||||||
|
einfo (_("%F%P: final link failed: %E\n"));
|
||||||
|
else
|
||||||
|
xexit (1);
|
||||||
|
}
|
||||||
|
}
|
21
contrib/toolchain/binutils/ld/ldwrite.h
Normal file
21
contrib/toolchain/binutils/ld/ldwrite.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/* ldwrite.h -
|
||||||
|
Copyright 1991, 1992, 1993, 2003, 2005, 2007 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
extern void ldwrite (void);
|
1718
contrib/toolchain/binutils/ld/lexsup.c
Normal file
1718
contrib/toolchain/binutils/ld/lexsup.c
Normal file
File diff suppressed because it is too large
Load Diff
319
contrib/toolchain/binutils/ld/mri.c
Normal file
319
contrib/toolchain/binutils/ld/mri.c
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
/* mri.c -- handle MRI style linker scripts
|
||||||
|
Copyright 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||||
|
2002, 2003, 2004, 2005, 2007, 2011 Free Software Foundation, Inc.
|
||||||
|
Contributed by Steve Chamberlain <sac@cygnus.com>.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
|
||||||
|
/* This bit does the tree decoration when MRI style link scripts
|
||||||
|
are parsed. */
|
||||||
|
|
||||||
|
#include "sysdep.h"
|
||||||
|
#include "bfd.h"
|
||||||
|
#include "ld.h"
|
||||||
|
#include "ldexp.h"
|
||||||
|
#include "ldlang.h"
|
||||||
|
#include "ldmisc.h"
|
||||||
|
#include "mri.h"
|
||||||
|
#include <ldgram.h>
|
||||||
|
#include "libiberty.h"
|
||||||
|
|
||||||
|
struct section_name_struct {
|
||||||
|
struct section_name_struct *next;
|
||||||
|
const char *name;
|
||||||
|
const char *alias;
|
||||||
|
etree_type *vma;
|
||||||
|
etree_type *align;
|
||||||
|
etree_type *subalign;
|
||||||
|
int ok_to_load;
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned int symbol_truncate = 10000;
|
||||||
|
static struct section_name_struct *order;
|
||||||
|
static struct section_name_struct *only_load;
|
||||||
|
static struct section_name_struct *address;
|
||||||
|
static struct section_name_struct *alias;
|
||||||
|
|
||||||
|
static struct section_name_struct *alignment;
|
||||||
|
static struct section_name_struct *subalignment;
|
||||||
|
|
||||||
|
static struct section_name_struct **
|
||||||
|
lookup (const char *name, struct section_name_struct **list)
|
||||||
|
{
|
||||||
|
struct section_name_struct **ptr = list;
|
||||||
|
|
||||||
|
while (*ptr)
|
||||||
|
{
|
||||||
|
if (strcmp (name, (*ptr)->name) == 0)
|
||||||
|
/* If this is a match, delete it, we only keep the last instance
|
||||||
|
of any name. */
|
||||||
|
*ptr = (*ptr)->next;
|
||||||
|
else
|
||||||
|
ptr = &((*ptr)->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
*ptr = (struct section_name_struct *)
|
||||||
|
xmalloc (sizeof (struct section_name_struct));
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mri_add_to_list (struct section_name_struct **list,
|
||||||
|
const char *name,
|
||||||
|
etree_type *vma,
|
||||||
|
const char *zalias,
|
||||||
|
etree_type *align,
|
||||||
|
etree_type *subalign)
|
||||||
|
{
|
||||||
|
struct section_name_struct **ptr = lookup (name, list);
|
||||||
|
|
||||||
|
(*ptr)->name = name;
|
||||||
|
(*ptr)->vma = vma;
|
||||||
|
(*ptr)->next = NULL;
|
||||||
|
(*ptr)->ok_to_load = 0;
|
||||||
|
(*ptr)->alias = zalias;
|
||||||
|
(*ptr)->align = align;
|
||||||
|
(*ptr)->subalign = subalign;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mri_output_section (const char *name, etree_type *vma)
|
||||||
|
{
|
||||||
|
mri_add_to_list (&address, name, vma, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If any ABSOLUTE <name> are in the script, only load those files
|
||||||
|
marked thus. */
|
||||||
|
|
||||||
|
void
|
||||||
|
mri_only_load (const char *name)
|
||||||
|
{
|
||||||
|
mri_add_to_list (&only_load, name, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mri_base (etree_type *exp)
|
||||||
|
{
|
||||||
|
base = exp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int done_tree = 0;
|
||||||
|
|
||||||
|
void
|
||||||
|
mri_draw_tree (void)
|
||||||
|
{
|
||||||
|
if (done_tree)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Now build the statements for the ldlang machine. */
|
||||||
|
|
||||||
|
/* Attach the addresses of any which have addresses,
|
||||||
|
and add the ones not mentioned. */
|
||||||
|
if (address != NULL)
|
||||||
|
{
|
||||||
|
struct section_name_struct *alist;
|
||||||
|
struct section_name_struct *olist;
|
||||||
|
|
||||||
|
if (order == NULL)
|
||||||
|
order = address;
|
||||||
|
|
||||||
|
for (alist = address;
|
||||||
|
alist != NULL;
|
||||||
|
alist = alist->next)
|
||||||
|
{
|
||||||
|
int done = 0;
|
||||||
|
|
||||||
|
for (olist = order; done == 0 && olist != NULL; olist = olist->next)
|
||||||
|
{
|
||||||
|
if (strcmp (alist->name, olist->name) == 0)
|
||||||
|
{
|
||||||
|
olist->vma = alist->vma;
|
||||||
|
done = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!done)
|
||||||
|
{
|
||||||
|
/* Add this onto end of order list. */
|
||||||
|
mri_add_to_list (&order, alist->name, alist->vma, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we're only supposed to load a subset of them in, then prune
|
||||||
|
the list. */
|
||||||
|
if (only_load != NULL)
|
||||||
|
{
|
||||||
|
struct section_name_struct *ptr1;
|
||||||
|
struct section_name_struct *ptr2;
|
||||||
|
|
||||||
|
if (order == NULL)
|
||||||
|
order = only_load;
|
||||||
|
|
||||||
|
/* See if this name is in the list, if it is then we can load it. */
|
||||||
|
for (ptr1 = only_load; ptr1; ptr1 = ptr1->next)
|
||||||
|
for (ptr2 = order; ptr2; ptr2 = ptr2->next)
|
||||||
|
if (strcmp (ptr2->name, ptr1->name) == 0)
|
||||||
|
ptr2->ok_to_load = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No only load list, so everything is ok to load. */
|
||||||
|
struct section_name_struct *ptr;
|
||||||
|
|
||||||
|
for (ptr = order; ptr; ptr = ptr->next)
|
||||||
|
ptr->ok_to_load = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the order of sections to load. */
|
||||||
|
if (order != NULL)
|
||||||
|
{
|
||||||
|
/* Been told to output the sections in a certain order. */
|
||||||
|
struct section_name_struct *p = order;
|
||||||
|
|
||||||
|
while (p)
|
||||||
|
{
|
||||||
|
struct section_name_struct *aptr;
|
||||||
|
etree_type *align = 0;
|
||||||
|
etree_type *subalign = 0;
|
||||||
|
struct wildcard_list *tmp;
|
||||||
|
|
||||||
|
/* See if an alignment has been specified. */
|
||||||
|
for (aptr = alignment; aptr; aptr = aptr->next)
|
||||||
|
if (strcmp (aptr->name, p->name) == 0)
|
||||||
|
align = aptr->align;
|
||||||
|
|
||||||
|
for (aptr = subalignment; aptr; aptr = aptr->next)
|
||||||
|
if (strcmp (aptr->name, p->name) == 0)
|
||||||
|
subalign = aptr->subalign;
|
||||||
|
|
||||||
|
if (base == 0)
|
||||||
|
base = p->vma ? p->vma : exp_nameop (NAME, ".");
|
||||||
|
|
||||||
|
lang_enter_output_section_statement (p->name, base,
|
||||||
|
p->ok_to_load ? normal_section : noload_section,
|
||||||
|
align, subalign, NULL, 0, 0);
|
||||||
|
base = 0;
|
||||||
|
tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
|
||||||
|
tmp->next = NULL;
|
||||||
|
tmp->spec.name = p->name;
|
||||||
|
tmp->spec.exclude_name_list = NULL;
|
||||||
|
tmp->spec.sorted = none;
|
||||||
|
tmp->spec.section_flag_list = NULL;
|
||||||
|
lang_add_wild (NULL, tmp, FALSE);
|
||||||
|
|
||||||
|
/* If there is an alias for this section, add it too. */
|
||||||
|
for (aptr = alias; aptr; aptr = aptr->next)
|
||||||
|
if (strcmp (aptr->alias, p->name) == 0)
|
||||||
|
{
|
||||||
|
tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
|
||||||
|
tmp->next = NULL;
|
||||||
|
tmp->spec.name = aptr->name;
|
||||||
|
tmp->spec.exclude_name_list = NULL;
|
||||||
|
tmp->spec.sorted = none;
|
||||||
|
tmp->spec.section_flag_list = NULL;
|
||||||
|
lang_add_wild (NULL, tmp, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
lang_leave_output_section_statement (0, "*default*", NULL, NULL);
|
||||||
|
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done_tree = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mri_load (const char *name)
|
||||||
|
{
|
||||||
|
base = 0;
|
||||||
|
lang_add_input_file (name, lang_input_file_is_file_enum, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mri_order (const char *name)
|
||||||
|
{
|
||||||
|
mri_add_to_list (&order, name, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mri_alias (const char *want, const char *is, int isn)
|
||||||
|
{
|
||||||
|
if (!is)
|
||||||
|
{
|
||||||
|
char buf[20];
|
||||||
|
|
||||||
|
/* Some sections are digits. */
|
||||||
|
sprintf (buf, "%d", isn);
|
||||||
|
|
||||||
|
is = xstrdup (buf);
|
||||||
|
|
||||||
|
if (is == NULL)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
mri_add_to_list (&alias, is, 0, want, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mri_name (const char *name)
|
||||||
|
{
|
||||||
|
lang_add_output (name, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mri_format (const char *name)
|
||||||
|
{
|
||||||
|
if (strcmp (name, "S") == 0)
|
||||||
|
lang_add_output_format ("srec", NULL, NULL, 1);
|
||||||
|
|
||||||
|
else if (strcmp (name, "IEEE") == 0)
|
||||||
|
lang_add_output_format ("ieee", NULL, NULL, 1);
|
||||||
|
|
||||||
|
else if (strcmp (name, "COFF") == 0)
|
||||||
|
lang_add_output_format ("coff-m68k", NULL, NULL, 1);
|
||||||
|
|
||||||
|
else
|
||||||
|
einfo (_("%P%F: unknown format type %s\n"), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mri_public (const char *name, etree_type *exp)
|
||||||
|
{
|
||||||
|
lang_add_assignment (exp_assign (name, exp, FALSE));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mri_align (const char *name, etree_type *exp)
|
||||||
|
{
|
||||||
|
mri_add_to_list (&alignment, name, 0, 0, exp, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mri_alignmod (const char *name, etree_type *exp)
|
||||||
|
{
|
||||||
|
mri_add_to_list (&subalignment, name, 0, 0, 0, exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mri_truncate (unsigned int exp)
|
||||||
|
{
|
||||||
|
symbol_truncate = exp;
|
||||||
|
}
|
38
contrib/toolchain/binutils/ld/mri.h
Normal file
38
contrib/toolchain/binutils/ld/mri.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/* mri.h -- header file for MRI scripting functions
|
||||||
|
Copyright 1993, 1995, 1996, 2003, 2005, 2007 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#ifndef MRI_H
|
||||||
|
#define MRI_H
|
||||||
|
|
||||||
|
extern void mri_output_section (const char *, etree_type *);
|
||||||
|
extern void mri_only_load (const char *);
|
||||||
|
extern void mri_base (etree_type *);
|
||||||
|
extern void mri_load (const char *);
|
||||||
|
extern void mri_order (const char *);
|
||||||
|
extern void mri_alias (const char *, const char *, int);
|
||||||
|
extern void mri_name (const char *);
|
||||||
|
extern void mri_format (const char *);
|
||||||
|
extern void mri_public (const char *, etree_type *);
|
||||||
|
extern void mri_align (const char *, etree_type *);
|
||||||
|
extern void mri_alignmod (const char *, etree_type *);
|
||||||
|
extern void mri_truncate (unsigned int);
|
||||||
|
extern void mri_draw_tree (void);
|
||||||
|
|
||||||
|
#endif
|
3452
contrib/toolchain/binutils/ld/pe-dll.c
Normal file
3452
contrib/toolchain/binutils/ld/pe-dll.c
Normal file
File diff suppressed because it is too large
Load Diff
74
contrib/toolchain/binutils/ld/pe-dll.h
Normal file
74
contrib/toolchain/binutils/ld/pe-dll.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/* pe-dll.h: Header file for routines used to build Windows DLLs.
|
||||||
|
Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#ifndef PE_DLL_H
|
||||||
|
#define PE_DLL_H
|
||||||
|
|
||||||
|
#include "sysdep.h"
|
||||||
|
#include "bfd.h"
|
||||||
|
#include "bfdlink.h"
|
||||||
|
#include "deffile.h"
|
||||||
|
|
||||||
|
extern def_file *pe_def_file;
|
||||||
|
extern int pe_dll_export_everything;
|
||||||
|
extern int pe_dll_exclude_all_symbols;
|
||||||
|
extern int pe_dll_do_default_excludes;
|
||||||
|
extern int pe_dll_kill_ats;
|
||||||
|
extern int pe_dll_stdcall_aliases;
|
||||||
|
extern int pe_dll_warn_dup_exports;
|
||||||
|
extern int pe_dll_compat_implib;
|
||||||
|
extern int pe_dll_extra_pe_debug;
|
||||||
|
extern int pe_use_nul_prefixed_import_tables;
|
||||||
|
extern int pe_use_coff_long_section_names;
|
||||||
|
extern int pe_leading_underscore;
|
||||||
|
|
||||||
|
typedef enum { EXCLUDESYMS, EXCLUDELIBS, EXCLUDEFORIMPLIB } exclude_type;
|
||||||
|
|
||||||
|
extern void pe_dll_id_target
|
||||||
|
(const char *);
|
||||||
|
extern void pe_dll_add_excludes
|
||||||
|
(const char *, const exclude_type);
|
||||||
|
extern void pe_dll_generate_def_file
|
||||||
|
(const char *);
|
||||||
|
extern void pe_dll_generate_implib
|
||||||
|
(def_file *, const char *, struct bfd_link_info *);
|
||||||
|
extern void pe_process_import_defs
|
||||||
|
(bfd *, struct bfd_link_info *);
|
||||||
|
extern bfd_boolean pe_implied_import_dll
|
||||||
|
(const char *);
|
||||||
|
extern void pe_dll_build_sections
|
||||||
|
(bfd *, struct bfd_link_info *);
|
||||||
|
extern void pe_exe_build_sections
|
||||||
|
(bfd *, struct bfd_link_info *);
|
||||||
|
extern void pe_dll_fill_sections
|
||||||
|
(bfd *, struct bfd_link_info *);
|
||||||
|
extern void pe_exe_fill_sections
|
||||||
|
(bfd *, struct bfd_link_info *);
|
||||||
|
extern void pe_walk_relocs_of_symbol
|
||||||
|
(struct bfd_link_info *, const char *, int (*) (arelent *, asection *));
|
||||||
|
extern void pe_create_import_fixup
|
||||||
|
(arelent * rel, asection *, bfd_vma);
|
||||||
|
extern bfd_boolean pe_bfd_is_dll
|
||||||
|
(bfd *);
|
||||||
|
extern void pe_output_file_set_long_section_names
|
||||||
|
(bfd *);
|
||||||
|
|
||||||
|
#endif /* PE_DLL_H */
|
1041
contrib/toolchain/binutils/ld/plugin.c
Normal file
1041
contrib/toolchain/binutils/ld/plugin.c
Normal file
File diff suppressed because it is too large
Load Diff
72
contrib/toolchain/binutils/ld/plugin.h
Normal file
72
contrib/toolchain/binutils/ld/plugin.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/* Plugin control for the GNU linker.
|
||||||
|
Copyright 2010, 2011 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU Binutils.
|
||||||
|
|
||||||
|
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#ifndef GLD_PLUGIN_H
|
||||||
|
#define GLD_PLUGIN_H
|
||||||
|
|
||||||
|
/* Report plugin symbols. */
|
||||||
|
extern bfd_boolean report_plugin_symbols;
|
||||||
|
|
||||||
|
/* Set at all symbols read time, to avoid recursively offering the plugin
|
||||||
|
its own newly-added input files and libs to claim. */
|
||||||
|
extern bfd_boolean no_more_claiming;
|
||||||
|
|
||||||
|
/* This is the only forward declaration we need to avoid having
|
||||||
|
to include the plugin-api.h header in order to use this file. */
|
||||||
|
struct ld_plugin_input_file;
|
||||||
|
|
||||||
|
/* Handle -plugin arg: find and load plugin. */
|
||||||
|
extern void plugin_opt_plugin (const char *plugin);
|
||||||
|
|
||||||
|
/* Accumulate option arguments for last-loaded plugin, or return
|
||||||
|
error if none. */
|
||||||
|
extern int plugin_opt_plugin_arg (const char *arg);
|
||||||
|
|
||||||
|
/* Return true if any plugins are active this run. Only valid
|
||||||
|
after options have been processed. */
|
||||||
|
extern bfd_boolean plugin_active_plugins_p (void);
|
||||||
|
|
||||||
|
/* Load up and initialise all plugins after argument parsing. */
|
||||||
|
extern void plugin_load_plugins (void);
|
||||||
|
|
||||||
|
/* Return name of plugin which caused an error in any of the above. */
|
||||||
|
extern const char *plugin_error_plugin (void);
|
||||||
|
|
||||||
|
/* Call 'claim file' hook for all plugins. */
|
||||||
|
extern void plugin_maybe_claim (struct ld_plugin_input_file *,
|
||||||
|
lang_input_statement_type *);
|
||||||
|
|
||||||
|
/* Call 'all symbols read' hook for all plugins. */
|
||||||
|
extern int plugin_call_all_symbols_read (void);
|
||||||
|
|
||||||
|
/* Call 'cleanup' hook for all plugins at exit. */
|
||||||
|
extern void plugin_call_cleanup (void);
|
||||||
|
|
||||||
|
/* Generate a dummy BFD to represent an IR file, for any callers of
|
||||||
|
plugin_call_claim_file to use as the handle in the ld_plugin_input_file
|
||||||
|
struct that they build to pass in. The BFD is initially writable, so
|
||||||
|
that symbols can be added to it; it must be made readable after the
|
||||||
|
add_symbols hook has been called so that it can be read when linking. */
|
||||||
|
extern bfd *plugin_get_ir_dummy_bfd (const char *name, bfd *template);
|
||||||
|
|
||||||
|
/* Return true if bfd is a dynamic library that should be reloaded. */
|
||||||
|
extern bfd_boolean plugin_should_reload (bfd *);
|
||||||
|
|
||||||
|
#endif /* !def GLD_PLUGIN_H */
|
@ -36,7 +36,7 @@ all: libiberty.a
|
|||||||
|
|
||||||
libiberty.a : $(OBJS) MAkefile
|
libiberty.a : $(OBJS) MAkefile
|
||||||
$(AR) crs libiberty.a $(OBJS)
|
$(AR) crs libiberty.a $(OBJS)
|
||||||
# mv -f libiberty.a $(SDK_DIR)/lib
|
mv -f libiberty.a $(SDK_DIR)/lib
|
||||||
|
|
||||||
%.o : %.c Makefile
|
%.o : %.c Makefile
|
||||||
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $<
|
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $<
|
||||||
|
@ -41,15 +41,6 @@ extern int errno;
|
|||||||
|
|
||||||
#include "libiberty.h"
|
#include "libiberty.h"
|
||||||
|
|
||||||
/* Virtually every UN*X system now in common use (except for pre-4.3-tahoe
|
|
||||||
BSD systems) now provides getcwd as called for by POSIX. Allow for
|
|
||||||
the few exceptions to the general rule here. */
|
|
||||||
|
|
||||||
#if !defined(HAVE_GETCWD) && defined(HAVE_GETWD)
|
|
||||||
/* Prototype in case the system headers doesn't provide it. */
|
|
||||||
extern char *getwd ();
|
|
||||||
#define getcwd(buf,len) getwd(buf)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MAXPATHLEN
|
#ifdef MAXPATHLEN
|
||||||
#define GUESSPATHLEN (MAXPATHLEN + 1)
|
#define GUESSPATHLEN (MAXPATHLEN + 1)
|
||||||
@ -57,72 +48,32 @@ extern char *getwd ();
|
|||||||
#define GUESSPATHLEN 100
|
#define GUESSPATHLEN 100
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !(defined (VMS) || (defined(_WIN32) && !defined(__CYGWIN__)))
|
|
||||||
|
|
||||||
/* Get the working directory. Use the PWD environment variable if it's
|
|
||||||
set correctly, since this is faster and gives more uniform answers
|
|
||||||
to the user. Yield the working directory if successful; otherwise,
|
|
||||||
yield 0 and set errno. */
|
|
||||||
|
|
||||||
char *
|
|
||||||
getpwd (void)
|
|
||||||
{
|
|
||||||
static char *pwd;
|
|
||||||
static int failure_errno;
|
|
||||||
|
|
||||||
char *p = pwd;
|
|
||||||
size_t s;
|
|
||||||
struct stat dotstat, pwdstat;
|
|
||||||
|
|
||||||
if (!p && !(errno = failure_errno))
|
|
||||||
{
|
|
||||||
if (! ((p = getenv ("PWD")) != 0
|
|
||||||
&& *p == '/'
|
|
||||||
&& stat (p, &pwdstat) == 0
|
|
||||||
&& stat (".", &dotstat) == 0
|
|
||||||
&& dotstat.st_ino == pwdstat.st_ino
|
|
||||||
&& dotstat.st_dev == pwdstat.st_dev))
|
|
||||||
|
|
||||||
/* The shortcut didn't work. Try the slow, ``sure'' way. */
|
|
||||||
for (s = GUESSPATHLEN; !getcwd (p = XNEWVEC (char, s), s); s *= 2)
|
|
||||||
{
|
|
||||||
int e = errno;
|
|
||||||
free (p);
|
|
||||||
#ifdef ERANGE
|
|
||||||
if (e != ERANGE)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
errno = failure_errno = e;
|
|
||||||
p = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Cache the result. This assumes that the program does
|
|
||||||
not invoke chdir between calls to getpwd. */
|
|
||||||
pwd = p;
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* VMS || _WIN32 && !__CYGWIN__ */
|
|
||||||
|
|
||||||
#ifndef MAXPATHLEN
|
#ifndef MAXPATHLEN
|
||||||
#define MAXPATHLEN 255
|
#define MAXPATHLEN 255
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static char *getccwd(char *buf, size_t size)
|
||||||
|
{
|
||||||
|
int bsize;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"int $0x40"
|
||||||
|
:"=a"(bsize)
|
||||||
|
:"a"(30),"b"(2),"c"(buf), "d"(size)
|
||||||
|
:"memory");
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
};
|
||||||
|
|
||||||
char *
|
char *
|
||||||
getpwd (void)
|
getpwd (void)
|
||||||
{
|
{
|
||||||
static char *pwd = 0;
|
static char *pwd = 0;
|
||||||
|
|
||||||
if (!pwd)
|
if (!pwd)
|
||||||
pwd = getcwd (XNEWVEC (char, MAXPATHLEN + 1), MAXPATHLEN + 1
|
pwd = getccwd (XNEWVEC (char, MAXPATHLEN + 1), MAXPATHLEN + 1);
|
||||||
#ifdef VMS
|
|
||||||
, 0
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
return pwd;
|
return pwd;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* VMS || _WIN32 && !__CYGWIN__ */
|
|
||||||
|
@ -235,77 +235,81 @@ make_relative_prefix_1 (const char *progname, const char *bin_prefix,
|
|||||||
char *ret = NULL, *ptr, *full_progname;
|
char *ret = NULL, *ptr, *full_progname;
|
||||||
|
|
||||||
if (progname == NULL || bin_prefix == NULL || prefix == NULL)
|
if (progname == NULL || bin_prefix == NULL || prefix == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* If there is no full pathname, try to find the program by checking in each
|
/* If there is no full pathname, try to find the program by checking in each
|
||||||
of the directories specified in the PATH environment variable. */
|
of the directories specified in the PATH environment variable. */
|
||||||
if (lbasename (progname) == progname)
|
if (lbasename (progname) == progname)
|
||||||
{
|
{
|
||||||
char *temp;
|
char *temp;
|
||||||
|
|
||||||
temp = getenv ("PATH");
|
#if 0
|
||||||
if (temp)
|
temp = getenv ("PATH");
|
||||||
{
|
|
||||||
char *startp, *endp, *nstore;
|
|
||||||
size_t prefixlen = strlen (temp) + 1;
|
|
||||||
size_t len;
|
|
||||||
if (prefixlen < 2)
|
|
||||||
prefixlen = 2;
|
|
||||||
|
|
||||||
len = prefixlen + strlen (progname) + 1;
|
if (temp)
|
||||||
|
{
|
||||||
|
char *startp, *endp, *nstore;
|
||||||
|
size_t prefixlen = strlen (temp) + 1;
|
||||||
|
size_t len;
|
||||||
|
if (prefixlen < 2)
|
||||||
|
prefixlen = 2;
|
||||||
|
|
||||||
|
len = prefixlen + strlen (progname) + 1;
|
||||||
#ifdef HAVE_HOST_EXECUTABLE_SUFFIX
|
#ifdef HAVE_HOST_EXECUTABLE_SUFFIX
|
||||||
len += strlen (HOST_EXECUTABLE_SUFFIX);
|
len += strlen (HOST_EXECUTABLE_SUFFIX);
|
||||||
#endif
|
#endif
|
||||||
nstore = (char *) alloca (len);
|
nstore = (char *) alloca (len);
|
||||||
|
|
||||||
startp = endp = temp;
|
startp = endp = temp;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (*endp == PATH_SEPARATOR || *endp == 0)
|
if (*endp == PATH_SEPARATOR || *endp == 0)
|
||||||
{
|
{
|
||||||
if (endp == startp)
|
if (endp == startp)
|
||||||
{
|
{
|
||||||
nstore[0] = '.';
|
nstore[0] = '.';
|
||||||
nstore[1] = DIR_SEPARATOR;
|
nstore[1] = DIR_SEPARATOR;
|
||||||
nstore[2] = '\0';
|
nstore[2] = '\0';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy (nstore, startp, endp - startp);
|
memcpy (nstore, startp, endp - startp);
|
||||||
if (! IS_DIR_SEPARATOR (endp[-1]))
|
if (! IS_DIR_SEPARATOR (endp[-1]))
|
||||||
{
|
{
|
||||||
nstore[endp - startp] = DIR_SEPARATOR;
|
nstore[endp - startp] = DIR_SEPARATOR;
|
||||||
nstore[endp - startp + 1] = 0;
|
nstore[endp - startp + 1] = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
nstore[endp - startp] = 0;
|
nstore[endp - startp] = 0;
|
||||||
}
|
}
|
||||||
strcat (nstore, progname);
|
strcat (nstore, progname);
|
||||||
if (! access (nstore, X_OK)
|
if (! access (nstore, X_OK)
|
||||||
#ifdef HAVE_HOST_EXECUTABLE_SUFFIX
|
#ifdef HAVE_HOST_EXECUTABLE_SUFFIX
|
||||||
|| ! access (strcat (nstore, HOST_EXECUTABLE_SUFFIX), X_OK)
|
|| ! access (strcat (nstore, HOST_EXECUTABLE_SUFFIX), X_OK)
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
#if defined (HAVE_SYS_STAT_H) && defined (S_ISREG)
|
#if defined (HAVE_SYS_STAT_H) && defined (S_ISREG)
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat (nstore, &st) >= 0 && S_ISREG (st.st_mode))
|
if (stat (nstore, &st) >= 0 && S_ISREG (st.st_mode))
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
progname = nstore;
|
progname = nstore;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*endp == 0)
|
if (*endp == 0)
|
||||||
break;
|
break;
|
||||||
endp = startp = endp + 1;
|
endp = startp = endp + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
endp++;
|
endp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (resolve_links)
|
if (resolve_links)
|
||||||
full_progname = lrealpath (progname);
|
full_progname = lrealpath (progname);
|
||||||
|
@ -64,9 +64,9 @@ unlink_if_ordinary (const char *name)
|
|||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (lstat (name, &st) == 0
|
// if (lstat (name, &st) == 0
|
||||||
&& (S_ISREG (st.st_mode) || S_ISLNK (st.st_mode)))
|
// && (S_ISREG (st.st_mode) || S_ISLNK (st.st_mode)))
|
||||||
return unlink (name);
|
// return unlink (name);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user