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+= --out-implib
|
||||
|
||||
SUBDIRS = libiberty bfd
|
||||
SUBDIRS = libiberty bfd ld
|
||||
|
||||
# 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_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 = \
|
||||
archive.c archures.c bfd.c bfdio.c \
|
||||
@ -19,9 +21,9 @@ SRCS = \
|
||||
elf-nacl.c elf-strtab.c elf-vxworks.c \
|
||||
format.c hash.c ihex.c init.c libbfd.c \
|
||||
linker.c merge.c opncls.c pe-i386.c \
|
||||
peigen.c reloc.c section.c simple.c \
|
||||
srec.c stabs.c stab-syms.c syms.c \
|
||||
targets.c tekhex.c verilog.c
|
||||
peigen.c pei-i386.c reloc.c section.c \
|
||||
simple.c srec.c stabs.c stab-syms.c \
|
||||
syms.c targets.c tekhex.c verilog.c
|
||||
|
||||
|
||||
OBJS = $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS)))
|
||||
@ -32,13 +34,18 @@ all: libbfd.a
|
||||
|
||||
libbfd.a : $(OBJS) MAkefile
|
||||
$(AR) crs libbfd.a $(OBJS)
|
||||
# mv -f libbfd.a $(SDK_DIR)/lib
|
||||
mv -f libbfd.a $(SDK_DIR)/lib
|
||||
|
||||
%.o : %.c Makefile
|
||||
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $<
|
||||
|
||||
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 *
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -76,23 +76,8 @@ static int max_open_files = 0;
|
||||
static int
|
||||
bfd_cache_max_open (void)
|
||||
{
|
||||
if (max_open_files == 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
max_open_files = 16;
|
||||
|
||||
return max_open_files;
|
||||
}
|
||||
|
@ -673,12 +673,14 @@ _maybe_make_executable (bfd * abfd)
|
||||
which run tests with "ld [...] -o /dev/null". */
|
||||
&& S_ISREG(buf.st_mode))
|
||||
{
|
||||
unsigned int mask = umask (0);
|
||||
/*
|
||||
unsigned int mask = umask (0);
|
||||
|
||||
umask (mask);
|
||||
chmod (abfd->filename,
|
||||
umask (mask);
|
||||
chmod (abfd->filename,
|
||||
(0777
|
||||
& (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
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "config.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
|
||||
$(AR) crs libiberty.a $(OBJS)
|
||||
# mv -f libiberty.a $(SDK_DIR)/lib
|
||||
mv -f libiberty.a $(SDK_DIR)/lib
|
||||
|
||||
%.o : %.c Makefile
|
||||
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $<
|
||||
|
@ -41,15 +41,6 @@ extern int errno;
|
||||
|
||||
#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
|
||||
#define GUESSPATHLEN (MAXPATHLEN + 1)
|
||||
@ -57,72 +48,32 @@ extern char *getwd ();
|
||||
#define GUESSPATHLEN 100
|
||||
#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
|
||||
#define MAXPATHLEN 255
|
||||
#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 *
|
||||
getpwd (void)
|
||||
{
|
||||
static char *pwd = 0;
|
||||
|
||||
if (!pwd)
|
||||
pwd = getcwd (XNEWVEC (char, MAXPATHLEN + 1), MAXPATHLEN + 1
|
||||
#ifdef VMS
|
||||
, 0
|
||||
#endif
|
||||
);
|
||||
pwd = getccwd (XNEWVEC (char, MAXPATHLEN + 1), MAXPATHLEN + 1);
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
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 (temp)
|
||||
{
|
||||
char *startp, *endp, *nstore;
|
||||
size_t prefixlen = strlen (temp) + 1;
|
||||
size_t len;
|
||||
if (prefixlen < 2)
|
||||
prefixlen = 2;
|
||||
#if 0
|
||||
temp = getenv ("PATH");
|
||||
|
||||
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
|
||||
len += strlen (HOST_EXECUTABLE_SUFFIX);
|
||||
len += strlen (HOST_EXECUTABLE_SUFFIX);
|
||||
#endif
|
||||
nstore = (char *) alloca (len);
|
||||
nstore = (char *) alloca (len);
|
||||
|
||||
startp = endp = temp;
|
||||
while (1)
|
||||
{
|
||||
if (*endp == PATH_SEPARATOR || *endp == 0)
|
||||
{
|
||||
if (endp == startp)
|
||||
{
|
||||
nstore[0] = '.';
|
||||
nstore[1] = DIR_SEPARATOR;
|
||||
nstore[2] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (nstore, startp, endp - startp);
|
||||
if (! IS_DIR_SEPARATOR (endp[-1]))
|
||||
{
|
||||
nstore[endp - startp] = DIR_SEPARATOR;
|
||||
nstore[endp - startp + 1] = 0;
|
||||
}
|
||||
else
|
||||
nstore[endp - startp] = 0;
|
||||
}
|
||||
strcat (nstore, progname);
|
||||
if (! access (nstore, X_OK)
|
||||
startp = endp = temp;
|
||||
while (1)
|
||||
{
|
||||
if (*endp == PATH_SEPARATOR || *endp == 0)
|
||||
{
|
||||
if (endp == startp)
|
||||
{
|
||||
nstore[0] = '.';
|
||||
nstore[1] = DIR_SEPARATOR;
|
||||
nstore[2] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (nstore, startp, endp - startp);
|
||||
if (! IS_DIR_SEPARATOR (endp[-1]))
|
||||
{
|
||||
nstore[endp - startp] = DIR_SEPARATOR;
|
||||
nstore[endp - startp + 1] = 0;
|
||||
}
|
||||
else
|
||||
nstore[endp - startp] = 0;
|
||||
}
|
||||
strcat (nstore, progname);
|
||||
if (! access (nstore, X_OK)
|
||||
#ifdef HAVE_HOST_EXECUTABLE_SUFFIX
|
||||
|| ! access (strcat (nstore, HOST_EXECUTABLE_SUFFIX), X_OK)
|
||||
|| ! access (strcat (nstore, HOST_EXECUTABLE_SUFFIX), X_OK)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
)
|
||||
{
|
||||
#if defined (HAVE_SYS_STAT_H) && defined (S_ISREG)
|
||||
struct stat st;
|
||||
if (stat (nstore, &st) >= 0 && S_ISREG (st.st_mode))
|
||||
struct stat st;
|
||||
if (stat (nstore, &st) >= 0 && S_ISREG (st.st_mode))
|
||||
#endif
|
||||
{
|
||||
progname = nstore;
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
progname = nstore;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*endp == 0)
|
||||
break;
|
||||
endp = startp = endp + 1;
|
||||
}
|
||||
else
|
||||
endp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*endp == 0)
|
||||
break;
|
||||
endp = startp = endp + 1;
|
||||
}
|
||||
else
|
||||
endp++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if (resolve_links)
|
||||
full_progname = lrealpath (progname);
|
||||
|
@ -64,9 +64,9 @@ unlink_if_ordinary (const char *name)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (lstat (name, &st) == 0
|
||||
&& (S_ISREG (st.st_mode) || S_ISLNK (st.st_mode)))
|
||||
return unlink (name);
|
||||
// if (lstat (name, &st) == 0
|
||||
// && (S_ISREG (st.st_mode) || S_ISLNK (st.st_mode)))
|
||||
// return unlink (name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user