binutils: build LD.

git-svn-id: svn://kolibrios.org@5199 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2014-11-29 06:17:35 +00:00
parent 84eba6470e
commit 8bb709c8c6
51 changed files with 40053 additions and 169 deletions

View File

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

View File

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

View File

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

View 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;
}

View File

@ -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))));
*/
}
}
}

View 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"

View File

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

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

View 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 */

View 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 */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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

View 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

View 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);
}

View 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 ();
}

View 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

View 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

View 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;
}

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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);
}

View 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

File diff suppressed because it is too large Load Diff

View 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;

File diff suppressed because it is too large Load Diff

View 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

View 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"

File diff suppressed because it is too large Load Diff

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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);
}

View 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

View 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++;
}
}
}

View 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);

View 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);
}
}

View 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);

File diff suppressed because it is too large Load Diff

View 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;
}

View 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

File diff suppressed because it is too large Load Diff

View 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 */

File diff suppressed because it is too large Load Diff

View 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 */

View File

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

View File

@ -66,10 +66,10 @@ dupargv (char **argv)
{
int argc;
char **copy;
if (argv == NULL)
return NULL;
/* the vector */
for (argc = 0; argv[argc] != NULL; argc++);
copy = (char **) xmalloc ((argc + 1) * sizeof (char *));
@ -441,11 +441,11 @@ expandargv (int *argcp, char ***argvp)
while (file_argv[file_argc])
++file_argc;
/* Now, insert FILE_ARGV into ARGV. The "+1" below handles the
NULL terminator at the end of ARGV. */
*argvp = ((char **)
xrealloc (*argvp,
NULL terminator at the end of ARGV. */
*argvp = ((char **)
xrealloc (*argvp,
(*argcp + file_argc + 1) * sizeof (char *)));
memmove (*argvp + i + file_argc, *argvp + i + 1,
memmove (*argvp + i + file_argc, *argvp + i + 1,
(*argcp - i) * sizeof (char *));
memcpy (*argvp + i, file_argv, file_argc * sizeof (char *));
/* The original option has been replaced by all the new
@ -501,7 +501,7 @@ static const char *const tests[] =
"arg 'Jack said \\'hi\\'' has single quotes",
"arg 'Jack said \\\"hi\\\"' has double quotes",
"a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9",
/* This should be expanded into only one argument. */
"trailing-whitespace ",

View File

@ -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__ */

View File

@ -82,7 +82,7 @@ relative prefix can be found, return @code{NULL}.
# define HAVE_DOS_BASED_FILE_SYSTEM
# define HAVE_HOST_EXECUTABLE_SUFFIX
# define HOST_EXECUTABLE_SUFFIX ".exe"
# ifndef DIR_SEPARATOR_2
# ifndef DIR_SEPARATOR_2
# define DIR_SEPARATOR_2 '\\'
# endif
# define PATH_SEPARATOR ';'
@ -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);

View File

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