binutils: build libbfd

git-svn-id: svn://kolibrios.org@5197 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge)
2014-11-28 23:54:02 +00:00
parent 2a46f2320b
commit 40cd438474
70 changed files with 116975 additions and 1 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
SUBDIRS = libiberty bfd
# targets

View File

@@ -0,0 +1,44 @@
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 -Wstrict-prototypes -Wmissing-prototypes -Wshadow -Wno-format -Werror
CFLAGS = -c $(CFLAGS_OPT)
INCLUDES= -I. -I../include -I$(SDK_DIR)/sources/newlib/libc/include -I$(SDK_DIR)/sources/zlib
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"
SRCS = \
archive.c archures.c bfd.c bfdio.c \
binary.c cache.c coffgen.c cofflink.c \
compress.c corefile.c cpu-i386.c \
dwarf1.c dwarf2.c elf.c elf32.c \
elf32-gen.c elf32-i386.c elf-attrs.c \
elf-eh-frame.c elf-ifunc.c elflink.c \
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
OBJS = $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS)))
# targets
all: libbfd.a
libbfd.a : $(OBJS) MAkefile
$(AR) crs libbfd.a $(OBJS)
# 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 $@ $<

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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,47 @@
/* generated for gcc.exe (GCC) 4.8.1 */
#ifndef GCC_GENERATED_STDINT_H
#define GCC_GENERATED_STDINT_H 1
#include <sys/types.h>
#include <stdint.h>
/* glibc uses these symbols as guards to prevent redefinitions. */
#ifdef __int8_t_defined
#define _INT8_T
#define _INT16_T
#define _INT32_T
#endif
#ifdef __uint32_t_defined
#define _UINT32_T
#endif
/* Some systems have guard macros to prevent redefinitions, define them. */
#ifndef _INT8_T
#define _INT8_T
#endif
#ifndef _INT16_T
#define _INT16_T
#endif
#ifndef _INT32_T
#define _INT32_T
#endif
#ifndef _UINT8_T
#define _UINT8_T
#endif
#ifndef _UINT16_T
#define _UINT16_T
#endif
#ifndef _UINT32_T
#define _UINT32_T
#endif
/* system headers have good uint64_t and int64_t */
#ifndef _INT64_T
#define _INT64_T
#endif
#ifndef _UINT64_T
#define _UINT64_T
#endif
#endif /* GCC_GENERATED_STDINT_H */

View File

@@ -0,0 +1,621 @@
/* Low-level I/O routines for BFDs.
Copyright 1990-2013 Free Software Foundation, Inc.
Written by Cygnus Support.
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 <limits.h>
#include "bfd.h"
#include "libbfd.h"
#ifndef S_IXUSR
#define S_IXUSR 0100 /* Execute by owner. */
#endif
#ifndef S_IXGRP
#define S_IXGRP 0010 /* Execute by group. */
#endif
#ifndef S_IXOTH
#define S_IXOTH 0001 /* Execute by others. */
#endif
#ifndef FD_CLOEXEC
#define FD_CLOEXEC 1
#endif
file_ptr
real_ftell (FILE *file)
{
#if defined (HAVE_FTELLO64)
return ftello64 (file);
#elif defined (HAVE_FTELLO)
return ftello (file);
#else
return ftell (file);
#endif
}
int
real_fseek (FILE *file, file_ptr offset, int whence)
{
#if defined (HAVE_FSEEKO64)
return fseeko64 (file, offset, whence);
#elif defined (HAVE_FSEEKO)
return fseeko (file, offset, whence);
#else
return fseek (file, offset, whence);
#endif
}
/* Mark FILE as close-on-exec. Return FILE. FILE may be NULL, in
which case nothing is done. */
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;
}
FILE *
real_fopen (const char *filename, const char *modes)
{
#ifdef VMS
char *vms_attr;
/* On VMS, fopen allows file attributes as optional arguments.
We need to use them but we'd better to use the common prototype.
In fopen-vms.h, they are separated from the mode with a comma.
Split here. */
vms_attr = strchr (modes, ',');
if (vms_attr == NULL)
{
/* No attributes. */
return close_on_exec (fopen (filename, modes));
}
else
{
/* Attributes found. Split. */
size_t modes_len = strlen (modes) + 1;
char attrs[modes_len + 1];
char *at[3];
int i;
memcpy (attrs, modes, modes_len);
at[0] = attrs;
for (i = 0; i < 2; i++)
{
at[i + 1] = strchr (at[i], ',');
BFD_ASSERT (at[i + 1] != NULL);
*(at[i + 1]++) = 0; /* Replace ',' with a nul, and skip it. */
}
return close_on_exec (fopen (filename, at[0], at[1], at[2]));
}
#else /* !VMS */
#if defined (HAVE_FOPEN64)
return close_on_exec (fopen64 (filename, modes));
#else
return close_on_exec (fopen (filename, modes));
#endif
#endif /* !VMS */
}
/*
INTERNAL_DEFINITION
struct bfd_iovec
DESCRIPTION
The <<struct bfd_iovec>> contains the internal file I/O class.
Each <<BFD>> has an instance of this class and all file I/O is
routed through it (it is assumed that the instance implements
all methods listed below).
.struct bfd_iovec
.{
. {* To avoid problems with macros, a "b" rather than "f"
. prefix is prepended to each method name. *}
. {* Attempt to read/write NBYTES on ABFD's IOSTREAM storing/fetching
. bytes starting at PTR. Return the number of bytes actually
. transfered (a read past end-of-file returns less than NBYTES),
. or -1 (setting <<bfd_error>>) if an error occurs. *}
. file_ptr (*bread) (struct bfd *abfd, void *ptr, file_ptr nbytes);
. file_ptr (*bwrite) (struct bfd *abfd, const void *ptr,
. file_ptr nbytes);
. {* Return the current IOSTREAM file offset, or -1 (setting <<bfd_error>>
. if an error occurs. *}
. file_ptr (*btell) (struct bfd *abfd);
. {* For the following, on successful completion a value of 0 is returned.
. Otherwise, a value of -1 is returned (and <<bfd_error>> is set). *}
. int (*bseek) (struct bfd *abfd, file_ptr offset, int whence);
. int (*bclose) (struct bfd *abfd);
. int (*bflush) (struct bfd *abfd);
. int (*bstat) (struct bfd *abfd, struct stat *sb);
. {* Mmap a part of the files. ADDR, LEN, PROT, FLAGS and OFFSET are the usual
. mmap parameter, except that LEN and OFFSET do not need to be page
. aligned. Returns (void *)-1 on failure, mmapped address on success.
. Also write in MAP_ADDR the address of the page aligned buffer and in
. MAP_LEN the size mapped (a page multiple). Use unmap with MAP_ADDR and
. MAP_LEN to unmap. *}
. void *(*bmmap) (struct bfd *abfd, void *addr, bfd_size_type len,
. int prot, int flags, file_ptr offset,
. void **map_addr, bfd_size_type *map_len);
.};
.extern const struct bfd_iovec _bfd_memory_iovec;
*/
/* Return value is amount read. */
bfd_size_type
bfd_bread (void *ptr, bfd_size_type size, bfd *abfd)
{
size_t nread;
/* If this is an archive element, don't read past the end of
this element. */
if (abfd->arelt_data != NULL)
{
bfd_size_type maxbytes = arelt_size (abfd);
if (abfd->where + size > maxbytes)
{
if (abfd->where >= maxbytes)
return 0;
size = maxbytes - abfd->where;
}
}
if (abfd->iovec)
nread = abfd->iovec->bread (abfd, ptr, size);
else
nread = 0;
if (nread != (size_t) -1)
abfd->where += nread;
return nread;
}
bfd_size_type
bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd)
{
size_t nwrote;
if (abfd->iovec)
nwrote = abfd->iovec->bwrite (abfd, ptr, size);
else
nwrote = 0;
if (nwrote != (size_t) -1)
abfd->where += nwrote;
if (nwrote != size)
{
#ifdef ENOSPC
errno = ENOSPC;
#endif
bfd_set_error (bfd_error_system_call);
}
return nwrote;
}
file_ptr
bfd_tell (bfd *abfd)
{
file_ptr ptr;
if (abfd->iovec)
{
bfd *parent_bfd = abfd;
ptr = abfd->iovec->btell (abfd);
while (parent_bfd->my_archive != NULL)
{
ptr -= parent_bfd->origin;
parent_bfd = parent_bfd->my_archive;
}
}
else
ptr = 0;
abfd->where = ptr;
return ptr;
}
int
bfd_flush (bfd *abfd)
{
if (abfd->iovec)
return abfd->iovec->bflush (abfd);
return 0;
}
/* Returns 0 for success, negative value for failure (in which case
bfd_get_error can retrieve the error code). */
int
bfd_stat (bfd *abfd, struct stat *statbuf)
{
int result;
if (abfd->iovec)
result = abfd->iovec->bstat (abfd, statbuf);
else
result = -1;
if (result < 0)
bfd_set_error (bfd_error_system_call);
return result;
}
/* Returns 0 for success, nonzero for failure (in which case bfd_get_error
can retrieve the error code). */
int
bfd_seek (bfd *abfd, file_ptr position, int direction)
{
int result;
file_ptr file_position;
/* For the time being, a BFD may not seek to it's end. The problem
is that we don't easily have a way to recognize the end of an
element in an archive. */
BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR);
if (direction == SEEK_CUR && position == 0)
return 0;
if (abfd->format != bfd_archive && abfd->my_archive == 0)
{
if (direction == SEEK_SET && (bfd_vma) position == abfd->where)
return 0;
}
else
{
/* We need something smarter to optimize access to archives.
Currently, anything inside an archive is read via the file
handle for the archive. Which means that a bfd_seek on one
component affects the `current position' in the archive, as
well as in any other component.
It might be sufficient to put a spike through the cache
abstraction, and look to the archive for the file position,
but I think we should try for something cleaner.
In the meantime, no optimization for archives. */
}
file_position = position;
if (direction == SEEK_SET)
{
bfd *parent_bfd = abfd;
while (parent_bfd->my_archive != NULL)
{
file_position += parent_bfd->origin;
parent_bfd = parent_bfd->my_archive;
}
}
if (abfd->iovec)
result = abfd->iovec->bseek (abfd, file_position, direction);
else
result = -1;
if (result != 0)
{
int hold_errno = errno;
/* Force redetermination of `where' field. */
bfd_tell (abfd);
/* An EINVAL error probably means that the file offset was
absurd. */
if (hold_errno == EINVAL)
bfd_set_error (bfd_error_file_truncated);
else
{
bfd_set_error (bfd_error_system_call);
errno = hold_errno;
}
}
else
{
/* Adjust `where' field. */
if (direction == SEEK_SET)
abfd->where = position;
else
abfd->where += position;
}
return result;
}
/*
FUNCTION
bfd_get_mtime
SYNOPSIS
long bfd_get_mtime (bfd *abfd);
DESCRIPTION
Return the file modification time (as read from the file system, or
from the archive header for archive members).
*/
long
bfd_get_mtime (bfd *abfd)
{
struct stat buf;
if (abfd->mtime_set)
return abfd->mtime;
if (abfd->iovec == NULL)
return 0;
if (abfd->iovec->bstat (abfd, &buf) != 0)
return 0;
abfd->mtime = buf.st_mtime; /* Save value in case anyone wants it */
return buf.st_mtime;
}
/*
FUNCTION
bfd_get_size
SYNOPSIS
file_ptr bfd_get_size (bfd *abfd);
DESCRIPTION
Return the file size (as read from file system) for the file
associated with BFD @var{abfd}.
The initial motivation for, and use of, this routine is not
so we can get the exact size of the object the BFD applies to, since
that might not be generally possible (archive members for example).
It would be ideal if someone could eventually modify
it so that such results were guaranteed.
Instead, we want to ask questions like "is this NNN byte sized
object I'm about to try read from file offset YYY reasonable?"
As as example of where we might do this, some object formats
use string tables for which the first <<sizeof (long)>> bytes of the
table contain the size of the table itself, including the size bytes.
If an application tries to read what it thinks is one of these
string tables, without some way to validate the size, and for
some reason the size is wrong (byte swapping error, wrong location
for the string table, etc.), the only clue is likely to be a read
error when it tries to read the table, or a "virtual memory
exhausted" error when it tries to allocate 15 bazillon bytes
of space for the 15 bazillon byte table it is about to read.
This function at least allows us to answer the question, "is the
size reasonable?".
*/
file_ptr
bfd_get_size (bfd *abfd)
{
struct stat buf;
if (abfd->iovec == NULL)
return 0;
if (abfd->iovec->bstat (abfd, &buf) != 0)
return 0;
return buf.st_size;
}
/*
FUNCTION
bfd_mmap
SYNOPSIS
void *bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
int prot, int flags, file_ptr offset,
void **map_addr, bfd_size_type *map_len);
DESCRIPTION
Return mmap()ed region of the file, if possible and implemented.
LEN and OFFSET do not need to be page aligned. The page aligned
address and length are written to MAP_ADDR and MAP_LEN.
*/
void *
bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
int prot, int flags, file_ptr offset,
void **map_addr, bfd_size_type *map_len)
{
void *ret = (void *)-1;
if (abfd->iovec == NULL)
return ret;
return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset,
map_addr, map_len);
}
/* Memory file I/O operations. */
static file_ptr
memory_bread (bfd *abfd, void *ptr, file_ptr size)
{
struct bfd_in_memory *bim;
bfd_size_type get;
bim = (struct bfd_in_memory *) abfd->iostream;
get = size;
if (abfd->where + get > bim->size)
{
if (bim->size < (bfd_size_type) abfd->where)
get = 0;
else
get = bim->size - abfd->where;
bfd_set_error (bfd_error_file_truncated);
}
memcpy (ptr, bim->buffer + abfd->where, (size_t) get);
return get;
}
static file_ptr
memory_bwrite (bfd *abfd, const void *ptr, file_ptr size)
{
struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
if (abfd->where + size > bim->size)
{
bfd_size_type newsize, oldsize;
oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
bim->size = abfd->where + size;
/* Round up to cut down on memory fragmentation */
newsize = (bim->size + 127) & ~(bfd_size_type) 127;
if (newsize > oldsize)
{
bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
if (bim->buffer == NULL)
{
bim->size = 0;
return 0;
}
if (newsize > bim->size)
memset (bim->buffer + bim->size, 0, newsize - bim->size);
}
}
memcpy (bim->buffer + abfd->where, ptr, (size_t) size);
return size;
}
static file_ptr
memory_btell (bfd *abfd)
{
return abfd->where;
}
static int
memory_bseek (bfd *abfd, file_ptr position, int direction)
{
file_ptr nwhere;
struct bfd_in_memory *bim;
bim = (struct bfd_in_memory *) abfd->iostream;
if (direction == SEEK_SET)
nwhere = position;
else
nwhere = abfd->where + position;
if (nwhere < 0)
{
abfd->where = 0;
errno = EINVAL;
return -1;
}
if ((bfd_size_type)nwhere > bim->size)
{
if (abfd->direction == write_direction
|| abfd->direction == both_direction)
{
bfd_size_type newsize, oldsize;
oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
bim->size = nwhere;
/* Round up to cut down on memory fragmentation */
newsize = (bim->size + 127) & ~(bfd_size_type) 127;
if (newsize > oldsize)
{
bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
if (bim->buffer == NULL)
{
errno = EINVAL;
bim->size = 0;
return -1;
}
memset (bim->buffer + oldsize, 0, newsize - oldsize);
}
}
else
{
abfd->where = bim->size;
errno = EINVAL;
bfd_set_error (bfd_error_file_truncated);
return -1;
}
}
return 0;
}
static int
memory_bclose (struct bfd *abfd)
{
struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
if (bim->buffer != NULL)
free (bim->buffer);
free (bim);
abfd->iostream = NULL;
return 0;
}
static int
memory_bflush (bfd *abfd ATTRIBUTE_UNUSED)
{
return 0;
}
static int
memory_bstat (bfd *abfd, struct stat *statbuf)
{
struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
memset (statbuf, 0, sizeof (*statbuf));
statbuf->st_size = bim->size;
return 0;
}
static void *
memory_bmmap (bfd *abfd ATTRIBUTE_UNUSED, void *addr ATTRIBUTE_UNUSED,
bfd_size_type len ATTRIBUTE_UNUSED, int prot ATTRIBUTE_UNUSED,
int flags ATTRIBUTE_UNUSED, file_ptr offset ATTRIBUTE_UNUSED,
void **map_addr ATTRIBUTE_UNUSED,
bfd_size_type *map_len ATTRIBUTE_UNUSED)
{
return (void *)-1;
}
const struct bfd_iovec _bfd_memory_iovec =
{
&memory_bread, &memory_bwrite, &memory_btell, &memory_bseek,
&memory_bclose, &memory_bflush, &memory_bstat, &memory_bmmap
};

View File

@@ -0,0 +1,4 @@
#define BFD_VERSION_DATE 20131202
#define BFD_VERSION 224000000
#define BFD_VERSION_STRING "(GNU Binutils) " "2.24"
#define REPORT_BUGS_TO "<http://www.sourceware.org/bugzilla/>"

View File

@@ -0,0 +1,369 @@
/* BFD back-end for binary objects.
Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
2004, 2005, 2006, 2007, 2009, 2011 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>
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. */
/* This is a BFD backend which may be used to write binary objects.
It may only be used for output, not input. The intention is that
this may be used as an output format for objcopy in order to
generate raw binary data.
This is very simple. The only complication is that the real data
will start at some address X, and in some cases we will not want to
include X zeroes just to get to that point. Since the start
address is not meaningful for this object file format, we use it
instead to indicate the number of zeroes to skip at the start of
the file. objcopy cooperates by specially setting the start
address to zero by default. */
#include "sysdep.h"
#include "bfd.h"
#include "safe-ctype.h"
#include "libbfd.h"
/* Any bfd we create by reading a binary file has three symbols:
a start symbol, an end symbol, and an absolute length symbol. */
#define BIN_SYMS 3
/* Create a binary object. Invoked via bfd_set_format. */
static bfd_boolean
binary_mkobject (bfd *abfd ATTRIBUTE_UNUSED)
{
return TRUE;
}
/* Any file may be considered to be a binary file, provided the target
was not defaulted. That is, it must be explicitly specified as
being binary. */
static const bfd_target *
binary_object_p (bfd *abfd)
{
struct stat statbuf;
asection *sec;
flagword flags;
if (abfd->target_defaulted)
{
bfd_set_error (bfd_error_wrong_format);
return NULL;
}
abfd->symcount = BIN_SYMS;
/* Find the file size. */
if (bfd_stat (abfd, &statbuf) < 0)
{
bfd_set_error (bfd_error_system_call);
return NULL;
}
/* One data section. */
flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS;
sec = bfd_make_section_with_flags (abfd, ".data", flags);
if (sec == NULL)
return NULL;
sec->vma = 0;
sec->size = statbuf.st_size;
sec->filepos = 0;
abfd->tdata.any = (void *) sec;
return abfd->xvec;
}
#define binary_close_and_cleanup _bfd_generic_close_and_cleanup
#define binary_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
#define binary_new_section_hook _bfd_generic_new_section_hook
/* Get contents of the only section. */
static bfd_boolean
binary_get_section_contents (bfd *abfd,
asection *section ATTRIBUTE_UNUSED,
void * location,
file_ptr offset,
bfd_size_type count)
{
if (bfd_seek (abfd, offset, SEEK_SET) != 0
|| bfd_bread (location, count, abfd) != count)
return FALSE;
return TRUE;
}
/* Return the amount of memory needed to read the symbol table. */
static long
binary_get_symtab_upper_bound (bfd *abfd ATTRIBUTE_UNUSED)
{
return (BIN_SYMS + 1) * sizeof (asymbol *);
}
/* Create a symbol name based on the bfd's filename. */
static char *
mangle_name (bfd *abfd, char *suffix)
{
bfd_size_type size;
char *buf;
char *p;
size = (strlen (bfd_get_filename (abfd))
+ strlen (suffix)
+ sizeof "_binary__");
buf = (char *) bfd_alloc (abfd, size);
if (buf == NULL)
return "";
sprintf (buf, "_binary_%s_%s", bfd_get_filename (abfd), suffix);
/* Change any non-alphanumeric characters to underscores. */
for (p = buf; *p; p++)
if (! ISALNUM (*p))
*p = '_';
return buf;
}
/* Return the symbol table. */
static long
binary_canonicalize_symtab (bfd *abfd, asymbol **alocation)
{
asection *sec = (asection *) abfd->tdata.any;
asymbol *syms;
unsigned int i;
bfd_size_type amt = BIN_SYMS * sizeof (asymbol);
syms = (asymbol *) bfd_alloc (abfd, amt);
if (syms == NULL)
return -1;
/* Start symbol. */
syms[0].the_bfd = abfd;
syms[0].name = mangle_name (abfd, "start");
syms[0].value = 0;
syms[0].flags = BSF_GLOBAL;
syms[0].section = sec;
syms[0].udata.p = NULL;
/* End symbol. */
syms[1].the_bfd = abfd;
syms[1].name = mangle_name (abfd, "end");
syms[1].value = sec->size;
syms[1].flags = BSF_GLOBAL;
syms[1].section = sec;
syms[1].udata.p = NULL;
/* Size symbol. */
syms[2].the_bfd = abfd;
syms[2].name = mangle_name (abfd, "size");
syms[2].value = sec->size;
syms[2].flags = BSF_GLOBAL;
syms[2].section = bfd_abs_section_ptr;
syms[2].udata.p = NULL;
for (i = 0; i < BIN_SYMS; i++)
*alocation++ = syms++;
*alocation = NULL;
return BIN_SYMS;
}
#define binary_make_empty_symbol _bfd_generic_make_empty_symbol
#define binary_print_symbol _bfd_nosymbols_print_symbol
/* Get information about a symbol. */
static void
binary_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
asymbol *symbol,
symbol_info *ret)
{
bfd_symbol_info (symbol, ret);
}
#define binary_bfd_is_local_label_name bfd_generic_is_local_label_name
#define binary_get_lineno _bfd_nosymbols_get_lineno
#define binary_find_nearest_line _bfd_nosymbols_find_nearest_line
#define binary_find_inliner_info _bfd_nosymbols_find_inliner_info
#define binary_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
#define binary_read_minisymbols _bfd_generic_read_minisymbols
#define binary_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
#define binary_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
/* Set the architecture of a binary file. */
#define binary_set_arch_mach _bfd_generic_set_arch_mach
/* Write section contents of a binary file. */
static bfd_boolean
binary_set_section_contents (bfd *abfd,
asection *sec,
const void * data,
file_ptr offset,
bfd_size_type size)
{
if (size == 0)
return TRUE;
if (! abfd->output_has_begun)
{
bfd_boolean found_low;
bfd_vma low;
asection *s;
/* The lowest section LMA sets the virtual address of the start
of the file. We use this to set the file position of all the
sections. */
found_low = FALSE;
low = 0;
for (s = abfd->sections; s != NULL; s = s->next)
if (((s->flags
& (SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_NEVER_LOAD))
== (SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC))
&& (s->size > 0)
&& (! found_low || s->lma < low))
{
low = s->lma;
found_low = TRUE;
}
for (s = abfd->sections; s != NULL; s = s->next)
{
s->filepos = s->lma - low;
/* Skip following warning check for sections that will not
occupy file space. */
if ((s->flags
& (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_NEVER_LOAD))
!= (SEC_HAS_CONTENTS | SEC_ALLOC)
|| (s->size == 0))
continue;
/* If attempting to generate a binary file from a bfd with
LMA's all over the place, huge (sparse?) binary files may
result. This condition attempts to detect this situation
and print a warning. Better heuristics would be nice to
have. */
if (s->filepos < 0)
(*_bfd_error_handler)
(_("Warning: Writing section `%s' to huge (ie negative) file offset 0x%lx."),
bfd_get_section_name (abfd, s),
(unsigned long) s->filepos);
}
abfd->output_has_begun = TRUE;
}
/* We don't want to output anything for a section that is neither
loaded nor allocated. The contents of such a section are not
meaningful in the binary format. */
if ((sec->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
return TRUE;
if ((sec->flags & SEC_NEVER_LOAD) != 0)
return TRUE;
return _bfd_generic_set_section_contents (abfd, sec, data, offset, size);
}
/* No space is required for header information. */
static int
binary_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
struct bfd_link_info *info ATTRIBUTE_UNUSED)
{
return 0;
}
#define binary_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
#define binary_bfd_relax_section bfd_generic_relax_section
#define binary_bfd_gc_sections bfd_generic_gc_sections
#define binary_bfd_lookup_section_flags bfd_generic_lookup_section_flags
#define binary_bfd_merge_sections bfd_generic_merge_sections
#define binary_bfd_is_group_section bfd_generic_is_group_section
#define binary_bfd_discard_group bfd_generic_discard_group
#define binary_section_already_linked _bfd_generic_section_already_linked
#define binary_bfd_define_common_symbol bfd_generic_define_common_symbol
#define binary_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define binary_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
#define binary_bfd_link_just_syms _bfd_generic_link_just_syms
#define binary_bfd_copy_link_hash_symbol_type \
_bfd_generic_copy_link_hash_symbol_type
#define binary_bfd_link_add_symbols _bfd_generic_link_add_symbols
#define binary_bfd_final_link _bfd_generic_final_link
#define binary_bfd_link_split_section _bfd_generic_link_split_section
#define binary_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
const bfd_target binary_vec =
{
"binary", /* name */
bfd_target_unknown_flavour, /* flavour */
BFD_ENDIAN_UNKNOWN, /* byteorder */
BFD_ENDIAN_UNKNOWN, /* header_byteorder */
EXEC_P, /* object_flags */
(SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
| SEC_ROM | SEC_HAS_CONTENTS), /* section_flags */
0, /* symbol_leading_char */
' ', /* ar_pad_char */
16, /* ar_max_namelen */
255, /* match priority. */
bfd_getb64, bfd_getb_signed_64, bfd_putb64,
bfd_getb32, bfd_getb_signed_32, bfd_putb32,
bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
bfd_getb64, bfd_getb_signed_64, bfd_putb64,
bfd_getb32, bfd_getb_signed_32, bfd_putb32,
bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
{ /* bfd_check_format */
_bfd_dummy_target,
binary_object_p,
_bfd_dummy_target,
_bfd_dummy_target,
},
{ /* bfd_set_format */
bfd_false,
binary_mkobject,
bfd_false,
bfd_false,
},
{ /* bfd_write_contents */
bfd_false,
bfd_true,
bfd_false,
bfd_false,
},
BFD_JUMP_TABLE_GENERIC (binary),
BFD_JUMP_TABLE_COPY (_bfd_generic),
BFD_JUMP_TABLE_CORE (_bfd_nocore),
BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
BFD_JUMP_TABLE_SYMBOLS (binary),
BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
BFD_JUMP_TABLE_WRITE (binary),
BFD_JUMP_TABLE_LINK (binary),
BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
NULL,
NULL
};

View File

@@ -0,0 +1,645 @@
/* BFD library -- caching of file descriptors.
Copyright 1990, 1991, 1992, 1993, 1994, 1996, 2000, 2001, 2002,
2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
Hacked by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
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. */
/*
SECTION
File caching
The file caching mechanism is embedded within BFD and allows
the application to open as many BFDs as it wants without
regard to the underlying operating system's file descriptor
limit (often as low as 20 open files). The module in
<<cache.c>> maintains a least recently used list of
<<bfd_cache_max_open>> files, and exports the name
<<bfd_cache_lookup>>, which runs around and makes sure that
the required BFD is open. If not, then it chooses a file to
close, closes it and opens the one wanted, returning its file
handle.
SUBSECTION
Caching functions
*/
#include "sysdep.h"
#include "bfd.h"
#include "libbfd.h"
#include "libiberty.h"
#include "bfd_stdint.h"
#ifdef HAVE_MMAP
#include <sys/mman.h>
#endif
/* In some cases we can optimize cache operation when reopening files.
For instance, a flush is entirely unnecessary if the file is already
closed, so a flush would use CACHE_NO_OPEN. Similarly, a seek using
SEEK_SET or SEEK_END need not first seek to the current position.
For stat we ignore seek errors, just in case the file has changed
while we weren't looking. If it has, then it's possible that the
file is shorter and we don't want a seek error to prevent us doing
the stat. */
enum cache_flag {
CACHE_NORMAL = 0,
CACHE_NO_OPEN = 1,
CACHE_NO_SEEK = 2,
CACHE_NO_SEEK_ERROR = 4
};
/* The maximum number of files which the cache will keep open at
one time. When needed call bfd_cache_max_open to initialize. */
static int max_open_files = 0;
/* Set max_open_files, if not already set, to 12.5% of the allowed open
file descriptors, but at least 10, and return the value. */
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;
}
return max_open_files;
}
/* The number of BFD files we have open. */
static int open_files;
/* Zero, or a pointer to the topmost BFD on the chain. This is
used by the <<bfd_cache_lookup>> macro in @file{libbfd.h} to
determine when it can avoid a function call. */
static bfd *bfd_last_cache = NULL;
/* Insert a BFD into the cache. */
static void
insert (bfd *abfd)
{
if (bfd_last_cache == NULL)
{
abfd->lru_next = abfd;
abfd->lru_prev = abfd;
}
else
{
abfd->lru_next = bfd_last_cache;
abfd->lru_prev = bfd_last_cache->lru_prev;
abfd->lru_prev->lru_next = abfd;
abfd->lru_next->lru_prev = abfd;
}
bfd_last_cache = abfd;
}
/* Remove a BFD from the cache. */
static void
snip (bfd *abfd)
{
abfd->lru_prev->lru_next = abfd->lru_next;
abfd->lru_next->lru_prev = abfd->lru_prev;
if (abfd == bfd_last_cache)
{
bfd_last_cache = abfd->lru_next;
if (abfd == bfd_last_cache)
bfd_last_cache = NULL;
}
}
/* Close a BFD and remove it from the cache. */
static bfd_boolean
bfd_cache_delete (bfd *abfd)
{
bfd_boolean ret;
if (fclose ((FILE *) abfd->iostream) == 0)
ret = TRUE;
else
{
ret = FALSE;
bfd_set_error (bfd_error_system_call);
}
snip (abfd);
abfd->iostream = NULL;
--open_files;
return ret;
}
/* We need to open a new file, and the cache is full. Find the least
recently used cacheable BFD and close it. */
static bfd_boolean
close_one (void)
{
register bfd *to_kill;
if (bfd_last_cache == NULL)
to_kill = NULL;
else
{
for (to_kill = bfd_last_cache->lru_prev;
! to_kill->cacheable;
to_kill = to_kill->lru_prev)
{
if (to_kill == bfd_last_cache)
{
to_kill = NULL;
break;
}
}
}
if (to_kill == NULL)
{
/* There are no open cacheable BFD's. */
return TRUE;
}
to_kill->where = real_ftell ((FILE *) to_kill->iostream);
return bfd_cache_delete (to_kill);
}
/* Check to see if the required BFD is the same as the last one
looked up. If so, then it can use the stream in the BFD with
impunity, since it can't have changed since the last lookup;
otherwise, it has to perform the complicated lookup function. */
#define bfd_cache_lookup(x, flag) \
((x) == bfd_last_cache \
? (FILE *) (bfd_last_cache->iostream) \
: bfd_cache_lookup_worker (x, flag))
/* Called when the macro <<bfd_cache_lookup>> fails to find a
quick answer. Find a file descriptor for @var{abfd}. If
necessary, it open it. If there are already more than
<<bfd_cache_max_open>> files open, it tries to close one first, to
avoid running out of file descriptors. It will return NULL
if it is unable to (re)open the @var{abfd}. */
static FILE *
bfd_cache_lookup_worker (bfd *abfd, enum cache_flag flag)
{
bfd *orig_bfd = abfd;
if ((abfd->flags & BFD_IN_MEMORY) != 0)
abort ();
while (abfd->my_archive)
abfd = abfd->my_archive;
if (abfd->iostream != NULL)
{
/* Move the file to the start of the cache. */
if (abfd != bfd_last_cache)
{
snip (abfd);
insert (abfd);
}
return (FILE *) abfd->iostream;
}
if (flag & CACHE_NO_OPEN)
return NULL;
if (bfd_open_file (abfd) == NULL)
;
else if (!(flag & CACHE_NO_SEEK)
&& real_fseek ((FILE *) abfd->iostream, abfd->where, SEEK_SET) != 0
&& !(flag & CACHE_NO_SEEK_ERROR))
bfd_set_error (bfd_error_system_call);
else
return (FILE *) abfd->iostream;
(*_bfd_error_handler) (_("reopening %B: %s\n"),
orig_bfd, bfd_errmsg (bfd_get_error ()));
return NULL;
}
static file_ptr
cache_btell (struct bfd *abfd)
{
FILE *f = bfd_cache_lookup (abfd, CACHE_NO_OPEN);
if (f == NULL)
return abfd->where;
return real_ftell (f);
}
static int
cache_bseek (struct bfd *abfd, file_ptr offset, int whence)
{
FILE *f = bfd_cache_lookup (abfd, whence != SEEK_CUR ? CACHE_NO_SEEK : CACHE_NORMAL);
if (f == NULL)
return -1;
return real_fseek (f, offset, whence);
}
/* Note that archive entries don't have streams; they share their parent's.
This allows someone to play with the iostream behind BFD's back.
Also, note that the origin pointer points to the beginning of a file's
contents (0 for non-archive elements). For archive entries this is the
first octet in the file, NOT the beginning of the archive header. */
static file_ptr
cache_bread_1 (struct bfd *abfd, void *buf, file_ptr nbytes)
{
FILE *f;
file_ptr nread;
/* FIXME - this looks like an optimization, but it's really to cover
up for a feature of some OSs (not solaris - sigh) that
ld/pe-dll.c takes advantage of (apparently) when it creates BFDs
internally and tries to link against them. BFD seems to be smart
enough to realize there are no symbol records in the "file" that
doesn't exist but attempts to read them anyway. On Solaris,
attempting to read zero bytes from a NULL file results in a core
dump, but on other platforms it just returns zero bytes read.
This makes it to something reasonable. - DJ */
if (nbytes == 0)
return 0;
f = bfd_cache_lookup (abfd, CACHE_NORMAL);
if (f == NULL)
return 0;
#if defined (__VAX) && defined (VMS)
/* Apparently fread on Vax VMS does not keep the record length
information. */
nread = read (fileno (f), buf, nbytes);
/* Set bfd_error if we did not read as much data as we expected. If
the read failed due to an error set the bfd_error_system_call,
else set bfd_error_file_truncated. */
if (nread == (file_ptr)-1)
{
bfd_set_error (bfd_error_system_call);
return -1;
}
#else
nread = fread (buf, 1, nbytes, f);
/* Set bfd_error if we did not read as much data as we expected. If
the read failed due to an error set the bfd_error_system_call,
else set bfd_error_file_truncated. */
if (nread < nbytes && ferror (f))
{
bfd_set_error (bfd_error_system_call);
return -1;
}
#endif
if (nread < nbytes)
/* This may or may not be an error, but in case the calling code
bails out because of it, set the right error code. */
bfd_set_error (bfd_error_file_truncated);
return nread;
}
static file_ptr
cache_bread (struct bfd *abfd, void *buf, file_ptr nbytes)
{
file_ptr nread = 0;
/* Some filesystems are unable to handle reads that are too large
(for instance, NetApp shares with oplocks turned off). To avoid
hitting this limitation, we read the buffer in chunks of 8MB max. */
while (nread < nbytes)
{
const file_ptr max_chunk_size = 0x800000;
file_ptr chunk_size = nbytes - nread;
file_ptr chunk_nread;
if (chunk_size > max_chunk_size)
chunk_size = max_chunk_size;
chunk_nread = cache_bread_1 (abfd, (char *) buf + nread, chunk_size);
/* Update the nread count.
We just have to be careful of the case when cache_bread_1 returns
a negative count: If this is our first read, then set nread to
that negative count in order to return that negative value to the
caller. Otherwise, don't add it to our total count, or we would
end up returning a smaller number of bytes read than we actually
did. */
if (nread == 0 || chunk_nread > 0)
nread += chunk_nread;
if (chunk_nread < chunk_size)
break;
}
return nread;
}
static file_ptr
cache_bwrite (struct bfd *abfd, const void *where, file_ptr nbytes)
{
file_ptr nwrite;
FILE *f = bfd_cache_lookup (abfd, CACHE_NORMAL);
if (f == NULL)
return 0;
nwrite = fwrite (where, 1, nbytes, f);
if (nwrite < nbytes && ferror (f))
{
bfd_set_error (bfd_error_system_call);
return -1;
}
return nwrite;
}
static int
cache_bclose (struct bfd *abfd)
{
return bfd_cache_close (abfd) - 1;
}
static int
cache_bflush (struct bfd *abfd)
{
int sts;
FILE *f = bfd_cache_lookup (abfd, CACHE_NO_OPEN);
if (f == NULL)
return 0;
sts = fflush (f);
if (sts < 0)
bfd_set_error (bfd_error_system_call);
return sts;
}
static int
cache_bstat (struct bfd *abfd, struct stat *sb)
{
int sts;
FILE *f = bfd_cache_lookup (abfd, CACHE_NO_SEEK_ERROR);
if (f == NULL)
return -1;
sts = fstat (fileno (f), sb);
if (sts < 0)
bfd_set_error (bfd_error_system_call);
return sts;
}
static void *
cache_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED,
void *addr ATTRIBUTE_UNUSED,
bfd_size_type len ATTRIBUTE_UNUSED,
int prot ATTRIBUTE_UNUSED,
int flags ATTRIBUTE_UNUSED,
file_ptr offset ATTRIBUTE_UNUSED,
void **map_addr ATTRIBUTE_UNUSED,
bfd_size_type *map_len ATTRIBUTE_UNUSED)
{
void *ret = (void *) -1;
if ((abfd->flags & BFD_IN_MEMORY) != 0)
abort ();
#ifdef HAVE_MMAP
else
{
static uintptr_t pagesize_m1;
FILE *f;
file_ptr pg_offset;
bfd_size_type pg_len;
f = bfd_cache_lookup (abfd, CACHE_NO_SEEK_ERROR);
if (f == NULL)
return ret;
if (pagesize_m1 == 0)
pagesize_m1 = getpagesize () - 1;
/* Handle archive members. */
if (abfd->my_archive != NULL)
offset += abfd->origin;
/* Align. */
pg_offset = offset & ~pagesize_m1;
pg_len = (len + (offset - pg_offset) + pagesize_m1) & ~pagesize_m1;
ret = mmap (addr, pg_len, prot, flags, fileno (f), pg_offset);
if (ret == (void *) -1)
bfd_set_error (bfd_error_system_call);
else
{
*map_addr = ret;
*map_len = pg_len;
ret = (char *) ret + (offset & pagesize_m1);
}
}
#endif
return ret;
}
static const struct bfd_iovec cache_iovec =
{
&cache_bread, &cache_bwrite, &cache_btell, &cache_bseek,
&cache_bclose, &cache_bflush, &cache_bstat, &cache_bmmap
};
/*
INTERNAL_FUNCTION
bfd_cache_init
SYNOPSIS
bfd_boolean bfd_cache_init (bfd *abfd);
DESCRIPTION
Add a newly opened BFD to the cache.
*/
bfd_boolean
bfd_cache_init (bfd *abfd)
{
BFD_ASSERT (abfd->iostream != NULL);
if (open_files >= bfd_cache_max_open ())
{
if (! close_one ())
return FALSE;
}
abfd->iovec = &cache_iovec;
insert (abfd);
++open_files;
return TRUE;
}
/*
INTERNAL_FUNCTION
bfd_cache_close
SYNOPSIS
bfd_boolean bfd_cache_close (bfd *abfd);
DESCRIPTION
Remove the BFD @var{abfd} from the cache. If the attached file is open,
then close it too.
RETURNS
<<FALSE>> is returned if closing the file fails, <<TRUE>> is
returned if all is well.
*/
bfd_boolean
bfd_cache_close (bfd *abfd)
{
if (abfd->iovec != &cache_iovec)
return TRUE;
if (abfd->iostream == NULL)
/* Previously closed. */
return TRUE;
return bfd_cache_delete (abfd);
}
/*
FUNCTION
bfd_cache_close_all
SYNOPSIS
bfd_boolean bfd_cache_close_all (void);
DESCRIPTION
Remove all BFDs from the cache. If the attached file is open,
then close it too.
RETURNS
<<FALSE>> is returned if closing one of the file fails, <<TRUE>> is
returned if all is well.
*/
bfd_boolean
bfd_cache_close_all ()
{
bfd_boolean ret = TRUE;
while (bfd_last_cache != NULL)
ret &= bfd_cache_close (bfd_last_cache);
return ret;
}
/*
INTERNAL_FUNCTION
bfd_open_file
SYNOPSIS
FILE* bfd_open_file (bfd *abfd);
DESCRIPTION
Call the OS to open a file for @var{abfd}. Return the <<FILE *>>
(possibly <<NULL>>) that results from this operation. Set up the
BFD so that future accesses know the file is open. If the <<FILE *>>
returned is <<NULL>>, then it won't have been put in the
cache, so it won't have to be removed from it.
*/
FILE *
bfd_open_file (bfd *abfd)
{
abfd->cacheable = TRUE; /* Allow it to be closed later. */
if (open_files >= bfd_cache_max_open ())
{
if (! close_one ())
return NULL;
}
switch (abfd->direction)
{
case read_direction:
case no_direction:
abfd->iostream = real_fopen (abfd->filename, FOPEN_RB);
break;
case both_direction:
case write_direction:
if (abfd->opened_once)
{
abfd->iostream = real_fopen (abfd->filename, FOPEN_RUB);
if (abfd->iostream == NULL)
abfd->iostream = real_fopen (abfd->filename, FOPEN_WUB);
}
else
{
/* Create the file.
Some operating systems won't let us overwrite a running
binary. For them, we want to unlink the file first.
However, gcc 2.95 will create temporary files using
O_EXCL and tight permissions to prevent other users from
substituting other .o files during the compilation. gcc
will then tell the assembler to use the newly created
file as an output file. If we unlink the file here, we
open a brief window when another user could still
substitute a file.
So we unlink the output file if and only if it has
non-zero size. */
#ifndef __MSDOS__
/* Don't do this for MSDOS: it doesn't care about overwriting
a running binary, but if this file is already open by
another BFD, we will be in deep trouble if we delete an
open file. In fact, objdump does just that if invoked with
the --info option. */
struct stat s;
if (stat (abfd->filename, &s) == 0 && s.st_size != 0)
unlink_if_ordinary (abfd->filename);
#endif
abfd->iostream = real_fopen (abfd->filename, FOPEN_WUB);
abfd->opened_once = TRUE;
}
break;
}
if (abfd->iostream == NULL)
bfd_set_error (bfd_error_system_call);
else
{
if (! bfd_cache_init (abfd))
return NULL;
}
return (FILE *) abfd->iostream;
}

View File

@@ -0,0 +1,681 @@
/* BFD back-end for Intel 386 COFF files.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
Written by Cygnus Support.
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"
#include "libbfd.h"
#include "coff/i386.h"
#include "coff/internal.h"
#ifdef COFF_WITH_PE
#include "coff/pe.h"
#endif
#ifdef COFF_GO32_EXE
#include "coff/go32exe.h"
#endif
#ifndef bfd_pe_print_pdata
#define bfd_pe_print_pdata NULL
#endif
#include "libcoff.h"
static reloc_howto_type *coff_i386_rtype_to_howto
(bfd *, asection *, struct internal_reloc *,
struct coff_link_hash_entry *, struct internal_syment *,
bfd_vma *);
static reloc_howto_type *coff_i386_reloc_type_lookup
(bfd *, bfd_reloc_code_real_type);
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
/* The page size is a guess based on ELF. */
#define COFF_PAGE_SIZE 0x1000
/* For some reason when using i386 COFF the value stored in the .text
section for a reference to a common symbol is the value itself plus
any desired offset. Ian Taylor, Cygnus Support. */
/* If we are producing relocatable output, we need to do some
adjustments to the object file that are not done by the
bfd_perform_relocation function. This function is called by every
reloc type to make any required adjustments. */
static bfd_reloc_status_type
coff_i386_reloc (bfd *abfd,
arelent *reloc_entry,
asymbol *symbol,
void * data,
asection *input_section ATTRIBUTE_UNUSED,
bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
{
symvalue diff;
#ifndef COFF_WITH_PE
if (output_bfd == (bfd *) NULL)
return bfd_reloc_continue;
#endif
if (bfd_is_com_section (symbol->section))
{
#ifndef COFF_WITH_PE
/* We are relocating a common symbol. The current value in the
object file is ORIG + OFFSET, where ORIG is the value of the
common symbol as seen by the object file when it was compiled
(this may be zero if the symbol was undefined) and OFFSET is
the offset into the common symbol (normally zero, but may be
non-zero when referring to a field in a common structure).
ORIG is the negative of reloc_entry->addend, which is set by
the CALC_ADDEND macro below. We want to replace the value in
the object file with NEW + OFFSET, where NEW is the value of
the common symbol which we are going to put in the final
object file. NEW is symbol->value. */
diff = symbol->value + reloc_entry->addend;
#else
/* In PE mode, we do not offset the common symbol. */
diff = reloc_entry->addend;
#endif
}
else
{
/* For some reason bfd_perform_relocation always effectively
ignores the addend for a COFF target when producing
relocatable output. This seems to be always wrong for 386
COFF, so we handle the addend here instead. */
#ifdef COFF_WITH_PE
if (output_bfd == (bfd *) NULL)
{
reloc_howto_type *howto = reloc_entry->howto;
/* Although PC relative relocations are very similar between
PE and non-PE formats, but they are off by 1 << howto->size
bytes. For the external relocation, PE is very different
from others. See md_apply_fix3 () in gas/config/tc-i386.c.
When we link PE and non-PE object files together to
generate a non-PE executable, we have to compensate it
here. */
if (howto->pc_relative && howto->pcrel_offset)
diff = -(1 << howto->size);
else if (symbol->flags & BSF_WEAK)
diff = reloc_entry->addend - symbol->value;
else
diff = -reloc_entry->addend;
}
else
#endif
diff = reloc_entry->addend;
}
#ifdef COFF_WITH_PE
/* FIXME: How should this case be handled? */
if (reloc_entry->howto->type == R_IMAGEBASE
&& output_bfd != NULL
&& bfd_get_flavour(output_bfd) == bfd_target_coff_flavour)
diff -= pe_data (output_bfd)->pe_opthdr.ImageBase;
#endif
#define DOIT(x) \
x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
if (diff != 0)
{
reloc_howto_type *howto = reloc_entry->howto;
unsigned char *addr = (unsigned char *) data + reloc_entry->address;
switch (howto->size)
{
case 0:
{
char x = bfd_get_8 (abfd, addr);
DOIT (x);
bfd_put_8 (abfd, x, addr);
}
break;
case 1:
{
short x = bfd_get_16 (abfd, addr);
DOIT (x);
bfd_put_16 (abfd, (bfd_vma) x, addr);
}
break;
case 2:
{
long x = bfd_get_32 (abfd, addr);
DOIT (x);
bfd_put_32 (abfd, (bfd_vma) x, addr);
}
break;
default:
abort ();
}
}
/* Now let bfd_perform_relocation finish everything up. */
return bfd_reloc_continue;
}
#ifdef COFF_WITH_PE
/* Return TRUE if this relocation should appear in the output .reloc
section. */
static bfd_boolean in_reloc_p (bfd * abfd ATTRIBUTE_UNUSED,
reloc_howto_type *howto)
{
return ! howto->pc_relative && howto->type != R_IMAGEBASE
&& howto->type != R_SECREL32;
}
#endif /* COFF_WITH_PE */
#ifndef PCRELOFFSET
#define PCRELOFFSET FALSE
#endif
static reloc_howto_type howto_table[] =
{
EMPTY_HOWTO (0),
EMPTY_HOWTO (1),
EMPTY_HOWTO (2),
EMPTY_HOWTO (3),
EMPTY_HOWTO (4),
EMPTY_HOWTO (5),
HOWTO (R_DIR32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
coff_i386_reloc, /* special_function */
"dir32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
/* PE IMAGE_REL_I386_DIR32NB relocation (7). */
HOWTO (R_IMAGEBASE, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
coff_i386_reloc, /* special_function */
"rva32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
EMPTY_HOWTO (010),
EMPTY_HOWTO (011),
EMPTY_HOWTO (012),
#ifdef COFF_WITH_PE
/* 32-bit longword section relative relocation (013). */
HOWTO (R_SECREL32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
coff_i386_reloc, /* special_function */
"secrel32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
#else
EMPTY_HOWTO (013),
#endif
EMPTY_HOWTO (014),
EMPTY_HOWTO (015),
EMPTY_HOWTO (016),
/* Byte relocation (017). */
HOWTO (R_RELBYTE, /* type */
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
8, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
coff_i386_reloc, /* special_function */
"8", /* name */
TRUE, /* partial_inplace */
0x000000ff, /* src_mask */
0x000000ff, /* dst_mask */
PCRELOFFSET), /* pcrel_offset */
/* 16-bit word relocation (020). */
HOWTO (R_RELWORD, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
coff_i386_reloc, /* special_function */
"16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
0x0000ffff, /* dst_mask */
PCRELOFFSET), /* pcrel_offset */
/* 32-bit longword relocation (021). */
HOWTO (R_RELLONG, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
coff_i386_reloc, /* special_function */
"32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
PCRELOFFSET), /* pcrel_offset */
/* Byte PC relative relocation (022). */
HOWTO (R_PCRBYTE, /* type */
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
8, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
coff_i386_reloc, /* special_function */
"DISP8", /* name */
TRUE, /* partial_inplace */
0x000000ff, /* src_mask */
0x000000ff, /* dst_mask */
PCRELOFFSET), /* pcrel_offset */
/* 16-bit word PC relative relocation (023). */
HOWTO (R_PCRWORD, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
coff_i386_reloc, /* special_function */
"DISP16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
0x0000ffff, /* dst_mask */
PCRELOFFSET), /* pcrel_offset */
/* 32-bit longword PC relative relocation (024). */
HOWTO (R_PCRLONG, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
coff_i386_reloc, /* special_function */
"DISP32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
PCRELOFFSET) /* pcrel_offset */
};
/* Turn a howto into a reloc nunmber */
#define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
#define BADMAG(x) I386BADMAG(x)
#define I386 1 /* Customize coffcode.h */
#define RTYPE2HOWTO(cache_ptr, dst) \
((cache_ptr)->howto = \
((dst)->r_type < sizeof (howto_table) / sizeof (howto_table[0]) \
? howto_table + (dst)->r_type \
: NULL))
/* For 386 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
library. On some other COFF targets STYP_BSS is normally
STYP_NOLOAD. */
#define BSS_NOLOAD_IS_SHARED_LIBRARY
/* Compute the addend of a reloc. If the reloc is to a common symbol,
the object file contains the value of the common symbol. By the
time this is called, the linker may be using a different symbol
from a different object file with a different value. Therefore, we
hack wildly to locate the original symbol from this file so that we
can make the correct adjustment. This macro sets coffsym to the
symbol from the original file, and uses it to set the addend value
correctly. If this is not a common symbol, the usual addend
calculation is done, except that an additional tweak is needed for
PC relative relocs.
FIXME: This macro refers to symbols and asect; these are from the
calling function, not the macro arguments. */
#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
{ \
coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
coffsym = (obj_symbols (abfd) \
+ (cache_ptr->sym_ptr_ptr - symbols)); \
else if (ptr) \
coffsym = coff_symbol_from (abfd, ptr); \
if (coffsym != (coff_symbol_type *) NULL \
&& coffsym->native->u.syment.n_scnum == 0) \
cache_ptr->addend = - coffsym->native->u.syment.n_value; \
else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
&& ptr->section != (asection *) NULL) \
cache_ptr->addend = - (ptr->section->vma + ptr->value); \
else \
cache_ptr->addend = 0; \
if (ptr && howto_table[reloc.r_type].pc_relative) \
cache_ptr->addend += asect->vma; \
}
/* We use the special COFF backend linker. For normal i386 COFF, we
can use the generic relocate_section routine. For PE, we need our
own routine. */
#ifndef COFF_WITH_PE
#define coff_relocate_section _bfd_coff_generic_relocate_section
#else /* COFF_WITH_PE */
/* The PE relocate section routine. The only difference between this
and the regular routine is that we don't want to do anything for a
relocatable link. */
static bfd_boolean
coff_pe_i386_relocate_section (bfd *output_bfd,
struct bfd_link_info *info,
bfd *input_bfd,
asection *input_section,
bfd_byte *contents,
struct internal_reloc *relocs,
struct internal_syment *syms,
asection **sections)
{
if (info->relocatable)
return TRUE;
return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
input_section, contents,
relocs, syms, sections);
}
#define coff_relocate_section coff_pe_i386_relocate_section
#endif /* COFF_WITH_PE */
/* Convert an rtype to howto for the COFF backend linker. */
static reloc_howto_type *
coff_i386_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
asection *sec,
struct internal_reloc *rel,
struct coff_link_hash_entry *h,
struct internal_syment *sym,
bfd_vma *addendp)
{
reloc_howto_type *howto;
if (rel->r_type >= sizeof (howto_table) / sizeof (howto_table[0]))
{
bfd_set_error (bfd_error_bad_value);
return NULL;
}
howto = howto_table + rel->r_type;
#ifdef COFF_WITH_PE
/* Cancel out code in _bfd_coff_generic_relocate_section. */
*addendp = 0;
#endif
if (howto->pc_relative)
*addendp += sec->vma;
if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
{
/* This is a common symbol. The section contents include the
size (sym->n_value) as an addend. The relocate_section
function will be adding in the final value of the symbol. We
need to subtract out the current size in order to get the
correct result. */
BFD_ASSERT (h != NULL);
#ifndef COFF_WITH_PE
/* I think we *do* want to bypass this. If we don't, I have
seen some data parameters get the wrong relocation address.
If I link two versions with and without this section bypassed
and then do a binary comparison, the addresses which are
different can be looked up in the map. The case in which
this section has been bypassed has addresses which correspond
to values I can find in the map. */
*addendp -= sym->n_value;
#endif
}
#ifndef COFF_WITH_PE
/* If the output symbol is common (in which case this must be a
relocatable link), we need to add in the final size of the
common symbol. */
if (h != NULL && h->root.type == bfd_link_hash_common)
*addendp += h->root.u.c.size;
#endif
#ifdef COFF_WITH_PE
if (howto->pc_relative)
{
*addendp -= 4;
/* If the symbol is defined, then the generic code is going to
add back the symbol value in order to cancel out an
adjustment it made to the addend. However, we set the addend
to 0 at the start of this function. We need to adjust here,
to avoid the adjustment the generic code will make. FIXME:
This is getting a bit hackish. */
if (sym != NULL && sym->n_scnum != 0)
*addendp -= sym->n_value;
}
if (rel->r_type == R_IMAGEBASE
&& (bfd_get_flavour(sec->output_section->owner)
== bfd_target_coff_flavour))
{
*addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
}
BFD_ASSERT (sym != NULL);
if (rel->r_type == R_SECREL32 && sym != NULL)
{
bfd_vma osect_vma;
if (h && (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak))
osect_vma = h->root.u.def.section->output_section->vma;
else
{
asection *s;
int i;
/* Sigh, the only way to get the section to offset against
is to find it the hard way. */
for (s = abfd->sections, i = 1; i < sym->n_scnum; i++)
s = s->next;
osect_vma = s->output_section->vma;
}
*addendp -= osect_vma;
}
#endif
return howto;
}
#define coff_bfd_reloc_type_lookup coff_i386_reloc_type_lookup
#define coff_bfd_reloc_name_lookup coff_i386_reloc_name_lookup
static reloc_howto_type *
coff_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
bfd_reloc_code_real_type code)
{
switch (code)
{
case BFD_RELOC_RVA:
return howto_table + R_IMAGEBASE;
case BFD_RELOC_32:
return howto_table + R_DIR32;
case BFD_RELOC_32_PCREL:
return howto_table + R_PCRLONG;
case BFD_RELOC_16:
return howto_table + R_RELWORD;
case BFD_RELOC_16_PCREL:
return howto_table + R_PCRWORD;
case BFD_RELOC_8:
return howto_table + R_RELBYTE;
case BFD_RELOC_8_PCREL:
return howto_table + R_PCRBYTE;
#ifdef COFF_WITH_PE
case BFD_RELOC_32_SECREL:
return howto_table + R_SECREL32;
#endif
default:
BFD_FAIL ();
return 0;
}
}
static reloc_howto_type *
coff_i386_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
const char *r_name)
{
unsigned int i;
for (i = 0; i < sizeof (howto_table) / sizeof (howto_table[0]); i++)
if (howto_table[i].name != NULL
&& strcasecmp (howto_table[i].name, r_name) == 0)
return &howto_table[i];
return NULL;
}
#define coff_rtype_to_howto coff_i386_rtype_to_howto
#ifdef TARGET_UNDERSCORE
/* If i386 gcc uses underscores for symbol names, then it does not use
a leading dot for local labels, so if TARGET_UNDERSCORE is defined
we treat all symbols starting with L as local. */
static bfd_boolean
coff_i386_is_local_label_name (bfd *abfd, const char *name)
{
if (name[0] == 'L')
return TRUE;
return _bfd_coff_is_local_label_name (abfd, name);
}
#define coff_bfd_is_local_label_name coff_i386_is_local_label_name
#endif /* TARGET_UNDERSCORE */
#include "coffcode.h"
#define _bfd_generic_find_nearest_line_discriminator \
coff_find_nearest_line_discriminator
const bfd_target
#ifdef TARGET_SYM
TARGET_SYM =
#else
i386coff_vec =
#endif
{
#ifdef TARGET_NAME
TARGET_NAME,
#else
"coff-i386", /* name */
#endif
bfd_target_coff_flavour,
BFD_ENDIAN_LITTLE, /* data byte order is little */
BFD_ENDIAN_LITTLE, /* header byte order is little */
(HAS_RELOC | EXEC_P | /* object flags */
HAS_LINENO | HAS_DEBUG |
HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS ),
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
#ifdef COFF_WITH_PE
| SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY | SEC_DEBUGGING
#endif
| SEC_CODE | SEC_DATA | SEC_EXCLUDE ),
#ifdef TARGET_UNDERSCORE
TARGET_UNDERSCORE, /* leading underscore */
#else
0, /* leading underscore */
#endif
'/', /* ar_pad_char */
15, /* ar_max_namelen */
0, /* match priority. */
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
/* Note that we allow an object file to be treated as a core file as well. */
/* bfd_check_format */
#ifdef COFF_CHECK_FORMAT
{_bfd_dummy_target, COFF_CHECK_FORMAT,
bfd_generic_archive_p, COFF_CHECK_FORMAT},
#else
{_bfd_dummy_target, coff_object_p, bfd_generic_archive_p, coff_object_p},
#endif
{bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
bfd_false},
{bfd_false, coff_write_object_contents, /* bfd_write_contents */
_bfd_write_archive_contents, bfd_false},
BFD_JUMP_TABLE_GENERIC (coff),
BFD_JUMP_TABLE_COPY (coff),
BFD_JUMP_TABLE_CORE (_bfd_nocore),
BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
BFD_JUMP_TABLE_SYMBOLS (coff),
BFD_JUMP_TABLE_RELOCS (coff),
BFD_JUMP_TABLE_WRITE (coff),
BFD_JUMP_TABLE_LINK (coff),
BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
NULL,
COFF_SWAP_TABLE
};

File diff suppressed because it is too large Load Diff

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,429 @@
/* Compressed section support (intended for debug sections).
Copyright 2008, 2010, 2011, 2012
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"
#include "libbfd.h"
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
#ifdef HAVE_ZLIB_H
static bfd_boolean
decompress_contents (bfd_byte *compressed_buffer,
bfd_size_type compressed_size,
bfd_byte *uncompressed_buffer,
bfd_size_type uncompressed_size)
{
z_stream strm;
int rc;
/* It is possible the section consists of several compressed
buffers concatenated together, so we uncompress in a loop. */
strm.zalloc = NULL;
strm.zfree = NULL;
strm.opaque = NULL;
strm.avail_in = compressed_size - 12;
strm.next_in = (Bytef*) compressed_buffer + 12;
strm.avail_out = uncompressed_size;
BFD_ASSERT (Z_OK == 0);
rc = inflateInit (&strm);
while (strm.avail_in > 0 && strm.avail_out > 0)
{
if (rc != Z_OK)
break;
strm.next_out = ((Bytef*) uncompressed_buffer
+ (uncompressed_size - strm.avail_out));
rc = inflate (&strm, Z_FINISH);
if (rc != Z_STREAM_END)
break;
rc = inflateReset (&strm);
}
rc |= inflateEnd (&strm);
return rc == Z_OK && strm.avail_out == 0;
}
#endif
/*
FUNCTION
bfd_compress_section_contents
SYNOPSIS
bfd_boolean bfd_compress_section_contents
(bfd *abfd, asection *section, bfd_byte *uncompressed_buffer,
bfd_size_type uncompressed_size);
DESCRIPTION
Compress data of the size specified in @var{uncompressed_size}
and pointed to by @var{uncompressed_buffer} using zlib and store
as the contents field. This function assumes the contents
field was allocated using bfd_malloc() or equivalent. If zlib
is not installed on this machine, the input is unmodified.
Return @code{TRUE} if the full section contents is compressed
successfully.
*/
bfd_boolean
bfd_compress_section_contents (bfd *abfd ATTRIBUTE_UNUSED,
sec_ptr sec ATTRIBUTE_UNUSED,
bfd_byte *uncompressed_buffer ATTRIBUTE_UNUSED,
bfd_size_type uncompressed_size ATTRIBUTE_UNUSED)
{
#ifndef HAVE_ZLIB_H
bfd_set_error (bfd_error_invalid_operation);
return FALSE;
#else
uLong compressed_size;
bfd_byte *compressed_buffer;
compressed_size = compressBound (uncompressed_size) + 12;
compressed_buffer = (bfd_byte *) bfd_malloc (compressed_size);
if (compressed_buffer == NULL)
return FALSE;
if (compress ((Bytef*) compressed_buffer + 12,
&compressed_size,
(const Bytef*) uncompressed_buffer,
uncompressed_size) != Z_OK)
{
free (compressed_buffer);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
/* Write the zlib header. In this case, it should be "ZLIB" followed
by the uncompressed section size, 8 bytes in big-endian order. */
memcpy (compressed_buffer, "ZLIB", 4);
compressed_buffer[11] = uncompressed_size; uncompressed_size >>= 8;
compressed_buffer[10] = uncompressed_size; uncompressed_size >>= 8;
compressed_buffer[9] = uncompressed_size; uncompressed_size >>= 8;
compressed_buffer[8] = uncompressed_size; uncompressed_size >>= 8;
compressed_buffer[7] = uncompressed_size; uncompressed_size >>= 8;
compressed_buffer[6] = uncompressed_size; uncompressed_size >>= 8;
compressed_buffer[5] = uncompressed_size; uncompressed_size >>= 8;
compressed_buffer[4] = uncompressed_size;
compressed_size += 12;
/* Free the uncompressed contents if we compress in place. */
if (uncompressed_buffer == sec->contents)
free (uncompressed_buffer);
sec->contents = compressed_buffer;
sec->size = compressed_size;
sec->compress_status = COMPRESS_SECTION_DONE;
return TRUE;
#endif /* HAVE_ZLIB_H */
}
/*
FUNCTION
bfd_get_full_section_contents
SYNOPSIS
bfd_boolean bfd_get_full_section_contents
(bfd *abfd, asection *section, bfd_byte **ptr);
DESCRIPTION
Read all data from @var{section} in BFD @var{abfd}, decompress
if needed, and store in @var{*ptr}. If @var{*ptr} is NULL,
return @var{*ptr} with memory malloc'd by this function.
Return @code{TRUE} if the full section contents is retrieved
successfully.
*/
bfd_boolean
bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
{
bfd_size_type sz;
bfd_byte *p = *ptr;
#ifdef HAVE_ZLIB_H
bfd_boolean ret;
bfd_size_type save_size;
bfd_size_type save_rawsize;
bfd_byte *compressed_buffer;
#endif
if (abfd->direction != write_direction && sec->rawsize != 0)
sz = sec->rawsize;
else
sz = sec->size;
if (sz == 0)
return TRUE;
switch (sec->compress_status)
{
case COMPRESS_SECTION_NONE:
if (p == NULL)
{
p = (bfd_byte *) bfd_malloc (sz);
if (p == NULL)
return FALSE;
}
if (!bfd_get_section_contents (abfd, sec, p, 0, sz))
{
if (*ptr != p)
free (p);
return FALSE;
}
*ptr = p;
return TRUE;
case DECOMPRESS_SECTION_SIZED:
#ifndef HAVE_ZLIB_H
bfd_set_error (bfd_error_invalid_operation);
return FALSE;
#else
/* Read in the full compressed section contents. */
compressed_buffer = (bfd_byte *) bfd_malloc (sec->compressed_size);
if (compressed_buffer == NULL)
return FALSE;
save_rawsize = sec->rawsize;
save_size = sec->size;
/* Clear rawsize, set size to compressed size and set compress_status
to COMPRESS_SECTION_NONE. If the compressed size is bigger than
the uncompressed size, bfd_get_section_contents will fail. */
sec->rawsize = 0;
sec->size = sec->compressed_size;
sec->compress_status = COMPRESS_SECTION_NONE;
ret = bfd_get_section_contents (abfd, sec, compressed_buffer,
0, sec->compressed_size);
/* Restore rawsize and size. */
sec->rawsize = save_rawsize;
sec->size = save_size;
sec->compress_status = DECOMPRESS_SECTION_SIZED;
if (!ret)
goto fail_compressed;
if (p == NULL)
p = (bfd_byte *) bfd_malloc (sz);
if (p == NULL)
goto fail_compressed;
if (!decompress_contents (compressed_buffer, sec->compressed_size, p, sz))
{
bfd_set_error (bfd_error_bad_value);
if (p != *ptr)
free (p);
fail_compressed:
free (compressed_buffer);
return FALSE;
}
free (compressed_buffer);
*ptr = p;
return TRUE;
#endif
case COMPRESS_SECTION_DONE:
if (p == NULL)
{
p = (bfd_byte *) bfd_malloc (sz);
if (p == NULL)
return FALSE;
*ptr = p;
}
memcpy (p, sec->contents, sz);
return TRUE;
default:
abort ();
}
}
/*
FUNCTION
bfd_cache_section_contents
SYNOPSIS
void bfd_cache_section_contents
(asection *sec, void *contents);
DESCRIPTION
Stash @var(contents) so any following reads of @var(sec) do
not need to decompress again.
*/
void
bfd_cache_section_contents (asection *sec, void *contents)
{
if (sec->compress_status == DECOMPRESS_SECTION_SIZED)
sec->compress_status = COMPRESS_SECTION_DONE;
sec->contents = contents;
sec->flags |= SEC_IN_MEMORY;
}
/*
FUNCTION
bfd_is_section_compressed
SYNOPSIS
bfd_boolean bfd_is_section_compressed
(bfd *abfd, asection *section);
DESCRIPTION
Return @code{TRUE} if @var{section} is compressed.
*/
bfd_boolean
bfd_is_section_compressed (bfd *abfd, sec_ptr sec)
{
bfd_byte compressed_buffer [12];
unsigned int saved = sec->compress_status;
bfd_boolean compressed;
/* Don't decompress the section. */
sec->compress_status = COMPRESS_SECTION_NONE;
/* Read the zlib header. In this case, it should be "ZLIB" followed
by the uncompressed section size, 8 bytes in big-endian order. */
compressed = (bfd_get_section_contents (abfd, sec, compressed_buffer, 0, 12)
&& CONST_STRNEQ ((char*) compressed_buffer, "ZLIB"));
/* Restore compress_status. */
sec->compress_status = saved;
return compressed;
}
/*
FUNCTION
bfd_init_section_decompress_status
SYNOPSIS
bfd_boolean bfd_init_section_decompress_status
(bfd *abfd, asection *section);
DESCRIPTION
Record compressed section size, update section size with
decompressed size and set compress_status to
DECOMPRESS_SECTION_SIZED.
Return @code{FALSE} if the section is not a valid compressed
section or zlib is not installed on this machine. Otherwise,
return @code{TRUE}.
*/
bfd_boolean
bfd_init_section_decompress_status (bfd *abfd ATTRIBUTE_UNUSED,
sec_ptr sec ATTRIBUTE_UNUSED)
{
#ifndef HAVE_ZLIB_H
bfd_set_error (bfd_error_invalid_operation);
return FALSE;
#else
bfd_byte compressed_buffer [12];
bfd_size_type uncompressed_size;
if (sec->rawsize != 0
|| sec->contents != NULL
|| sec->compress_status != COMPRESS_SECTION_NONE
|| !bfd_get_section_contents (abfd, sec, compressed_buffer, 0, 12))
{
bfd_set_error (bfd_error_invalid_operation);
return FALSE;
}
/* Read the zlib header. In this case, it should be "ZLIB" followed
by the uncompressed section size, 8 bytes in big-endian order. */
if (! CONST_STRNEQ ((char*) compressed_buffer, "ZLIB"))
{
bfd_set_error (bfd_error_wrong_format);
return FALSE;
}
uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8;
uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8;
uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8;
uncompressed_size += compressed_buffer[7]; uncompressed_size <<= 8;
uncompressed_size += compressed_buffer[8]; uncompressed_size <<= 8;
uncompressed_size += compressed_buffer[9]; uncompressed_size <<= 8;
uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8;
uncompressed_size += compressed_buffer[11];
sec->compressed_size = sec->size;
sec->size = uncompressed_size;
sec->compress_status = DECOMPRESS_SECTION_SIZED;
return TRUE;
#endif
}
/*
FUNCTION
bfd_init_section_compress_status
SYNOPSIS
bfd_boolean bfd_init_section_compress_status
(bfd *abfd, asection *section);
DESCRIPTION
If open for read, compress section, update section size with
compressed size and set compress_status to COMPRESS_SECTION_DONE.
Return @code{FALSE} if the section is not a valid compressed
section or zlib is not installed on this machine. Otherwise,
return @code{TRUE}.
*/
bfd_boolean
bfd_init_section_compress_status (bfd *abfd ATTRIBUTE_UNUSED,
sec_ptr sec ATTRIBUTE_UNUSED)
{
#ifndef HAVE_ZLIB_H
bfd_set_error (bfd_error_invalid_operation);
return FALSE;
#else
bfd_size_type uncompressed_size;
bfd_byte *uncompressed_buffer;
bfd_boolean ret;
/* Error if not opened for read. */
if (abfd->direction != read_direction
|| sec->size == 0
|| sec->rawsize != 0
|| sec->contents != NULL
|| sec->compress_status != COMPRESS_SECTION_NONE)
{
bfd_set_error (bfd_error_invalid_operation);
return FALSE;
}
/* Read in the full section contents and compress it. */
uncompressed_size = sec->size;
uncompressed_buffer = (bfd_byte *) bfd_malloc (uncompressed_size);
if (!bfd_get_section_contents (abfd, sec, uncompressed_buffer,
0, uncompressed_size))
ret = FALSE;
else
ret = bfd_compress_section_contents (abfd, sec,
uncompressed_buffer,
uncompressed_size);
free (uncompressed_buffer);
return ret;
#endif
}

View File

@@ -0,0 +1,380 @@
/* 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
/* Name of host specific core header file to include in elf.c. */
/* #undef CORE_HEADER */
/* Define to 1 if translation of program messages to the user's native
language is requested. */
/* #undef ENABLE_NLS */
/* Define to 1 if you have the <alloca.h> header file. */
/* #undef HAVE_ALLOCA_H */
/* Define to 1 if you have the declaration of `basename', and to 0 if you
don't. */
#define HAVE_DECL_BASENAME 0
/* Define to 1 if you have the declaration of `ffs', and to 0 if you don't. */
#define HAVE_DECL_FFS 0
/* 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 `fseeko', and to 0 if you don't.
*/
#define HAVE_DECL_FSEEKO 0
/* Define to 1 if you have the declaration of `fseeko64', and to 0 if you
don't. */
#define HAVE_DECL_FSEEKO64 0
/* Define to 1 if you have the declaration of `ftello', and to 0 if you don't.
*/
#define HAVE_DECL_FTELLO 0
/* Define to 1 if you have the declaration of `ftello64', and to 0 if you
don't. */
#define HAVE_DECL_FTELLO64 0
/* Define to 1 if you have the declaration of `getenv', and to 0 if you don't.
*/
#define HAVE_DECL_GETENV 1
/* Define to 1 if you have the declaration of `malloc', and to 0 if you don't.
*/
#define HAVE_DECL_MALLOC 1
/* Define to 1 if you have the declaration of `realloc', and to 0 if you
don't. */
#define HAVE_DECL_REALLOC 1
/* Define to 1 if you have the declaration of `snprintf', and to 0 if you
don't. */
#define HAVE_DECL_SNPRINTF 1
/* Define to 1 if you have the declaration of `stpcpy', and to 0 if you don't.
*/
#define HAVE_DECL_STPCPY 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 declaration of `vsnprintf', and to 0 if you
don't. */
#define HAVE_DECL_VSNPRINTF 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 <dlfcn.h> header file. */
/* #undef HAVE_DLFCN_H */
/* Define to 1 if you have the `fcntl' function. */
/* #undef HAVE_FCNTL */
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if you have the `fdopen' function. */
#define HAVE_FDOPEN 1
/* Define to 1 if you have the `fileno' function. */
#define HAVE_FILENO 1
/* Define to 1 if you have the `fopen64' function. */
//#define HAVE_FOPEN64 0
/* Define to 1 if you have the `fseeko' function. */
/* #undef HAVE_FSEEKO */
/* Define to 1 if you have the `fseeko64' function. */
//#define HAVE_FSEEKO64 0
/* Define to 1 if you have the `ftello' function. */
/* #undef HAVE_FTELLO */
/* Define to 1 if you have the `ftello64' function. */
//#define HAVE_FTELLO64 0
/* Define to 1 if you have the `getgid' function. */
/* #undef HAVE_GETGID */
/* Define to 1 if you have the `getpagesize' function. */
//#define HAVE_GETPAGESIZE 1
/* Define to 1 if you have the `getrlimit' function. */
/* #undef HAVE_GETRLIMIT */
/* Define to 1 if you have the `getuid' function. */
/* #undef HAVE_GETUID */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define if <sys/procfs.h> has lwpstatus_t. */
/* #undef HAVE_LWPSTATUS_T */
/* Define if <sys/procfs.h> has lwpstatus_t.pr_context. */
/* #undef HAVE_LWPSTATUS_T_PR_CONTEXT */
/* Define if <sys/procfs.h> has lwpstatus_t.pr_fpreg. */
/* #undef HAVE_LWPSTATUS_T_PR_FPREG */
/* Define if <sys/procfs.h> has lwpstatus_t.pr_reg. */
/* #undef HAVE_LWPSTATUS_T_PR_REG */
/* Define if <sys/procfs.h> has lwpxstatus_t. */
/* #undef HAVE_LWPXSTATUS_T */
/* Define to 1 if you have the `madvise' function. */
/* #undef HAVE_MADVISE */
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have a working `mmap' system call. */
/* #undef HAVE_MMAP */
/* Define to 1 if you have the `mprotect' function. */
//#define HAVE_MPROTECT 0
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
/* #undef HAVE_NDIR_H */
/* Define if <sys/procfs.h> has prpsinfo32_t. */
/* #undef HAVE_PRPSINFO32_T */
/* Define if <sys/procfs.h> has prpsinfo32_t.pr_pid. */
/* #undef HAVE_PRPSINFO32_T_PR_PID */
/* Define if <sys/procfs.h> has prpsinfo_t. */
/* #undef HAVE_PRPSINFO_T */
/* Define if <sys/procfs.h> has prpsinfo_t.pr_pid. */
/* #undef HAVE_PRPSINFO_T_PR_PID */
/* Define if <sys/procfs.h> has prstatus32_t. */
/* #undef HAVE_PRSTATUS32_T */
/* Define if <sys/procfs.h> has prstatus32_t.pr_who. */
/* #undef HAVE_PRSTATUS32_T_PR_WHO */
/* Define if <sys/procfs.h> has prstatus_t. */
/* #undef HAVE_PRSTATUS_T */
/* Define if <sys/procfs.h> has prstatus_t.pr_who. */
/* #undef HAVE_PRSTATUS_T_PR_WHO */
/* Define if <sys/procfs.h> has psinfo32_t. */
/* #undef HAVE_PSINFO32_T */
/* Define if <sys/procfs.h> has psinfo32_t.pr_pid. */
/* #undef HAVE_PSINFO32_T_PR_PID */
/* Define if <sys/procfs.h> has psinfo_t. */
/* #undef HAVE_PSINFO_T */
/* Define if <sys/procfs.h> has psinfo_t.pr_pid. */
/* #undef HAVE_PSINFO_T_PR_PID */
/* Define if <sys/procfs.h> has pstatus32_t. */
/* #undef HAVE_PSTATUS32_T */
/* Define if <sys/procfs.h> has pstatus_t. */
/* #undef HAVE_PSTATUS_T */
/* Define if <sys/procfs.h> has pxstatus_t. */
/* #undef HAVE_PXSTATUS_T */
/* Define to 1 if you have the `setitimer' function. */
/* #undef HAVE_SETITIMER */
/* Define to 1 if you have the <stddef.h> header file. */
#define HAVE_STDDEF_H 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 `strtoull' function. */
#define HAVE_STRTOULL 1
/* Define if struct core_dumpx has member c_impl */
/* #undef HAVE_ST_C_IMPL */
/* Define to 1 if you have the `sysconf' function. */
/* #undef HAVE_SYSCONF */
/* 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/procfs.h> header file. */
/* #undef HAVE_SYS_PROCFS_H */
/* Define to 1 if you have the <sys/resource.h> header file. */
/* #undef HAVE_SYS_RESOURCE_H */
/* 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 <time.h> header file. */
#define HAVE_TIME_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define if <sys/procfs.h> has win32_pstatus_t. */
/* #undef HAVE_WIN32_PSTATUS_T */
/* 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 "bfd"
/* 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 "bfd"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "bfd 2.24"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "bfd"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "2.24"
/* The size of `char', as computed by sizeof. */
/* #undef SIZEOF_CHAR */
/* The size of `int', as computed by sizeof. */
/* #undef SIZEOF_INT */
/* The size of `long', as computed by sizeof. */
#define SIZEOF_LONG 4
/* The size of `long long', as computed by sizeof. */
#define SIZEOF_LONG_LONG 8
/* The size of `off_t', as computed by sizeof. */
/* #undef SIZEOF_OFF_T */
/* The size of `short', as computed by sizeof. */
/* #undef SIZEOF_SHORT */
/* 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
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#define TIME_WITH_SYS_TIME 1
/* Name of host specific header file to include in trad-core.c. */
/* #undef TRAD_HEADER */
/* Use b modifier when opening binary files? */
#define USE_BINARY_FOPEN 1
/* Define if we should use leading underscore on 64 bit mingw targets */
/* #undef USE_MINGW64_LEADING_UNDERSCORES */
/* Use mmap if it's available? */
/* #undef USE_MMAP */
/* Define if we should default to creating read-only plt entries */
/* #undef USE_SECUREPLT */
/* Define if we may generate symbols with ELF's STT_COMMON type */
/* #undef USE_STT_COMMON */
/* 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"
/* 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,191 @@
/* Core file generic interface routines for BFD.
Copyright 1990, 1991, 1992, 1993, 1994, 2000, 2001, 2002, 2003, 2005,
2007 Free Software Foundation, Inc.
Written by Cygnus Support.
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. */
/*
SECTION
Core files
SUBSECTION
Core file functions
DESCRIPTION
These are functions pertaining to core files.
*/
#include "sysdep.h"
#include "bfd.h"
#include "libbfd.h"
/*
FUNCTION
bfd_core_file_failing_command
SYNOPSIS
const char *bfd_core_file_failing_command (bfd *abfd);
DESCRIPTION
Return a read-only string explaining which program was running
when it failed and produced the core file @var{abfd}.
*/
const char *
bfd_core_file_failing_command (bfd *abfd)
{
if (abfd->format != bfd_core)
{
bfd_set_error (bfd_error_invalid_operation);
return NULL;
}
return BFD_SEND (abfd, _core_file_failing_command, (abfd));
}
/*
FUNCTION
bfd_core_file_failing_signal
SYNOPSIS
int bfd_core_file_failing_signal (bfd *abfd);
DESCRIPTION
Returns the signal number which caused the core dump which
generated the file the BFD @var{abfd} is attached to.
*/
int
bfd_core_file_failing_signal (bfd *abfd)
{
if (abfd->format != bfd_core)
{
bfd_set_error (bfd_error_invalid_operation);
return 0;
}
return BFD_SEND (abfd, _core_file_failing_signal, (abfd));
}
/*
FUNCTION
bfd_core_file_pid
SYNOPSIS
int bfd_core_file_pid (bfd *abfd);
DESCRIPTION
Returns the PID of the process the core dump the BFD
@var{abfd} is attached to was generated from.
*/
int
bfd_core_file_pid (bfd *abfd)
{
if (abfd->format != bfd_core)
{
bfd_set_error (bfd_error_invalid_operation);
return 0;
}
return BFD_SEND (abfd, _core_file_pid, (abfd));
}
/*
FUNCTION
core_file_matches_executable_p
SYNOPSIS
bfd_boolean core_file_matches_executable_p
(bfd *core_bfd, bfd *exec_bfd);
DESCRIPTION
Return <<TRUE>> if the core file attached to @var{core_bfd}
was generated by a run of the executable file attached to
@var{exec_bfd}, <<FALSE>> otherwise.
*/
bfd_boolean
core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
{
if (core_bfd->format != bfd_core || exec_bfd->format != bfd_object)
{
bfd_set_error (bfd_error_wrong_format);
return FALSE;
}
return BFD_SEND (core_bfd, _core_file_matches_executable_p,
(core_bfd, exec_bfd));
}
/*
FUNCTION
generic_core_file_matches_executable_p
SYNOPSIS
bfd_boolean generic_core_file_matches_executable_p
(bfd *core_bfd, bfd *exec_bfd);
DESCRIPTION
Return TRUE if the core file attached to @var{core_bfd}
was generated by a run of the executable file attached
to @var{exec_bfd}. The match is based on executable
basenames only.
Note: When not able to determine the core file failing
command or the executable name, we still return TRUE even
though we're not sure that core file and executable match.
This is to avoid generating a false warning in situations
where we really don't know whether they match or not.
*/
bfd_boolean
generic_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
{
char *exec;
char *core;
char *last_slash;
if (exec_bfd == NULL || core_bfd == NULL)
return TRUE;
/* The cast below is to avoid a compiler warning due to the assignment
of the const char * returned by bfd_core_file_failing_command to a
non-const char *. In this case, the assignement does not lead to
breaking the const, as we're only reading the string. */
core = (char *) bfd_core_file_failing_command (core_bfd);
if (core == NULL)
return TRUE;
exec = bfd_get_filename (exec_bfd);
if (exec == NULL)
return TRUE;
last_slash = strrchr (core, '/');
if (last_slash != NULL)
core = last_slash + 1;
last_slash = strrchr (exec, '/');
if (last_slash != NULL)
exec = last_slash + 1;
return filename_cmp (exec, core) == 0;
}

View File

@@ -0,0 +1,304 @@
/* BFD support for the Intel 386 architecture.
Copyright 1992, 1994, 1995, 1996, 1998, 2000, 2001, 2002, 2004, 2005,
2007, 2009, 2010, 2011, 2013
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"
#include "libbfd.h"
#include "libiberty.h"
extern void * bfd_arch_i386_short_nop_fill (bfd_size_type, bfd_boolean,
bfd_boolean);
static const bfd_arch_info_type *
bfd_i386_compatible (const bfd_arch_info_type *a,
const bfd_arch_info_type *b)
{
const bfd_arch_info_type *compat = bfd_default_compatible (a, b);
/* Don't allow mixing x64_32 with x86_64. */
if (compat
&& (a->mach & bfd_mach_x64_32) != (b->mach & bfd_mach_x64_32))
compat = NULL;
return compat;
}
/* Fill the buffer with zero or nop instruction if CODE is TRUE. Use
multi byte nop instructions if LONG_NOP is TRUE. */
static void *
bfd_arch_i386_fill (bfd_size_type count, bfd_boolean code,
bfd_boolean long_nop)
{
/* nop */
static const char nop_1[] = { 0x90 };
/* xchg %ax,%ax */
static const char nop_2[] = { 0x66, 0x90 };
/* nopl (%[re]ax) */
static const char nop_3[] = { 0x0f, 0x1f, 0x00 };
/* nopl 0(%[re]ax) */
static const char nop_4[] = { 0x0f, 0x1f, 0x40, 0x00 };
/* nopl 0(%[re]ax,%[re]ax,1) */
static const char nop_5[] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 };
/* nopw 0(%[re]ax,%[re]ax,1) */
static const char nop_6[] = { 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 };
/* nopl 0L(%[re]ax) */
static const char nop_7[] = { 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 };
/* nopl 0L(%[re]ax,%[re]ax,1) */
static const char nop_8[] =
{ 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00};
/* nopw 0L(%[re]ax,%[re]ax,1) */
static const char nop_9[] =
{ 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
/* nopw %cs:0L(%[re]ax,%[re]ax,1) */
static const char nop_10[] =
{ 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const char *const nops[] =
{ nop_1, nop_2, nop_3, nop_4, nop_5,
nop_6, nop_7, nop_8, nop_9, nop_10 };
bfd_size_type nop_size = long_nop ? ARRAY_SIZE (nops) : 2;
void *fill = bfd_malloc (count);
if (fill == NULL)
return fill;
if (code)
{
bfd_byte *p = fill;
while (count >= nop_size)
{
memcpy (p, nops[nop_size - 1], nop_size);
p += nop_size;
count -= nop_size;
}
if (count != 0)
memcpy (p, nops[count - 1], count);
}
else
memset (fill, 0, count);
return fill;
}
/* Fill the buffer with zero or short nop instruction if CODE is TRUE. */
void *
bfd_arch_i386_short_nop_fill (bfd_size_type count,
bfd_boolean is_bigendian ATTRIBUTE_UNUSED,
bfd_boolean code)
{
return bfd_arch_i386_fill (count, code, FALSE);
}
/* Fill the buffer with zero or long nop instruction if CODE is TRUE. */
static void *
bfd_arch_i386_long_nop_fill (bfd_size_type count,
bfd_boolean is_bigendian ATTRIBUTE_UNUSED,
bfd_boolean code)
{
return bfd_arch_i386_fill (count, code, TRUE);
}
/* Fill the buffer with zero, or one-byte nop instructions if CODE is TRUE. */
static void *
bfd_arch_i386_onebyte_nop_fill (bfd_size_type count,
bfd_boolean is_bigendian ATTRIBUTE_UNUSED,
bfd_boolean code)
{
void *fill = bfd_malloc (count);
if (fill != NULL)
memset (fill, code ? 0x90 : 0, count);
return fill;
}
static const bfd_arch_info_type bfd_x64_32_nacl_arch =
{
64, /* 64 bits in a word */
64, /* 64 bits in an address */
8, /* 8 bits in a byte */
bfd_arch_i386,
bfd_mach_x64_32_nacl,
"i386",
"i386:x64-32:nacl",
3,
FALSE,
bfd_i386_compatible,
bfd_default_scan,
bfd_arch_i386_onebyte_nop_fill,
NULL
};
static const bfd_arch_info_type bfd_x86_64_nacl_arch =
{
64, /* 64 bits in a word */
64, /* 64 bits in an address */
8, /* 8 bits in a byte */
bfd_arch_i386,
bfd_mach_x86_64_nacl,
"i386",
"i386:x86-64:nacl",
3,
FALSE,
bfd_i386_compatible,
bfd_default_scan,
bfd_arch_i386_onebyte_nop_fill,
&bfd_x64_32_nacl_arch
};
const bfd_arch_info_type bfd_i386_nacl_arch =
{
32, /* 32 bits in a word */
32, /* 32 bits in an address */
8, /* 8 bits in a byte */
bfd_arch_i386,
bfd_mach_i386_i386_nacl,
"i386",
"i386:nacl",
3,
TRUE,
bfd_i386_compatible,
bfd_default_scan,
bfd_arch_i386_onebyte_nop_fill,
&bfd_x86_64_nacl_arch
};
static const bfd_arch_info_type bfd_x64_32_arch_intel_syntax =
{
64, /* 64 bits in a word */
64, /* 64 bits in an address */
8, /* 8 bits in a byte */
bfd_arch_i386,
bfd_mach_x64_32_intel_syntax,
"i386:intel",
"i386:x64-32:intel",
3,
FALSE,
bfd_i386_compatible,
bfd_default_scan,
bfd_arch_i386_long_nop_fill,
&bfd_i386_nacl_arch
};
static const bfd_arch_info_type bfd_x86_64_arch_intel_syntax =
{
64, /* 64 bits in a word */
64, /* 64 bits in an address */
8, /* 8 bits in a byte */
bfd_arch_i386,
bfd_mach_x86_64_intel_syntax,
"i386:intel",
"i386:x86-64:intel",
3,
FALSE,
bfd_i386_compatible,
bfd_default_scan,
bfd_arch_i386_long_nop_fill,
&bfd_x64_32_arch_intel_syntax,
};
static const bfd_arch_info_type bfd_i386_arch_intel_syntax =
{
32, /* 32 bits in a word */
32, /* 32 bits in an address */
8, /* 8 bits in a byte */
bfd_arch_i386,
bfd_mach_i386_i386_intel_syntax,
"i386:intel",
"i386:intel",
3,
TRUE,
bfd_i386_compatible,
bfd_default_scan,
bfd_arch_i386_short_nop_fill,
&bfd_x86_64_arch_intel_syntax
};
static const bfd_arch_info_type i8086_arch =
{
32, /* 32 bits in a word */
32, /* 32 bits in an address (well, not really) */
8, /* 8 bits in a byte */
bfd_arch_i386,
bfd_mach_i386_i8086,
"i8086",
"i8086",
3,
FALSE,
bfd_i386_compatible,
bfd_default_scan,
bfd_arch_i386_short_nop_fill,
&bfd_i386_arch_intel_syntax
};
static const bfd_arch_info_type bfd_x64_32_arch =
{
64, /* 64 bits in a word */
64, /* 64 bits in an address */
8, /* 8 bits in a byte */
bfd_arch_i386,
bfd_mach_x64_32,
"i386",
"i386:x64-32",
3,
FALSE,
bfd_i386_compatible,
bfd_default_scan,
bfd_arch_i386_long_nop_fill,
&i8086_arch
};
static const bfd_arch_info_type bfd_x86_64_arch =
{
64, /* 64 bits in a word */
64, /* 64 bits in an address */
8, /* 8 bits in a byte */
bfd_arch_i386,
bfd_mach_x86_64,
"i386",
"i386:x86-64",
3,
FALSE,
bfd_i386_compatible,
bfd_default_scan,
bfd_arch_i386_long_nop_fill,
&bfd_x64_32_arch
};
const bfd_arch_info_type bfd_i386_arch =
{
32, /* 32 bits in a word */
32, /* 32 bits in an address */
8, /* 8 bits in a byte */
bfd_arch_i386,
bfd_mach_i386_i386,
"i386",
"i386",
3,
TRUE,
bfd_i386_compatible,
bfd_default_scan,
bfd_arch_i386_short_nop_fill,
&bfd_x86_64_arch
};

View File

@@ -0,0 +1,564 @@
/* DWARF 1 find nearest line (_bfd_dwarf1_find_nearest_line).
Copyright 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Written by Gavin Romig-Koch of Cygnus Solutions (gavin@cygnus.com).
This file is part of BFD.
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 "libiberty.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf/dwarf.h"
/* dwarf1_debug is the starting point for all dwarf1 info. */
struct dwarf1_debug
{
/* The bfd we are working with. */
bfd* abfd;
/* Pointer to the symbol table. */
asymbol** syms;
/* List of already parsed compilation units. */
struct dwarf1_unit* lastUnit;
/* The buffer for the .debug section.
Zero indicates that the .debug section failed to load. */
bfd_byte *debug_section;
/* Pointer to the end of the .debug_info section memory buffer. */
bfd_byte *debug_section_end;
/* The buffer for the .line section. */
bfd_byte *line_section;
/* End of that buffer. */
bfd_byte *line_section_end;
/* The current or next unread die within the .debug section. */
bfd_byte *currentDie;
};
/* One dwarf1_unit for each parsed compilation unit die. */
struct dwarf1_unit
{
/* Linked starting from stash->lastUnit. */
struct dwarf1_unit* prev;
/* Name of the compilation unit. */
char *name;
/* The highest and lowest address used in the compilation unit. */
unsigned long low_pc;
unsigned long high_pc;
/* Does this unit have a statement list? */
int has_stmt_list;
/* If any, the offset of the line number table in the .line section. */
unsigned long stmt_list_offset;
/* If non-zero, a pointer to the first child of this unit. */
bfd_byte *first_child;
/* How many line entries? */
unsigned long line_count;
/* The decoded line number table (line_count entries). */
struct linenumber* linenumber_table;
/* The list of functions in this unit. */
struct dwarf1_func* func_list;
};
/* One dwarf1_func for each parsed function die. */
struct dwarf1_func
{
/* Linked starting from aUnit->func_list. */
struct dwarf1_func* prev;
/* Name of function. */
char* name;
/* The highest and lowest address used in the compilation unit. */
unsigned long low_pc;
unsigned long high_pc;
};
/* Used to return info about a parsed die. */
struct die_info
{
unsigned long length;
unsigned long sibling;
unsigned long low_pc;
unsigned long high_pc;
unsigned long stmt_list_offset;
char* name;
int has_stmt_list;
unsigned short tag;
};
/* Parsed line number information. */
struct linenumber
{
/* First address in the line. */
unsigned long addr;
/* The line number. */
unsigned long linenumber;
};
/* Find the form of an attr, from the attr field. */
#define FORM_FROM_ATTR(attr) ((attr) & 0xF) /* Implicitly specified. */
/* Return a newly allocated dwarf1_unit. It should be cleared and
then attached into the 'stash' at 'stash->lastUnit'. */
static struct dwarf1_unit*
alloc_dwarf1_unit (struct dwarf1_debug* stash)
{
bfd_size_type amt = sizeof (struct dwarf1_unit);
struct dwarf1_unit* x = (struct dwarf1_unit *) bfd_zalloc (stash->abfd, amt);
if (x)
{
x->prev = stash->lastUnit;
stash->lastUnit = x;
}
return x;
}
/* Return a newly allocated dwarf1_func. It must be cleared and
attached into 'aUnit' at 'aUnit->func_list'. */
static struct dwarf1_func *
alloc_dwarf1_func (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
{
bfd_size_type amt = sizeof (struct dwarf1_func);
struct dwarf1_func* x = (struct dwarf1_func *) bfd_zalloc (stash->abfd, amt);
if (x)
{
x->prev = aUnit->func_list;
aUnit->func_list = x;
}
return x;
}
/* parse_die - parse a Dwarf1 die.
Parse the die starting at 'aDiePtr' into 'aDieInfo'.
'abfd' must be the bfd from which the section that 'aDiePtr'
points to was pulled from.
Return FALSE if the die is invalidly formatted; TRUE otherwise. */
static bfd_boolean
parse_die (bfd * abfd,
struct die_info * aDieInfo,
bfd_byte * aDiePtr,
bfd_byte * aDiePtrEnd)
{
bfd_byte *this_die = aDiePtr;
bfd_byte *xptr = this_die;
memset (aDieInfo, 0, sizeof (* aDieInfo));
/* First comes the length. */
aDieInfo->length = bfd_get_32 (abfd, (bfd_byte *) xptr);
xptr += 4;
if (aDieInfo->length == 0
|| (this_die + aDieInfo->length) >= aDiePtrEnd)
return FALSE;
if (aDieInfo->length < 6)
{
/* Just padding bytes. */
aDieInfo->tag = TAG_padding;
return TRUE;
}
/* Then the tag. */
aDieInfo->tag = bfd_get_16 (abfd, (bfd_byte *) xptr);
xptr += 2;
/* Then the attributes. */
while (xptr < (this_die + aDieInfo->length))
{
unsigned short attr;
/* Parse the attribute based on its form. This section
must handle all dwarf1 forms, but need only handle the
actual attributes that we care about. */
attr = bfd_get_16 (abfd, (bfd_byte *) xptr);
xptr += 2;
switch (FORM_FROM_ATTR (attr))
{
case FORM_DATA2:
xptr += 2;
break;
case FORM_DATA4:
case FORM_REF:
if (attr == AT_sibling)
aDieInfo->sibling = bfd_get_32 (abfd, (bfd_byte *) xptr);
else if (attr == AT_stmt_list)
{
aDieInfo->stmt_list_offset = bfd_get_32 (abfd, (bfd_byte *) xptr);
aDieInfo->has_stmt_list = 1;
}
xptr += 4;
break;
case FORM_DATA8:
xptr += 8;
break;
case FORM_ADDR:
if (attr == AT_low_pc)
aDieInfo->low_pc = bfd_get_32 (abfd, (bfd_byte *) xptr);
else if (attr == AT_high_pc)
aDieInfo->high_pc = bfd_get_32 (abfd, (bfd_byte *) xptr);
xptr += 4;
break;
case FORM_BLOCK2:
xptr += 2 + bfd_get_16 (abfd, (bfd_byte *) xptr);
break;
case FORM_BLOCK4:
xptr += 4 + bfd_get_32 (abfd, (bfd_byte *) xptr);
break;
case FORM_STRING:
if (attr == AT_name)
aDieInfo->name = (char *) xptr;
xptr += strlen ((char *) xptr) + 1;
break;
}
}
return TRUE;
}
/* Parse a dwarf1 line number table for 'aUnit->stmt_list_offset'
into 'aUnit->linenumber_table'. Return FALSE if an error
occurs; TRUE otherwise. */
static bfd_boolean
parse_line_table (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
{
bfd_byte *xptr;
/* Load the ".line" section from the bfd if we haven't already. */
if (stash->line_section == 0)
{
asection *msec;
bfd_size_type size;
msec = bfd_get_section_by_name (stash->abfd, ".line");
if (! msec)
return FALSE;
size = msec->rawsize ? msec->rawsize : msec->size;
stash->line_section
= bfd_simple_get_relocated_section_contents
(stash->abfd, msec, NULL, stash->syms);
if (! stash->line_section)
return FALSE;
stash->line_section_end = stash->line_section + size;
}
xptr = stash->line_section + aUnit->stmt_list_offset;
if (xptr < stash->line_section_end)
{
unsigned long eachLine;
bfd_byte *tblend;
unsigned long base;
bfd_size_type amt;
/* First comes the length. */
tblend = bfd_get_32 (stash->abfd, (bfd_byte *) xptr) + xptr;
xptr += 4;
/* Then the base address for each address in the table. */
base = bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
xptr += 4;
/* How many line entrys?
10 = 4 (line number) + 2 (pos in line) + 4 (address in line). */
aUnit->line_count = (tblend - xptr) / 10;
/* Allocate an array for the entries. */
amt = sizeof (struct linenumber) * aUnit->line_count;
aUnit->linenumber_table = (struct linenumber *) bfd_alloc (stash->abfd,
amt);
if (!aUnit->linenumber_table)
return FALSE;
for (eachLine = 0; eachLine < aUnit->line_count; eachLine++)
{
/* A line number. */
aUnit->linenumber_table[eachLine].linenumber
= bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
xptr += 4;
/* Skip the position within the line. */
xptr += 2;
/* And finally the address. */
aUnit->linenumber_table[eachLine].addr
= base + bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
xptr += 4;
}
}
return TRUE;
}
/* Parse each function die in a compilation unit 'aUnit'.
The first child die of 'aUnit' should be in 'aUnit->first_child',
the result is placed in 'aUnit->func_list'.
Return FALSE if error; TRUE otherwise. */
static bfd_boolean
parse_functions_in_unit (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
{
bfd_byte *eachDie;
if (aUnit->first_child)
for (eachDie = aUnit->first_child;
eachDie < stash->debug_section_end;
)
{
struct die_info eachDieInfo;
if (! parse_die (stash->abfd, &eachDieInfo, eachDie,
stash->debug_section_end))
return FALSE;
if (eachDieInfo.tag == TAG_global_subroutine
|| eachDieInfo.tag == TAG_subroutine
|| eachDieInfo.tag == TAG_inlined_subroutine
|| eachDieInfo.tag == TAG_entry_point)
{
struct dwarf1_func* aFunc = alloc_dwarf1_func (stash,aUnit);
if (!aFunc)
return FALSE;
aFunc->name = eachDieInfo.name;
aFunc->low_pc = eachDieInfo.low_pc;
aFunc->high_pc = eachDieInfo.high_pc;
}
/* Move to next sibling, if none, end loop */
if (eachDieInfo.sibling)
eachDie = stash->debug_section + eachDieInfo.sibling;
else
break;
}
return TRUE;
}
/* Find the nearest line to 'addr' in 'aUnit'.
Return whether we found the line (or a function) without error. */
static bfd_boolean
dwarf1_unit_find_nearest_line (struct dwarf1_debug* stash,
struct dwarf1_unit* aUnit,
unsigned long addr,
const char **filename_ptr,
const char **functionname_ptr,
unsigned int *linenumber_ptr)
{
int line_p = FALSE;
int func_p = FALSE;
if (aUnit->low_pc <= addr && addr < aUnit->high_pc)
{
if (aUnit->has_stmt_list)
{
unsigned long i;
struct dwarf1_func* eachFunc;
if (! aUnit->linenumber_table)
{
if (! parse_line_table (stash, aUnit))
return FALSE;
}
if (! aUnit->func_list)
{
if (! parse_functions_in_unit (stash, aUnit))
return FALSE;
}
for (i = 0; i < aUnit->line_count; i++)
{
if (aUnit->linenumber_table[i].addr <= addr
&& addr < aUnit->linenumber_table[i+1].addr)
{
*filename_ptr = aUnit->name;
*linenumber_ptr = aUnit->linenumber_table[i].linenumber;
line_p = TRUE;
break;
}
}
for (eachFunc = aUnit->func_list;
eachFunc;
eachFunc = eachFunc->prev)
{
if (eachFunc->low_pc <= addr
&& addr < eachFunc->high_pc)
{
*functionname_ptr = eachFunc->name;
func_p = TRUE;
break;
}
}
}
}
return line_p || func_p;
}
/* The DWARF 1 version of find_nearest line.
Return TRUE if the line is found without error. */
bfd_boolean
_bfd_dwarf1_find_nearest_line (bfd *abfd,
asection *section,
asymbol **symbols,
bfd_vma offset,
const char **filename_ptr,
const char **functionname_ptr,
unsigned int *linenumber_ptr)
{
struct dwarf1_debug *stash = elf_tdata (abfd)->dwarf1_find_line_info;
struct dwarf1_unit* eachUnit;
/* What address are we looking for? */
unsigned long addr = (unsigned long)(offset + section->vma);
*filename_ptr = NULL;
*functionname_ptr = NULL;
*linenumber_ptr = 0;
if (! stash)
{
asection *msec;
bfd_size_type size = sizeof (struct dwarf1_debug);
stash = elf_tdata (abfd)->dwarf1_find_line_info
= (struct dwarf1_debug *) bfd_zalloc (abfd, size);
if (! stash)
return FALSE;
msec = bfd_get_section_by_name (abfd, ".debug");
if (! msec)
/* No dwarf1 info. Note that at this point the stash
has been allocated, but contains zeros, this lets
future calls to this function fail quicker. */
return FALSE;
size = msec->rawsize ? msec->rawsize : msec->size;
stash->debug_section
= bfd_simple_get_relocated_section_contents (abfd, msec, NULL,
symbols);
if (! stash->debug_section)
return FALSE;
stash->debug_section_end = stash->debug_section + size;
stash->currentDie = stash->debug_section;
stash->abfd = abfd;
stash->syms = symbols;
}
/* A null debug_section indicates that there was no dwarf1 info
or that an error occured while setting up the stash. */
if (! stash->debug_section)
return FALSE;
/* Look at the previously parsed units to see if any contain
the addr. */
for (eachUnit = stash->lastUnit; eachUnit; eachUnit = eachUnit->prev)
if (eachUnit->low_pc <= addr && addr < eachUnit->high_pc)
return dwarf1_unit_find_nearest_line (stash, eachUnit, addr,
filename_ptr,
functionname_ptr,
linenumber_ptr);
while (stash->currentDie < stash->debug_section_end)
{
struct die_info aDieInfo;
if (! parse_die (stash->abfd, &aDieInfo, stash->currentDie,
stash->debug_section_end))
return FALSE;
if (aDieInfo.tag == TAG_compile_unit)
{
struct dwarf1_unit* aUnit
= alloc_dwarf1_unit (stash);
if (!aUnit)
return FALSE;
aUnit->name = aDieInfo.name;
aUnit->low_pc = aDieInfo.low_pc;
aUnit->high_pc = aDieInfo.high_pc;
aUnit->has_stmt_list = aDieInfo.has_stmt_list;
aUnit->stmt_list_offset = aDieInfo.stmt_list_offset;
/* A die has a child if it's followed by a die that is
not it's sibling. */
if (aDieInfo.sibling
&& stash->currentDie + aDieInfo.length
< stash->debug_section_end
&& stash->currentDie + aDieInfo.length
!= stash->debug_section + aDieInfo.sibling)
aUnit->first_child = stash->currentDie + aDieInfo.length;
else
aUnit->first_child = 0;
if (aUnit->low_pc <= addr && addr < aUnit->high_pc)
return dwarf1_unit_find_nearest_line (stash, aUnit, addr,
filename_ptr,
functionname_ptr,
linenumber_ptr);
}
if (aDieInfo.sibling != 0)
stash->currentDie = stash->debug_section + aDieInfo.sibling;
else
stash->currentDie += aDieInfo.length;
}
return FALSE;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,703 @@
/* ELF attributes support (based on ARM EABI attributes).
Copyright 2005, 2006, 2007, 2009, 2010, 2012
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"
#include "libiberty.h"
#include "libbfd.h"
#include "elf-bfd.h"
/* Return the number of bytes needed by I in uleb128 format. */
static int
uleb128_size (unsigned int i)
{
int size;
size = 1;
while (i >= 0x80)
{
i >>= 7;
size++;
}
return size;
}
/* Return TRUE if the attribute has the default value (0/""). */
static bfd_boolean
is_default_attr (obj_attribute *attr)
{
if (ATTR_TYPE_HAS_INT_VAL (attr->type) && attr->i != 0)
return FALSE;
if (ATTR_TYPE_HAS_STR_VAL (attr->type) && attr->s && *attr->s)
return FALSE;
if (ATTR_TYPE_HAS_NO_DEFAULT (attr->type))
return FALSE;
return TRUE;
}
/* Return the size of a single attribute. */
static bfd_vma
obj_attr_size (int tag, obj_attribute *attr)
{
bfd_vma size;
if (is_default_attr (attr))
return 0;
size = uleb128_size (tag);
if (ATTR_TYPE_HAS_INT_VAL (attr->type))
size += uleb128_size (attr->i);
if (ATTR_TYPE_HAS_STR_VAL (attr->type))
size += strlen ((char *)attr->s) + 1;
return size;
}
/* Return the vendor name for a given object attributes section. */
static const char *
vendor_obj_attr_name (bfd *abfd, int vendor)
{
return (vendor == OBJ_ATTR_PROC
? get_elf_backend_data (abfd)->obj_attrs_vendor
: "gnu");
}
/* Return the size of the object attributes section for VENDOR
(OBJ_ATTR_PROC or OBJ_ATTR_GNU), or 0 if there are no attributes
for that vendor to record and the vendor is OBJ_ATTR_GNU. */
static bfd_vma
vendor_obj_attr_size (bfd *abfd, int vendor)
{
bfd_vma size;
obj_attribute *attr;
obj_attribute_list *list;
int i;
const char *vendor_name = vendor_obj_attr_name (abfd, vendor);
if (!vendor_name)
return 0;
attr = elf_known_obj_attributes (abfd)[vendor];
size = 0;
for (i = LEAST_KNOWN_OBJ_ATTRIBUTE; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
size += obj_attr_size (i, &attr[i]);
for (list = elf_other_obj_attributes (abfd)[vendor];
list;
list = list->next)
size += obj_attr_size (list->tag, &list->attr);
/* <size> <vendor_name> NUL 0x1 <size> */
return ((size || vendor == OBJ_ATTR_PROC)
? size + 10 + strlen (vendor_name)
: 0);
}
/* Return the size of the object attributes section. */
bfd_vma
bfd_elf_obj_attr_size (bfd *abfd)
{
bfd_vma size;
size = vendor_obj_attr_size (abfd, OBJ_ATTR_PROC);
size += vendor_obj_attr_size (abfd, OBJ_ATTR_GNU);
/* 'A' <sections for each vendor> */
return (size ? size + 1 : 0);
}
/* Write VAL in uleb128 format to P, returning a pointer to the
following byte. */
static bfd_byte *
write_uleb128 (bfd_byte *p, unsigned int val)
{
bfd_byte c;
do
{
c = val & 0x7f;
val >>= 7;
if (val)
c |= 0x80;
*(p++) = c;
}
while (val);
return p;
}
/* Write attribute ATTR to butter P, and return a pointer to the following
byte. */
static bfd_byte *
write_obj_attribute (bfd_byte *p, int tag, obj_attribute *attr)
{
/* Suppress default entries. */
if (is_default_attr (attr))
return p;
p = write_uleb128 (p, tag);
if (ATTR_TYPE_HAS_INT_VAL (attr->type))
p = write_uleb128 (p, attr->i);
if (ATTR_TYPE_HAS_STR_VAL (attr->type))
{
int len;
len = strlen (attr->s) + 1;
memcpy (p, attr->s, len);
p += len;
}
return p;
}
/* Write the contents of the object attributes section (length SIZE)
for VENDOR to CONTENTS. */
static void
vendor_set_obj_attr_contents (bfd *abfd, bfd_byte *contents, bfd_vma size,
int vendor)
{
bfd_byte *p;
obj_attribute *attr;
obj_attribute_list *list;
int i;
const char *vendor_name = vendor_obj_attr_name (abfd, vendor);
size_t vendor_length = strlen (vendor_name) + 1;
p = contents;
bfd_put_32 (abfd, size, p);
p += 4;
memcpy (p, vendor_name, vendor_length);
p += vendor_length;
*(p++) = Tag_File;
bfd_put_32 (abfd, size - 4 - vendor_length, p);
p += 4;
attr = elf_known_obj_attributes (abfd)[vendor];
for (i = LEAST_KNOWN_OBJ_ATTRIBUTE; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
{
int tag = i;
if (get_elf_backend_data (abfd)->obj_attrs_order)
tag = get_elf_backend_data (abfd)->obj_attrs_order (i);
p = write_obj_attribute (p, tag, &attr[tag]);
}
for (list = elf_other_obj_attributes (abfd)[vendor];
list;
list = list->next)
p = write_obj_attribute (p, list->tag, &list->attr);
}
/* Write the contents of the object attributes section to CONTENTS. */
void
bfd_elf_set_obj_attr_contents (bfd *abfd, bfd_byte *contents, bfd_vma size)
{
bfd_byte *p;
int vendor;
bfd_vma my_size;
p = contents;
*(p++) = 'A';
my_size = 1;
for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++)
{
bfd_vma vendor_size = vendor_obj_attr_size (abfd, vendor);
if (vendor_size)
vendor_set_obj_attr_contents (abfd, p, vendor_size, vendor);
p += vendor_size;
my_size += vendor_size;
}
if (size != my_size)
abort ();
}
/* Allocate/find an object attribute. */
static obj_attribute *
elf_new_obj_attr (bfd *abfd, int vendor, int tag)
{
obj_attribute *attr;
obj_attribute_list *list;
obj_attribute_list *p;
obj_attribute_list **lastp;
if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
{
/* Known tags are preallocated. */
attr = &elf_known_obj_attributes (abfd)[vendor][tag];
}
else
{
/* Create a new tag. */
list = (obj_attribute_list *)
bfd_alloc (abfd, sizeof (obj_attribute_list));
memset (list, 0, sizeof (obj_attribute_list));
list->tag = tag;
/* Keep the tag list in order. */
lastp = &elf_other_obj_attributes (abfd)[vendor];
for (p = *lastp; p; p = p->next)
{
if (tag < p->tag)
break;
lastp = &p->next;
}
list->next = *lastp;
*lastp = list;
attr = &list->attr;
}
return attr;
}
/* Return the value of an integer object attribute. */
int
bfd_elf_get_obj_attr_int (bfd *abfd, int vendor, int tag)
{
obj_attribute_list *p;
if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
{
/* Known tags are preallocated. */
return elf_known_obj_attributes (abfd)[vendor][tag].i;
}
else
{
for (p = elf_other_obj_attributes (abfd)[vendor];
p;
p = p->next)
{
if (tag == p->tag)
return p->attr.i;
if (tag < p->tag)
break;
}
return 0;
}
}
/* Add an integer object attribute. */
void
bfd_elf_add_obj_attr_int (bfd *abfd, int vendor, int tag, unsigned int i)
{
obj_attribute *attr;
attr = elf_new_obj_attr (abfd, vendor, tag);
attr->type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
attr->i = i;
}
/* Duplicate an object attribute string value. */
char *
_bfd_elf_attr_strdup (bfd *abfd, const char * s)
{
char * p;
int len;
len = strlen (s) + 1;
p = (char *) bfd_alloc (abfd, len);
return (char *) memcpy (p, s, len);
}
/* Add a string object attribute. */
void
bfd_elf_add_obj_attr_string (bfd *abfd, int vendor, int tag, const char *s)
{
obj_attribute *attr;
attr = elf_new_obj_attr (abfd, vendor, tag);
attr->type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
attr->s = _bfd_elf_attr_strdup (abfd, s);
}
/* Add a int+string object attribute. */
void
bfd_elf_add_obj_attr_int_string (bfd *abfd, int vendor, int tag,
unsigned int i, const char *s)
{
obj_attribute *attr;
attr = elf_new_obj_attr (abfd, vendor, tag);
attr->type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
attr->i = i;
attr->s = _bfd_elf_attr_strdup (abfd, s);
}
/* Copy the object attributes from IBFD to OBFD. */
void
_bfd_elf_copy_obj_attributes (bfd *ibfd, bfd *obfd)
{
obj_attribute *in_attr;
obj_attribute *out_attr;
obj_attribute_list *list;
int i;
int vendor;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
return;
for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++)
{
in_attr
= &elf_known_obj_attributes (ibfd)[vendor][LEAST_KNOWN_OBJ_ATTRIBUTE];
out_attr
= &elf_known_obj_attributes (obfd)[vendor][LEAST_KNOWN_OBJ_ATTRIBUTE];
for (i = LEAST_KNOWN_OBJ_ATTRIBUTE; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
{
out_attr->type = in_attr->type;
out_attr->i = in_attr->i;
if (in_attr->s && *in_attr->s)
out_attr->s = _bfd_elf_attr_strdup (obfd, in_attr->s);
in_attr++;
out_attr++;
}
for (list = elf_other_obj_attributes (ibfd)[vendor];
list;
list = list->next)
{
in_attr = &list->attr;
switch (in_attr->type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL))
{
case ATTR_TYPE_FLAG_INT_VAL:
bfd_elf_add_obj_attr_int (obfd, vendor, list->tag, in_attr->i);
break;
case ATTR_TYPE_FLAG_STR_VAL:
bfd_elf_add_obj_attr_string (obfd, vendor, list->tag,
in_attr->s);
break;
case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL:
bfd_elf_add_obj_attr_int_string (obfd, vendor, list->tag,
in_attr->i, in_attr->s);
break;
default:
abort ();
}
}
}
}
/* Determine whether a GNU object attribute tag takes an integer, a
string or both. */
static int
gnu_obj_attrs_arg_type (int tag)
{
/* Except for Tag_compatibility, for GNU attributes we follow the
same rule ARM ones > 32 follow: odd-numbered tags take strings
and even-numbered tags take integers. In addition, tag & 2 is
nonzero for architecture-independent tags and zero for
architecture-dependent ones. */
if (tag == Tag_compatibility)
return 3;
else
return (tag & 1) != 0 ? 2 : 1;
}
/* Determine what arguments an attribute tag takes. */
int
_bfd_elf_obj_attrs_arg_type (bfd *abfd, int vendor, int tag)
{
switch (vendor)
{
case OBJ_ATTR_PROC:
return get_elf_backend_data (abfd)->obj_attrs_arg_type (tag);
break;
case OBJ_ATTR_GNU:
return gnu_obj_attrs_arg_type (tag);
break;
default:
abort ();
}
}
/* Parse an object attributes section. */
void
_bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
{
bfd_byte *contents;
bfd_byte *p;
bfd_vma len;
const char *std_sec;
contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
if (!contents)
return;
if (!bfd_get_section_contents (abfd, hdr->bfd_section, contents, 0,
hdr->sh_size))
{
free (contents);
return;
}
p = contents;
std_sec = get_elf_backend_data (abfd)->obj_attrs_vendor;
if (*(p++) == 'A')
{
len = hdr->sh_size - 1;
while (len > 0)
{
int namelen;
bfd_vma section_len;
int vendor;
section_len = bfd_get_32 (abfd, p);
p += 4;
if (section_len > len)
section_len = len;
len -= section_len;
namelen = strlen ((char *) p) + 1;
section_len -= namelen + 4;
if (std_sec && strcmp ((char *) p, std_sec) == 0)
vendor = OBJ_ATTR_PROC;
else if (strcmp ((char *) p, "gnu") == 0)
vendor = OBJ_ATTR_GNU;
else
{
/* Other vendor section. Ignore it. */
p += namelen + section_len;
continue;
}
p += namelen;
while (section_len > 0)
{
int tag;
unsigned int n;
unsigned int val;
bfd_vma subsection_len;
bfd_byte *end;
tag = read_unsigned_leb128 (abfd, p, &n);
p += n;
subsection_len = bfd_get_32 (abfd, p);
p += 4;
if (subsection_len > section_len)
subsection_len = section_len;
section_len -= subsection_len;
subsection_len -= n + 4;
end = p + subsection_len;
switch (tag)
{
case Tag_File:
while (p < end)
{
int type;
tag = read_unsigned_leb128 (abfd, p, &n);
p += n;
type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
switch (type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL))
{
case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL:
val = read_unsigned_leb128 (abfd, p, &n);
p += n;
bfd_elf_add_obj_attr_int_string (abfd, vendor, tag,
val, (char *)p);
p += strlen ((char *)p) + 1;
break;
case ATTR_TYPE_FLAG_STR_VAL:
bfd_elf_add_obj_attr_string (abfd, vendor, tag,
(char *)p);
p += strlen ((char *)p) + 1;
break;
case ATTR_TYPE_FLAG_INT_VAL:
val = read_unsigned_leb128 (abfd, p, &n);
p += n;
bfd_elf_add_obj_attr_int (abfd, vendor, tag, val);
break;
default:
abort ();
}
}
break;
case Tag_Section:
case Tag_Symbol:
/* Don't have anywhere convenient to attach these.
Fall through for now. */
default:
/* Ignore things we don't kow about. */
p += subsection_len;
subsection_len = 0;
break;
}
}
}
}
free (contents);
}
/* Merge common object attributes from IBFD into OBFD. Raise an error
if there are conflicting attributes. Any processor-specific
attributes have already been merged. This must be called from the
bfd_elfNN_bfd_merge_private_bfd_data hook for each individual
target, along with any target-specific merging. Because there are
no common attributes other than Tag_compatibility at present, and
non-"gnu" Tag_compatibility is not expected in "gnu" sections, this
is not presently called for targets without their own
attributes. */
bfd_boolean
_bfd_elf_merge_object_attributes (bfd *ibfd, bfd *obfd)
{
obj_attribute *in_attr;
obj_attribute *out_attr;
int vendor;
/* The only common attribute is currently Tag_compatibility,
accepted in both processor and "gnu" sections. */
for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++)
{
/* Handle Tag_compatibility. The tags are only compatible if the flags
are identical and, if the flags are '1', the strings are identical.
If the flags are non-zero, then we can only use the string "gnu". */
in_attr = &elf_known_obj_attributes (ibfd)[vendor][Tag_compatibility];
out_attr = &elf_known_obj_attributes (obfd)[vendor][Tag_compatibility];
if (in_attr->i > 0 && strcmp (in_attr->s, "gnu") != 0)
{
_bfd_error_handler
(_("error: %B: Object has vendor-specific contents that "
"must be processed by the '%s' toolchain"),
ibfd, in_attr->s);
return FALSE;
}
if (in_attr->i != out_attr->i
|| (in_attr->i != 0 && strcmp (in_attr->s, out_attr->s) != 0))
{
_bfd_error_handler (_("error: %B: Object tag '%d, %s' is "
"incompatible with tag '%d, %s'"),
ibfd,
in_attr->i, in_attr->s ? in_attr->s : "",
out_attr->i, out_attr->s ? out_attr->s : "");
return FALSE;
}
}
return TRUE;
}
/* Merge an unknown processor-specific attribute TAG, within the range
of known attributes, from IBFD into OBFD; return TRUE if the link
is OK, FALSE if it must fail. */
bfd_boolean
_bfd_elf_merge_unknown_attribute_low (bfd *ibfd, bfd *obfd, int tag)
{
obj_attribute *in_attr;
obj_attribute *out_attr;
bfd *err_bfd = NULL;
bfd_boolean result = TRUE;
in_attr = elf_known_obj_attributes_proc (ibfd);
out_attr = elf_known_obj_attributes_proc (obfd);
if (out_attr[tag].i != 0 || out_attr[tag].s != NULL)
err_bfd = obfd;
else if (in_attr[tag].i != 0 || in_attr[tag].s != NULL)
err_bfd = ibfd;
if (err_bfd != NULL)
result
= get_elf_backend_data (err_bfd)->obj_attrs_handle_unknown (err_bfd, tag);
/* Only pass on attributes that match in both inputs. */
if (in_attr[tag].i != out_attr[tag].i
|| (in_attr[tag].s == NULL) != (out_attr[tag].s == NULL)
|| (in_attr[tag].s != NULL && out_attr[tag].s != NULL
&& strcmp (in_attr[tag].s, out_attr[tag].s) != 0))
{
out_attr[tag].i = 0;
out_attr[tag].s = NULL;
}
return result;
}
/* Merge the lists of unknown processor-specific attributes, outside
the known range, from IBFD into OBFD; return TRUE if the link is
OK, FALSE if it must fail. */
bfd_boolean
_bfd_elf_merge_unknown_attribute_list (bfd *ibfd, bfd *obfd)
{
obj_attribute_list *in_list;
obj_attribute_list *out_list;
obj_attribute_list **out_listp;
bfd_boolean result = TRUE;
in_list = elf_other_obj_attributes_proc (ibfd);
out_listp = &elf_other_obj_attributes_proc (obfd);
out_list = *out_listp;
for (; in_list || out_list; )
{
bfd *err_bfd = NULL;
int err_tag = 0;
/* The tags for each list are in numerical order. */
/* If the tags are equal, then merge. */
if (out_list && (!in_list || in_list->tag > out_list->tag))
{
/* This attribute only exists in obfd. We can't merge, and we don't
know what the tag means, so delete it. */
err_bfd = obfd;
err_tag = out_list->tag;
*out_listp = out_list->next;
out_list = *out_listp;
}
else if (in_list && (!out_list || in_list->tag < out_list->tag))
{
/* This attribute only exists in ibfd. We can't merge, and we don't
know what the tag means, so ignore it. */
err_bfd = ibfd;
err_tag = in_list->tag;
in_list = in_list->next;
}
else /* The tags are equal. */
{
/* As present, all attributes in the list are unknown, and
therefore can't be merged meaningfully. */
err_bfd = obfd;
err_tag = out_list->tag;
/* Only pass on attributes that match in both inputs. */
if (in_list->attr.i != out_list->attr.i
|| (in_list->attr.s == NULL) != (out_list->attr.s == NULL)
|| (in_list->attr.s && out_list->attr.s
&& strcmp (in_list->attr.s, out_list->attr.s) != 0))
{
/* No match. Delete the attribute. */
*out_listp = out_list->next;
out_list = *out_listp;
}
else
{
/* Matched. Keep the attribute and move to the next. */
out_list = out_list->next;
in_list = in_list->next;
}
}
if (err_bfd)
result = result
&& get_elf_backend_data (err_bfd)->obj_attrs_handle_unknown (err_bfd,
err_tag);
}
return result;
}

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,276 @@
/* ELF STT_GNU_IFUNC support.
Copyright 2009-2013
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"
#include "bfdlink.h"
#include "libbfd.h"
#define ARCH_SIZE 0
#include "elf-bfd.h"
#include "safe-ctype.h"
#include "libiberty.h"
#include "objalloc.h"
/* Create sections needed by STT_GNU_IFUNC symbol. */
bfd_boolean
_bfd_elf_create_ifunc_sections (bfd *abfd, struct bfd_link_info *info)
{
flagword flags, pltflags;
asection *s;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
struct elf_link_hash_table *htab = elf_hash_table (info);
if (htab->irelifunc != NULL || htab->iplt != NULL)
return TRUE;
flags = bed->dynamic_sec_flags;
pltflags = flags;
if (bed->plt_not_loaded)
/* We do not clear SEC_ALLOC here because we still want the OS to
allocate space for the section; it's just that there's nothing
to read in from the object file. */
pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
else
pltflags |= SEC_ALLOC | SEC_CODE | SEC_LOAD;
if (bed->plt_readonly)
pltflags |= SEC_READONLY;
if (info->shared)
{
/* We need to create .rel[a].ifunc for shared objects. */
const char *rel_sec = (bed->rela_plts_and_copies_p
? ".rela.ifunc" : ".rel.ifunc");
s = bfd_make_section_with_flags (abfd, rel_sec,
flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s,
bed->s->log_file_align))
return FALSE;
htab->irelifunc = s;
}
else
{
/* We need to create .iplt, .rel[a].iplt, .igot and .igot.plt
for static executables. */
s = bfd_make_section_with_flags (abfd, ".iplt", pltflags);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
return FALSE;
htab->iplt = s;
s = bfd_make_section_with_flags (abfd,
(bed->rela_plts_and_copies_p
? ".rela.iplt" : ".rel.iplt"),
flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s,
bed->s->log_file_align))
return FALSE;
htab->irelplt = s;
/* We don't need the .igot section if we have the .igot.plt
section. */
if (bed->want_got_plt)
s = bfd_make_section_with_flags (abfd, ".igot.plt", flags);
else
s = bfd_make_section_with_flags (abfd, ".igot", flags);
if (s == NULL
|| !bfd_set_section_alignment (abfd, s,
bed->s->log_file_align))
return FALSE;
htab->igotplt = s;
}
return TRUE;
}
/* Allocate space in .plt, .got and associated reloc sections for
dynamic relocs against a STT_GNU_IFUNC symbol definition. */
bfd_boolean
_bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info,
struct elf_link_hash_entry *h,
struct elf_dyn_relocs **head,
unsigned int plt_entry_size,
unsigned int plt_header_size,
unsigned int got_entry_size)
{
asection *plt, *gotplt, *relplt;
struct elf_dyn_relocs *p;
unsigned int sizeof_reloc;
const struct elf_backend_data *bed;
struct elf_link_hash_table *htab;
/* When a shared library references a STT_GNU_IFUNC symbol defined
in executable, the address of the resolved function may be used.
But in non-shared executable, the address of its .plt slot may
be used. Pointer equality may not work correctly. PIE should
be used if pointer equality is required here. */
if (!info->shared
&& (h->dynindx != -1
|| info->export_dynamic)
&& h->pointer_equality_needed)
{
info->callbacks->einfo
(_("%F%P: dynamic STT_GNU_IFUNC symbol `%s' with pointer "
"equality in `%B' can not be used when making an "
"executable; recompile with -fPIE and relink with -pie\n"),
h->root.root.string,
h->root.u.def.section->owner);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
htab = elf_hash_table (info);
/* When building shared library, we need to handle the case where it is
marked with regular reference, but not non-GOT reference since the
non-GOT reference bit may not be set here. */
if (info->shared && !h->non_got_ref && h->ref_regular)
for (p = *head; p != NULL; p = p->next)
if (p->count)
{
h->non_got_ref = 1;
goto keep;
}
/* Support garbage collection against STT_GNU_IFUNC symbols. */
if (h->plt.refcount <= 0 && h->got.refcount <= 0)
{
h->got = htab->init_got_offset;
h->plt = htab->init_plt_offset;
*head = NULL;
return TRUE;
}
/* Return and discard space for dynamic relocations against it if
it is never referenced in a non-shared object. */
if (!h->ref_regular)
{
if (h->plt.refcount > 0
|| h->got.refcount > 0)
abort ();
h->got = htab->init_got_offset;
h->plt = htab->init_plt_offset;
*head = NULL;
return TRUE;
}
keep:
bed = get_elf_backend_data (info->output_bfd);
if (bed->rela_plts_and_copies_p)
sizeof_reloc = bed->s->sizeof_rela;
else
sizeof_reloc = bed->s->sizeof_rel;
/* When building a static executable, use .iplt, .igot.plt and
.rel[a].iplt sections for STT_GNU_IFUNC symbols. */
if (htab->splt != NULL)
{
plt = htab->splt;
gotplt = htab->sgotplt;
relplt = htab->srelplt;
/* If this is the first .plt entry, make room for the special
first entry. */
if (plt->size == 0)
plt->size += plt_header_size;
}
else
{
plt = htab->iplt;
gotplt = htab->igotplt;
relplt = htab->irelplt;
}
/* Don't update value of STT_GNU_IFUNC symbol to PLT. We need
the original value for R_*_IRELATIVE. */
h->plt.offset = plt->size;
/* Make room for this entry in the .plt/.iplt section. */
plt->size += plt_entry_size;
/* We also need to make an entry in the .got.plt/.got.iplt section,
which will be placed in the .got section by the linker script. */
gotplt->size += got_entry_size;
/* We also need to make an entry in the .rel[a].plt/.rel[a].iplt
section. */
relplt->size += sizeof_reloc;
relplt->reloc_count++;
/* We need dynamic relocation for STT_GNU_IFUNC symbol only when
there is a non-GOT reference in a shared object. */
if (!info->shared
|| !h->non_got_ref)
*head = NULL;
/* Finally, allocate space. */
p = *head;
if (p != NULL)
{
bfd_size_type count = 0;
do
{
count += p->count;
p = p->next;
}
while (p != NULL);
htab->irelifunc->size += count * sizeof_reloc;
}
/* For STT_GNU_IFUNC symbol, .got.plt has the real function address
and .got has the PLT entry adddress. We will load the GOT entry
with the PLT entry in finish_dynamic_symbol if it is used. For
branch, it uses .got.plt. For symbol value,
1. Use .got.plt in a shared object if it is forced local or not
dynamic.
2. Use .got.plt in a non-shared object if pointer equality isn't
needed.
3. Use .got.plt in PIE.
4. Use .got.plt if .got isn't used.
5. Otherwise use .got so that it can be shared among different
objects at run-time.
We only need to relocate .got entry in shared object. */
if (h->got.refcount <= 0
|| (info->shared
&& (h->dynindx == -1
|| h->forced_local))
|| (!info->shared
&& !h->pointer_equality_needed)
|| (info->executable && info->shared)
|| htab->sgot == NULL)
{
/* Use .got.plt. */
h->got.offset = (bfd_vma) -1;
}
else
{
h->got.offset = htab->sgot->size;
htab->sgot->size += got_entry_size;
if (info->shared)
htab->srelgot->size += sizeof_reloc;
}
return TRUE;
}

View File

@@ -0,0 +1,127 @@
/* Definitions for PRPSINFO structures under ELF on GNU/Linux.
Copyright 2013 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. */
#ifndef ELF_LINUX_PSINFO_H
#define ELF_LINUX_PSINFO_H
/* The PRPSINFO structures defined below are used by most
architectures, although some of them define their own versions
(like e.g., PPC). */
/* External 32-bit structure for PRPSINFO. This structure is
ABI-defined, thus we choose to use char arrays here in order to
avoid dealing with different types in different architectures.
This structure will ultimately be written in the corefile's note
section, as the PRPSINFO. */
struct elf_external_linux_prpsinfo32
{
char pr_state; /* Numeric process state. */
char pr_sname; /* Char for pr_state. */
char pr_zomb; /* Zombie. */
char pr_nice; /* Nice val. */
char pr_flag[4]; /* Flags. */
char pr_uid[2];
char pr_gid[2];
char pr_pid[4];
char pr_ppid[4];
char pr_pgrp[4];
char pr_sid[4];
char pr_fname[16]; /* Filename of executable. */
char pr_psargs[80]; /* Initial part of arg list. */
};
/* Helper macro to swap (properly handling endianess) things from the
`elf_internal_linux_prpsinfo' structure to the
`elf_external_linux_prpsinfo32' structure.
Note that FROM should be a pointer, and TO should be the explicit
type. */
#define LINUX_PRPSINFO32_SWAP_FIELDS(abfd, from, to) \
do \
{ \
H_PUT_8 (abfd, from->pr_state, &to.pr_state); \
H_PUT_8 (abfd, from->pr_sname, &to.pr_sname); \
H_PUT_8 (abfd, from->pr_zomb, &to.pr_zomb); \
H_PUT_8 (abfd, from->pr_nice, &to.pr_nice); \
H_PUT_32 (abfd, from->pr_flag, to.pr_flag); \
H_PUT_16 (abfd, from->pr_uid, to.pr_uid); \
H_PUT_16 (abfd, from->pr_gid, to.pr_gid); \
H_PUT_32 (abfd, from->pr_pid, to.pr_pid); \
H_PUT_32 (abfd, from->pr_ppid, to.pr_ppid); \
H_PUT_32 (abfd, from->pr_pgrp, to.pr_pgrp); \
H_PUT_32 (abfd, from->pr_sid, to.pr_sid); \
strncpy (to.pr_fname, from->pr_fname, sizeof (to.pr_fname)); \
strncpy (to.pr_psargs, from->pr_psargs, sizeof (to.pr_psargs)); \
} while (0)
/* External 64-bit structure for PRPSINFO. This structure is
ABI-defined, thus we choose to use char arrays here in order to
avoid dealing with different types in different architectures.
This structure will ultimately be written in the corefile's note
section, as the PRPSINFO. */
struct elf_external_linux_prpsinfo64
{
char pr_state; /* Numeric process state. */
char pr_sname; /* Char for pr_state. */
char pr_zomb; /* Zombie. */
char pr_nice; /* Nice val. */
char pr_flag[8]; /* Flags. */
char gap[4];
char pr_uid[4];
char pr_gid[4];
char pr_pid[4];
char pr_ppid[4];
char pr_pgrp[4];
char pr_sid[4];
char pr_fname[16]; /* Filename of executable. */
char pr_psargs[80]; /* Initial part of arg list. */
};
/* Helper macro to swap (properly handling endianess) things from the
`elf_internal_linux_prpsinfo' structure to the
`elf_external_linux_prpsinfo64' structure.
Note that FROM should be a pointer, and TO should be the explicit
type. */
#define LINUX_PRPSINFO64_SWAP_FIELDS(abfd, from, to) \
do \
{ \
H_PUT_8 (abfd, from->pr_state, &to.pr_state); \
H_PUT_8 (abfd, from->pr_sname, &to.pr_sname); \
H_PUT_8 (abfd, from->pr_zomb, &to.pr_zomb); \
H_PUT_8 (abfd, from->pr_nice, &to.pr_nice); \
H_PUT_64 (abfd, from->pr_flag, to.pr_flag); \
H_PUT_32 (abfd, from->pr_uid, to.pr_uid); \
H_PUT_32 (abfd, from->pr_gid, to.pr_gid); \
H_PUT_32 (abfd, from->pr_pid, to.pr_pid); \
H_PUT_32 (abfd, from->pr_ppid, to.pr_ppid); \
H_PUT_32 (abfd, from->pr_pgrp, to.pr_pgrp); \
H_PUT_32 (abfd, from->pr_sid, to.pr_sid); \
strncpy (to.pr_fname, from->pr_fname, sizeof (to.pr_fname)); \
strncpy (to.pr_psargs, from->pr_psargs, sizeof (to.pr_psargs)); \
} while (0)
#endif

View File

@@ -0,0 +1,355 @@
/* Native Client support for ELF
Copyright 2012, 2013 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., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
#include "sysdep.h"
#include "bfd.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf-nacl.h"
#include "elf/common.h"
#include "elf/internal.h"
static bfd_boolean
segment_executable (struct elf_segment_map *seg)
{
if (seg->p_flags_valid)
return (seg->p_flags & PF_X) != 0;
else
{
/* The p_flags value has not been computed yet,
so we have to look through the sections. */
unsigned int i;
for (i = 0; i < seg->count; ++i)
if (seg->sections[i]->flags & SEC_CODE)
return TRUE;
}
return FALSE;
}
/* Determine if this segment is eligible to receive the file and program
headers. It must be read-only and non-executable.
Its first section must start far enough past the page boundary to
allow space for the headers. */
static bfd_boolean
segment_eligible_for_headers (struct elf_segment_map *seg,
bfd_vma minpagesize, bfd_vma sizeof_headers)
{
unsigned int i;
if (seg->count == 0 || seg->sections[0]->lma % minpagesize < sizeof_headers)
return FALSE;
for (i = 0; i < seg->count; ++i)
{
if ((seg->sections[i]->flags & (SEC_CODE|SEC_READONLY)) != SEC_READONLY)
return FALSE;
}
return TRUE;
}
/* We permute the segment_map to get BFD to do the file layout we want:
The first non-executable PT_LOAD segment appears first in the file
and contains the ELF file header and phdrs. */
bfd_boolean
nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
{
const struct elf_backend_data *const bed = get_elf_backend_data (abfd);
struct elf_segment_map **m = &elf_seg_map (abfd);
struct elf_segment_map **first_load = NULL;
struct elf_segment_map **last_load = NULL;
bfd_boolean moved_headers = FALSE;
int sizeof_headers;
if (info != NULL && info->user_phdrs)
/* The linker script used PHDRS explicitly, so don't change what the
user asked for. */
return TRUE;
if (info != NULL)
/* We're doing linking, so evalute SIZEOF_HEADERS as in a linker script. */
sizeof_headers = bfd_sizeof_headers (abfd, info);
else
{
/* We're not doing linking, so this is objcopy or suchlike.
We just need to collect the size of the existing headers. */
struct elf_segment_map *seg;
sizeof_headers = bed->s->sizeof_ehdr;
for (seg = *m; seg != NULL; seg = seg->next)
sizeof_headers += bed->s->sizeof_phdr;
}
while (*m != NULL)
{
struct elf_segment_map *seg = *m;
if (seg->p_type == PT_LOAD)
{
bfd_boolean executable = segment_executable (seg);
if (executable
&& seg->count > 0
&& seg->sections[0]->vma % bed->minpagesize == 0)
{
asection *lastsec = seg->sections[seg->count - 1];
bfd_vma end = lastsec->vma + lastsec->size;
if (end % bed->minpagesize != 0)
{
/* This is an executable segment that starts on a page
boundary but does not end on a page boundary. Fill
it out to a whole page with code fill (the tail of
the segment will not be within any section). Thus
the entire code segment can be mapped from the file
as whole pages and that mapping will contain only
valid instructions.
To accomplish this, we must fake out the code in
assign_file_positions_for_load_sections (elf.c) so
that it advances past the rest of the final page,
rather than trying to put the next (unaligned, or
unallocated) section. We do this by appending a
dummy section record to this element in the segment
map. No such output section ever actually exists,
but this gets the layout logic to advance the file
positions past this partial page. Since we are
lying to BFD like this, nothing will ever know to
write the section contents. So we do that by hand
after the fact, in nacl_final_write_processing, below. */
struct elf_segment_map *newseg;
asection *sec;
struct bfd_elf_section_data *secdata;
BFD_ASSERT (!seg->p_size_valid);
secdata = bfd_zalloc (abfd, sizeof *secdata);
if (secdata == NULL)
return FALSE;
sec = bfd_zalloc (abfd, sizeof *sec);
if (sec == NULL)
return FALSE;
/* Fill in only the fields that actually affect the logic
in assign_file_positions_for_load_sections. */
sec->vma = end;
sec->lma = lastsec->lma + lastsec->size;
sec->size = bed->minpagesize - (end % bed->minpagesize);
sec->flags = (SEC_ALLOC | SEC_LOAD
| SEC_READONLY | SEC_CODE | SEC_LINKER_CREATED);
sec->used_by_bfd = secdata;
secdata->this_hdr.sh_type = SHT_PROGBITS;
secdata->this_hdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
secdata->this_hdr.sh_addr = sec->vma;
secdata->this_hdr.sh_size = sec->size;
newseg = bfd_alloc (abfd,
sizeof *newseg + ((seg->count + 1)
* sizeof (asection *)));
if (newseg == NULL)
return FALSE;
memcpy (newseg, seg,
sizeof *newseg + (seg->count * sizeof (asection *)));
newseg->sections[newseg->count++] = sec;
*m = seg = newseg;
}
}
/* First, we're just finding the earliest PT_LOAD.
By the normal rules, this will be the lowest-addressed one.
We only have anything interesting to do if it's executable. */
last_load = m;
if (first_load == NULL)
{
if (!executable)
goto next;
first_load = m;
}
/* Now that we've noted the first PT_LOAD, we're looking for
the first non-executable PT_LOAD with a nonempty p_filesz. */
else if (!moved_headers
&& segment_eligible_for_headers (seg, bed->minpagesize,
sizeof_headers))
{
/* This is the one we were looking for!
First, clear the flags on previous segments that
say they include the file header and phdrs. */
struct elf_segment_map *prevseg;
for (prevseg = *first_load;
prevseg != seg;
prevseg = prevseg->next)
if (prevseg->p_type == PT_LOAD)
{
prevseg->includes_filehdr = 0;
prevseg->includes_phdrs = 0;
}
/* This segment will include those headers instead. */
seg->includes_filehdr = 1;
seg->includes_phdrs = 1;
moved_headers = TRUE;
}
}
next:
m = &seg->next;
}
if (first_load != last_load && moved_headers)
{
/* Now swap the first and last PT_LOAD segments'
positions in segment_map. */
struct elf_segment_map *first = *first_load;
struct elf_segment_map *last = *last_load;
*first_load = first->next;
first->next = last->next;
last->next = first;
}
return TRUE;
}
/* After nacl_modify_segment_map has done its work, the file layout has
been done as we wanted. But the PT_LOAD phdrs are no longer in the
proper order for the ELF rule that they must appear in ascending address
order. So find the two segments we swapped before, and swap them back. */
bfd_boolean
nacl_modify_program_headers (bfd *abfd, struct bfd_link_info *info)
{
struct elf_segment_map **m = &elf_seg_map (abfd);
Elf_Internal_Phdr *phdr = elf_tdata (abfd)->phdr;
Elf_Internal_Phdr *p = phdr;
if (info != NULL && info->user_phdrs)
/* The linker script used PHDRS explicitly, so don't change what the
user asked for. */
return TRUE;
/* Find the PT_LOAD that contains the headers (should be the first). */
while (*m != NULL)
{
if ((*m)->p_type == PT_LOAD && (*m)->includes_filehdr)
break;
m = &(*m)->next;
++p;
}
if (*m != NULL)
{
struct elf_segment_map **first_load_seg = m;
Elf_Internal_Phdr *first_load_phdr = p;
struct elf_segment_map **next_load_seg = NULL;
Elf_Internal_Phdr *next_load_phdr = NULL;
/* Now move past that first one and find the PT_LOAD that should be
before it by address order. */
m = &(*m)->next;
++p;
while (*m != NULL)
{
if (p->p_type == PT_LOAD && p->p_vaddr < first_load_phdr->p_vaddr)
{
next_load_seg = m;
next_load_phdr = p;
break;
}
m = &(*m)->next;
++p;
}
/* Swap their positions in the segment_map back to how they used to be.
The phdrs have already been set up by now, so we have to slide up
the earlier ones to insert the one that should be first. */
if (next_load_seg != NULL)
{
Elf_Internal_Phdr move_phdr;
struct elf_segment_map *first_seg = *first_load_seg;
struct elf_segment_map *next_seg = *next_load_seg;
struct elf_segment_map *first_next = first_seg->next;
struct elf_segment_map *next_next = next_seg->next;
if (next_load_seg == &first_seg->next)
{
*first_load_seg = next_seg;
next_seg->next = first_seg;
first_seg->next = next_next;
}
else
{
*first_load_seg = first_next;
*next_load_seg = next_next;
first_seg->next = *next_load_seg;
*next_load_seg = first_seg;
next_seg->next = *first_load_seg;
*first_load_seg = next_seg;
}
move_phdr = *next_load_phdr;
memmove (first_load_phdr + 1, first_load_phdr,
(next_load_phdr - first_load_phdr) * sizeof move_phdr);
*first_load_phdr = move_phdr;
}
}
return TRUE;
}
void
nacl_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED)
{
struct elf_segment_map *seg;
for (seg = elf_seg_map (abfd); seg != NULL; seg = seg->next)
if (seg->p_type == PT_LOAD
&& seg->count > 1
&& seg->sections[seg->count - 1]->owner == NULL)
{
/* This is a fake section added in nacl_modify_segment_map, above.
It's not a real BFD section, so nothing wrote its contents.
Now write out its contents. */
asection *sec = seg->sections[seg->count - 1];
char *fill;
BFD_ASSERT (sec->flags & SEC_LINKER_CREATED);
BFD_ASSERT (sec->flags & SEC_CODE);
BFD_ASSERT (sec->size > 0);
fill = abfd->arch_info->fill (sec->size, bfd_big_endian (abfd), TRUE);
if (fill == NULL
|| bfd_seek (abfd, sec->filepos, SEEK_SET) != 0
|| bfd_bwrite (fill, sec->size, abfd) != sec->size)
{
/* We don't have a proper way to report an error here. So
instead fudge things so that elf_write_shdrs_and_ehdr will
fail. */
elf_elfheader (abfd)->e_shoff = (file_ptr) -1;
}
free (fill);
}
}

View File

@@ -0,0 +1,25 @@
/* Native Client support for ELF
Copyright 2012, 2013 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., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
#include "bfd.h"
bfd_boolean nacl_modify_segment_map (bfd *, struct bfd_link_info *);
bfd_boolean nacl_modify_program_headers (bfd *, struct bfd_link_info *);
void nacl_final_write_processing (bfd *, bfd_boolean linker);

View File

@@ -0,0 +1,421 @@
/* ELF strtab with GC and suffix merging support.
Copyright 2001, 2002, 2003, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
Written by Jakub Jelinek <jakub@redhat.com>.
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"
#include "libbfd.h"
#include "elf-bfd.h"
#include "hashtab.h"
#include "libiberty.h"
/* An entry in the strtab hash table. */
struct elf_strtab_hash_entry
{
struct bfd_hash_entry root;
/* Length of this entry. This includes the zero terminator. */
int len;
unsigned int refcount;
union {
/* Index within the merged section. */
bfd_size_type index;
/* Entry this is a suffix of (if len < 0). */
struct elf_strtab_hash_entry *suffix;
} u;
};
/* The strtab hash table. */
struct elf_strtab_hash
{
struct bfd_hash_table table;
/* Next available index. */
bfd_size_type size;
/* Number of array entries alloced. */
bfd_size_type alloced;
/* Final strtab size. */
bfd_size_type sec_size;
/* Array of pointers to strtab entries. */
struct elf_strtab_hash_entry **array;
};
/* Routine to create an entry in a section merge hashtab. */
static struct bfd_hash_entry *
elf_strtab_hash_newfunc (struct bfd_hash_entry *entry,
struct bfd_hash_table *table,
const char *string)
{
/* Allocate the structure if it has not already been allocated by a
subclass. */
if (entry == NULL)
entry = (struct bfd_hash_entry *)
bfd_hash_allocate (table, sizeof (struct elf_strtab_hash_entry));
if (entry == NULL)
return NULL;
/* Call the allocation method of the superclass. */
entry = bfd_hash_newfunc (entry, table, string);
if (entry)
{
/* Initialize the local fields. */
struct elf_strtab_hash_entry *ret;
ret = (struct elf_strtab_hash_entry *) entry;
ret->u.index = -1;
ret->refcount = 0;
ret->len = 0;
}
return entry;
}
/* Create a new hash table. */
struct elf_strtab_hash *
_bfd_elf_strtab_init (void)
{
struct elf_strtab_hash *table;
bfd_size_type amt = sizeof (struct elf_strtab_hash);
table = (struct elf_strtab_hash *) bfd_malloc (amt);
if (table == NULL)
return NULL;
if (!bfd_hash_table_init (&table->table, elf_strtab_hash_newfunc,
sizeof (struct elf_strtab_hash_entry)))
{
free (table);
return NULL;
}
table->sec_size = 0;
table->size = 1;
table->alloced = 64;
amt = sizeof (struct elf_strtab_hasn_entry *);
table->array = (struct elf_strtab_hash_entry **)
bfd_malloc (table->alloced * amt);
if (table->array == NULL)
{
free (table);
return NULL;
}
table->array[0] = NULL;
return table;
}
/* Free a strtab. */
void
_bfd_elf_strtab_free (struct elf_strtab_hash *tab)
{
bfd_hash_table_free (&tab->table);
free (tab->array);
free (tab);
}
/* Get the index of an entity in a hash table, adding it if it is not
already present. */
bfd_size_type
_bfd_elf_strtab_add (struct elf_strtab_hash *tab,
const char *str,
bfd_boolean copy)
{
register struct elf_strtab_hash_entry *entry;
/* We handle this specially, since we don't want to do refcounting
on it. */
if (*str == '\0')
return 0;
BFD_ASSERT (tab->sec_size == 0);
entry = (struct elf_strtab_hash_entry *)
bfd_hash_lookup (&tab->table, str, TRUE, copy);
if (entry == NULL)
return (bfd_size_type) -1;
entry->refcount++;
if (entry->len == 0)
{
entry->len = strlen (str) + 1;
/* 2G strings lose. */
BFD_ASSERT (entry->len > 0);
if (tab->size == tab->alloced)
{
bfd_size_type amt = sizeof (struct elf_strtab_hash_entry *);
tab->alloced *= 2;
tab->array = (struct elf_strtab_hash_entry **)
bfd_realloc_or_free (tab->array, tab->alloced * amt);
if (tab->array == NULL)
return (bfd_size_type) -1;
}
entry->u.index = tab->size++;
tab->array[entry->u.index] = entry;
}
return entry->u.index;
}
void
_bfd_elf_strtab_addref (struct elf_strtab_hash *tab, bfd_size_type idx)
{
if (idx == 0 || idx == (bfd_size_type) -1)
return;
BFD_ASSERT (tab->sec_size == 0);
BFD_ASSERT (idx < tab->size);
++tab->array[idx]->refcount;
}
void
_bfd_elf_strtab_delref (struct elf_strtab_hash *tab, bfd_size_type idx)
{
if (idx == 0 || idx == (bfd_size_type) -1)
return;
BFD_ASSERT (tab->sec_size == 0);
BFD_ASSERT (idx < tab->size);
BFD_ASSERT (tab->array[idx]->refcount > 0);
--tab->array[idx]->refcount;
}
unsigned int
_bfd_elf_strtab_refcount (struct elf_strtab_hash *tab, bfd_size_type idx)
{
return tab->array[idx]->refcount;
}
void
_bfd_elf_strtab_clear_all_refs (struct elf_strtab_hash *tab)
{
bfd_size_type idx;
for (idx = 1; idx < tab->size; idx++)
tab->array[idx]->refcount = 0;
}
/* Downsizes strtab. Entries from IDX up to the current size are
removed from the array. */
void
_bfd_elf_strtab_restore_size (struct elf_strtab_hash *tab, bfd_size_type idx)
{
bfd_size_type curr_size = tab->size;
BFD_ASSERT (tab->sec_size == 0);
BFD_ASSERT (idx <= curr_size);
tab->size = idx;
for (; idx < curr_size; ++idx)
{
/* We don't remove entries from the hash table, just set their
REFCOUNT to zero. Setting LEN zero will result in the size
growing if the entry is added again. See _bfd_elf_strtab_add. */
tab->array[idx]->refcount = 0;
tab->array[idx]->len = 0;
}
}
bfd_size_type
_bfd_elf_strtab_size (struct elf_strtab_hash *tab)
{
return tab->sec_size ? tab->sec_size : tab->size;
}
bfd_size_type
_bfd_elf_strtab_offset (struct elf_strtab_hash *tab, bfd_size_type idx)
{
struct elf_strtab_hash_entry *entry;
if (idx == 0)
return 0;
BFD_ASSERT (idx < tab->size);
BFD_ASSERT (tab->sec_size);
entry = tab->array[idx];
BFD_ASSERT (entry->refcount > 0);
entry->refcount--;
return tab->array[idx]->u.index;
}
bfd_boolean
_bfd_elf_strtab_emit (register bfd *abfd, struct elf_strtab_hash *tab)
{
bfd_size_type off = 1, i;
if (bfd_bwrite ("", 1, abfd) != 1)
return FALSE;
for (i = 1; i < tab->size; ++i)
{
register const char *str;
register unsigned int len;
BFD_ASSERT (tab->array[i]->refcount == 0);
len = tab->array[i]->len;
if ((int) len < 0)
continue;
str = tab->array[i]->root.string;
if (bfd_bwrite (str, len, abfd) != len)
return FALSE;
off += len;
}
BFD_ASSERT (off == tab->sec_size);
return TRUE;
}
/* Compare two elf_strtab_hash_entry structures. Called via qsort. */
static int
strrevcmp (const void *a, const void *b)
{
struct elf_strtab_hash_entry *A = *(struct elf_strtab_hash_entry **) a;
struct elf_strtab_hash_entry *B = *(struct elf_strtab_hash_entry **) b;
unsigned int lenA = A->len;
unsigned int lenB = B->len;
const unsigned char *s = (const unsigned char *) A->root.string + lenA - 1;
const unsigned char *t = (const unsigned char *) B->root.string + lenB - 1;
int l = lenA < lenB ? lenA : lenB;
while (l)
{
if (*s != *t)
return (int) *s - (int) *t;
s--;
t--;
l--;
}
return lenA - lenB;
}
static inline int
is_suffix (const struct elf_strtab_hash_entry *A,
const struct elf_strtab_hash_entry *B)
{
if (A->len <= B->len)
/* B cannot be a suffix of A unless A is equal to B, which is guaranteed
not to be equal by the hash table. */
return 0;
return memcmp (A->root.string + (A->len - B->len),
B->root.string, B->len - 1) == 0;
}
/* This function assigns final string table offsets for used strings,
merging strings matching suffixes of longer strings if possible. */
void
_bfd_elf_strtab_finalize (struct elf_strtab_hash *tab)
{
struct elf_strtab_hash_entry **array, **a, *e;
bfd_size_type size, amt;
/* GCC 2.91.66 (egcs-1.1.2) on i386 miscompiles this function when i is
a 64-bit bfd_size_type: a 64-bit target or --enable-64-bit-bfd.
Besides, indexing with a long long wouldn't give anything but extra
cycles. */
size_t i;
/* Sort the strings by suffix and length. */
amt = tab->size * sizeof (struct elf_strtab_hash_entry *);
array = (struct elf_strtab_hash_entry **) bfd_malloc (amt);
if (array == NULL)
goto alloc_failure;
for (i = 1, a = array; i < tab->size; ++i)
{
e = tab->array[i];
if (e->refcount)
{
*a++ = e;
/* Adjust the length to not include the zero terminator. */
e->len -= 1;
}
else
e->len = 0;
}
size = a - array;
if (size != 0)
{
qsort (array, size, sizeof (struct elf_strtab_hash_entry *), strrevcmp);
/* Loop over the sorted array and merge suffixes. Start from the
end because we want eg.
s1 -> "d"
s2 -> "bcd"
s3 -> "abcd"
to end up as
s3 -> "abcd"
s2 _____^
s1 _______^
ie. we don't want s1 pointing into the old s2. */
e = *--a;
e->len += 1;
while (--a >= array)
{
struct elf_strtab_hash_entry *cmp = *a;
cmp->len += 1;
if (is_suffix (e, cmp))
{
cmp->u.suffix = e;
cmp->len = -cmp->len;
}
else
e = cmp;
}
}
alloc_failure:
if (array)
free (array);
/* Assign positions to the strings we want to keep. */
size = 1;
for (i = 1; i < tab->size; ++i)
{
e = tab->array[i];
if (e->refcount && e->len > 0)
{
e->u.index = size;
size += e->len;
}
}
tab->sec_size = size;
/* Adjust the rest. */
for (i = 1; i < tab->size; ++i)
{
e = tab->array[i];
if (e->refcount && e->len < 0)
e->u.index = e->u.suffix->u.index + (e->u.suffix->len + e->len);
}
}

View File

@@ -0,0 +1,301 @@
/* VxWorks support for ELF
Copyright 2005, 2006, 2007, 2009, 2012 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., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
/* This file provides routines used by all VxWorks targets. */
#include "sysdep.h"
#include "bfd.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf-vxworks.h"
#include "elf/vxworks.h"
/* Return true if symbol NAME, as defined by ABFD, is one of the special
__GOTT_BASE__ or __GOTT_INDEX__ symbols. */
static bfd_boolean
elf_vxworks_gott_symbol_p (bfd *abfd, const char *name)
{
char leading;
leading = bfd_get_symbol_leading_char (abfd);
if (leading)
{
if (*name != leading)
return FALSE;
name++;
}
return (strcmp (name, "__GOTT_BASE__") == 0
|| strcmp (name, "__GOTT_INDEX__") == 0);
}
/* Tweak magic VxWorks symbols as they are loaded. */
bfd_boolean
elf_vxworks_add_symbol_hook (bfd *abfd,
struct bfd_link_info *info,
Elf_Internal_Sym *sym,
const char **namep,
flagword *flagsp,
asection **secp ATTRIBUTE_UNUSED,
bfd_vma *valp ATTRIBUTE_UNUSED)
{
/* Ideally these "magic" symbols would be exported by libc.so.1
which would be found via a DT_NEEDED tag, and then handled
specially by the linker at runtime. Except shared libraries
don't even link to libc.so.1 by default...
If the symbol is imported from, or will be put in a shared library,
give the symbol weak binding to get the desired samantics.
This transformation will be undone in
elf_i386_vxworks_link_output_symbol_hook. */
if ((info->shared || abfd->flags & DYNAMIC)
&& elf_vxworks_gott_symbol_p (abfd, *namep))
{
sym->st_info = ELF_ST_INFO (STB_WEAK, ELF_ST_TYPE (sym->st_info));
*flagsp |= BSF_WEAK;
}
return TRUE;
}
/* Perform VxWorks-specific handling of the create_dynamic_sections hook.
When creating an executable, set *SRELPLT2_OUT to the .rel(a).plt.unloaded
section. */
bfd_boolean
elf_vxworks_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info,
asection **srelplt2_out)
{
struct elf_link_hash_table *htab;
const struct elf_backend_data *bed;
asection *s;
htab = elf_hash_table (info);
bed = get_elf_backend_data (dynobj);
if (!info->shared)
{
s = bfd_make_section_anyway_with_flags (dynobj,
bed->default_use_rela_p
? ".rela.plt.unloaded"
: ".rel.plt.unloaded",
SEC_HAS_CONTENTS | SEC_IN_MEMORY
| SEC_READONLY
| SEC_LINKER_CREATED);
if (s == NULL
|| !bfd_set_section_alignment (dynobj, s, bed->s->log_file_align))
return FALSE;
*srelplt2_out = s;
}
/* Mark the GOT and PLT symbols as having relocations; they might
not, but we won't know for sure until we build the GOT in
finish_dynamic_symbol. Also make sure that the GOT symbol
is entered into the dynamic symbol table; the loader uses it
to initialize __GOTT_BASE__[__GOTT_INDEX__]. */
if (htab->hgot)
{
htab->hgot->indx = -2;
htab->hgot->other &= ~ELF_ST_VISIBILITY (-1);
htab->hgot->forced_local = 0;
if (!bfd_elf_link_record_dynamic_symbol (info, htab->hgot))
return FALSE;
}
if (htab->hplt)
{
htab->hplt->indx = -2;
htab->hplt->type = STT_FUNC;
}
return TRUE;
}
/* Tweak magic VxWorks symbols as they are written to the output file. */
int
elf_vxworks_link_output_symbol_hook (struct bfd_link_info *info
ATTRIBUTE_UNUSED,
const char *name,
Elf_Internal_Sym *sym,
asection *input_sec ATTRIBUTE_UNUSED,
struct elf_link_hash_entry *h)
{
/* Reverse the effects of the hack in elf_vxworks_add_symbol_hook. */
if (h
&& h->root.type == bfd_link_hash_undefweak
&& elf_vxworks_gott_symbol_p (h->root.u.undef.abfd, name))
sym->st_info = ELF_ST_INFO (STB_GLOBAL, ELF_ST_TYPE (sym->st_info));
return 1;
}
/* Copy relocations into the output file. Fixes up relocations against PLT
entries, then calls the generic routine. */
bfd_boolean
elf_vxworks_emit_relocs (bfd *output_bfd,
asection *input_section,
Elf_Internal_Shdr *input_rel_hdr,
Elf_Internal_Rela *internal_relocs,
struct elf_link_hash_entry **rel_hash)
{
const struct elf_backend_data *bed;
int j;
bed = get_elf_backend_data (output_bfd);
if (output_bfd->flags & (DYNAMIC|EXEC_P))
{
Elf_Internal_Rela *irela;
Elf_Internal_Rela *irelaend;
struct elf_link_hash_entry **hash_ptr;
for (irela = internal_relocs,
irelaend = irela + (NUM_SHDR_ENTRIES (input_rel_hdr)
* bed->s->int_rels_per_ext_rel),
hash_ptr = rel_hash;
irela < irelaend;
irela += bed->s->int_rels_per_ext_rel,
hash_ptr++)
{
if (*hash_ptr
&& (*hash_ptr)->def_dynamic
&& !(*hash_ptr)->def_regular
&& ((*hash_ptr)->root.type == bfd_link_hash_defined
|| (*hash_ptr)->root.type == bfd_link_hash_defweak)
&& (*hash_ptr)->root.u.def.section->output_section != NULL)
{
/* This is a relocation from an executable or shared
library against a symbol in a different shared
library. We are creating a definition in the output
file but it does not come from any of our normal (.o)
files. ie. a PLT stub. Normally this would be a
relocation against against SHN_UNDEF with the VMA of
the PLT stub. This upsets the VxWorks loader.
Convert it to a section-relative relocation. This
gets some other symbols (for instance .dynbss), but
is conservatively correct. */
for (j = 0; j < bed->s->int_rels_per_ext_rel; j++)
{
asection *sec = (*hash_ptr)->root.u.def.section;
int this_idx = sec->output_section->target_index;
irela[j].r_info
= ELF32_R_INFO (this_idx, ELF32_R_TYPE (irela[j].r_info));
irela[j].r_addend += (*hash_ptr)->root.u.def.value;
irela[j].r_addend += sec->output_offset;
}
/* Stop the generic routine adjusting this entry. */
*hash_ptr = NULL;
}
}
}
return _bfd_elf_link_output_relocs (output_bfd, input_section,
input_rel_hdr, internal_relocs,
rel_hash);
}
/* Set the sh_link and sh_info fields on the static plt relocation secton. */
void
elf_vxworks_final_write_processing (bfd *abfd,
bfd_boolean linker ATTRIBUTE_UNUSED)
{
asection * sec;
struct bfd_elf_section_data *d;
sec = bfd_get_section_by_name (abfd, ".rel.plt.unloaded");
if (!sec)
sec = bfd_get_section_by_name (abfd, ".rela.plt.unloaded");
if (!sec)
return;
d = elf_section_data (sec);
d->this_hdr.sh_link = elf_onesymtab (abfd);
sec = bfd_get_section_by_name (abfd, ".plt");
if (sec)
d->this_hdr.sh_info = elf_section_data (sec)->this_idx;
}
/* Add the dynamic entries required by VxWorks. These point to the
tls sections. */
bfd_boolean
elf_vxworks_add_dynamic_entries (bfd *output_bfd, struct bfd_link_info *info)
{
if (bfd_get_section_by_name (output_bfd, ".tls_data"))
{
if (!_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_DATA_START, 0)
|| !_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_DATA_SIZE, 0)
|| !_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_DATA_ALIGN, 0))
return FALSE;
}
if (bfd_get_section_by_name (output_bfd, ".tls_vars"))
{
if (!_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_VARS_START, 0)
|| !_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_VARS_SIZE, 0))
return FALSE;
}
return TRUE;
}
/* If *DYN is one of the VxWorks-specific dynamic entries, then fill
in the value now and return TRUE. Otherwise return FALSE. */
bfd_boolean
elf_vxworks_finish_dynamic_entry (bfd *output_bfd, Elf_Internal_Dyn *dyn)
{
asection *sec;
switch (dyn->d_tag)
{
default:
return FALSE;
case DT_VX_WRS_TLS_DATA_START:
sec = bfd_get_section_by_name (output_bfd, ".tls_data");
dyn->d_un.d_ptr = sec->vma;
break;
case DT_VX_WRS_TLS_DATA_SIZE:
sec = bfd_get_section_by_name (output_bfd, ".tls_data");
dyn->d_un.d_val = sec->size;
break;
case DT_VX_WRS_TLS_DATA_ALIGN:
sec = bfd_get_section_by_name (output_bfd, ".tls_data");
dyn->d_un.d_val
= (bfd_size_type)1 << bfd_get_section_alignment (output_bfd,
sec);
break;
case DT_VX_WRS_TLS_VARS_START:
sec = bfd_get_section_by_name (output_bfd, ".tls_vars");
dyn->d_un.d_ptr = sec->vma;
break;
case DT_VX_WRS_TLS_VARS_SIZE:
sec = bfd_get_section_by_name (output_bfd, ".tls_vars");
dyn->d_un.d_val = sec->size;
break;
}
return TRUE;
}

View File

@@ -0,0 +1,38 @@
/* VxWorks support for ELF
Copyright 2005, 2006, 2007 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., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
#include "elf/common.h"
#include "elf/internal.h"
bfd_boolean elf_vxworks_add_symbol_hook
(bfd *, struct bfd_link_info *, Elf_Internal_Sym *, const char **,
flagword *, asection **, bfd_vma *);
bfd_boolean elf_vxworks_link_output_symbol_hook
(struct bfd_link_info *, const char *name, Elf_Internal_Sym *,
asection *, struct elf_link_hash_entry *);
bfd_boolean elf_vxworks_emit_relocs
(bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *,
struct elf_link_hash_entry **);
void elf_vxworks_final_write_processing (bfd *, bfd_boolean);
bfd_boolean elf_vxworks_create_dynamic_sections
(bfd *, struct bfd_link_info *, asection **);
bfd_boolean elf_vxworks_add_dynamic_entries (bfd *, struct bfd_link_info *);
bfd_boolean elf_vxworks_finish_dynamic_entry (bfd *, Elf_Internal_Dyn *);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,103 @@
/* Generic support for 32-bit ELF
Copyright 1993, 1995, 1998, 1999, 2001, 2002, 2004, 2005, 2007
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"
#include "libbfd.h"
#include "elf-bfd.h"
/* This does not include any relocation information, but should be
good enough for GDB or objdump to read the file. */
static reloc_howto_type dummy =
HOWTO (0, /* type */
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
NULL, /* special_function */
"UNKNOWN", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
FALSE); /* pcrel_offset */
static void
elf_generic_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
arelent *bfd_reloc,
Elf_Internal_Rela *elf_reloc ATTRIBUTE_UNUSED)
{
bfd_reloc->howto = &dummy;
}
static void
elf_generic_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
arelent *bfd_reloc,
Elf_Internal_Rela *elf_reloc ATTRIBUTE_UNUSED)
{
bfd_reloc->howto = &dummy;
}
static void
check_for_relocs (bfd * abfd, asection * o, void * failed)
{
if ((o->flags & SEC_RELOC) != 0)
{
Elf_Internal_Ehdr *ehdrp;
ehdrp = elf_elfheader (abfd);
_bfd_error_handler (_("%B: Relocations in generic ELF (EM: %d)"),
abfd, ehdrp->e_machine);
bfd_set_error (bfd_error_wrong_format);
* (bfd_boolean *) failed = TRUE;
}
}
static bfd_boolean
elf32_generic_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
{
bfd_boolean failed = FALSE;
/* Check if there are any relocations. */
bfd_map_over_sections (abfd, check_for_relocs, & failed);
if (failed)
return FALSE;
return bfd_elf_link_add_symbols (abfd, info);
}
#define TARGET_LITTLE_SYM bfd_elf32_little_generic_vec
#define TARGET_LITTLE_NAME "elf32-little"
#define TARGET_BIG_SYM bfd_elf32_big_generic_vec
#define TARGET_BIG_NAME "elf32-big"
#define ELF_ARCH bfd_arch_unknown
#define ELF_MACHINE_CODE EM_NONE
#define ELF_MAXPAGESIZE 0x1
#define bfd_elf32_bfd_reloc_type_lookup bfd_default_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup _bfd_norelocs_bfd_reloc_name_lookup
#define bfd_elf32_bfd_link_add_symbols elf32_generic_link_add_symbols
#define elf_info_to_howto elf_generic_info_to_howto
#define elf_info_to_howto_rel elf_generic_info_to_howto_rel
#include "elf32-target.h"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,999 @@
/* Target definitions for 32-bit ELF
Copyright 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 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. */
/* This structure contains everything that BFD knows about a target.
It includes things like its byte order, name, what routines to call
to do various operations, etc. Every BFD points to a target structure
with its "xvec" member.
There are two such structures here: one for big-endian machines and
one for little-endian machines. */
#ifndef bfd_elf32_close_and_cleanup
#define bfd_elf32_close_and_cleanup _bfd_elf_close_and_cleanup
#endif
#ifndef bfd_elf32_bfd_free_cached_info
#define bfd_elf32_bfd_free_cached_info _bfd_free_cached_info
#endif
#ifndef bfd_elf32_get_section_contents
#define bfd_elf32_get_section_contents _bfd_generic_get_section_contents
#endif
#define bfd_elf32_canonicalize_dynamic_symtab \
_bfd_elf_canonicalize_dynamic_symtab
#ifndef bfd_elf32_get_synthetic_symtab
#define bfd_elf32_get_synthetic_symtab \
_bfd_elf_get_synthetic_symtab
#endif
#ifndef bfd_elf32_canonicalize_reloc
#define bfd_elf32_canonicalize_reloc _bfd_elf_canonicalize_reloc
#endif
#ifndef bfd_elf32_find_nearest_line
#define bfd_elf32_find_nearest_line _bfd_elf_find_nearest_line
#endif
#ifndef bfd_elf32_find_inliner_info
#define bfd_elf32_find_inliner_info _bfd_elf_find_inliner_info
#endif
#define bfd_elf32_read_minisymbols _bfd_elf_read_minisymbols
#define bfd_elf32_minisymbol_to_symbol _bfd_elf_minisymbol_to_symbol
#define bfd_elf32_get_dynamic_symtab_upper_bound \
_bfd_elf_get_dynamic_symtab_upper_bound
#define bfd_elf32_get_lineno _bfd_elf_get_lineno
#ifndef bfd_elf32_get_reloc_upper_bound
#define bfd_elf32_get_reloc_upper_bound _bfd_elf_get_reloc_upper_bound
#endif
#ifndef bfd_elf32_get_symbol_info
#define bfd_elf32_get_symbol_info _bfd_elf_get_symbol_info
#endif
#define bfd_elf32_canonicalize_symtab _bfd_elf_canonicalize_symtab
#define bfd_elf32_get_symtab_upper_bound _bfd_elf_get_symtab_upper_bound
#define bfd_elf32_make_empty_symbol _bfd_elf_make_empty_symbol
#ifndef bfd_elf32_new_section_hook
#define bfd_elf32_new_section_hook _bfd_elf_new_section_hook
#endif
#define bfd_elf32_set_arch_mach _bfd_elf_set_arch_mach
#ifndef bfd_elf32_set_section_contents
#define bfd_elf32_set_section_contents _bfd_elf_set_section_contents
#endif
#define bfd_elf32_sizeof_headers _bfd_elf_sizeof_headers
#define bfd_elf32_write_object_contents _bfd_elf_write_object_contents
#define bfd_elf32_write_corefile_contents _bfd_elf_write_corefile_contents
#define bfd_elf32_get_section_contents_in_window \
_bfd_generic_get_section_contents_in_window
#ifndef elf_backend_can_refcount
#define elf_backend_can_refcount 0
#endif
#ifndef elf_backend_want_got_plt
#define elf_backend_want_got_plt 0
#endif
#ifndef elf_backend_plt_readonly
#define elf_backend_plt_readonly 0
#endif
#ifndef elf_backend_want_plt_sym
#define elf_backend_want_plt_sym 0
#endif
#ifndef elf_backend_plt_not_loaded
#define elf_backend_plt_not_loaded 0
#endif
#ifndef elf_backend_plt_alignment
#define elf_backend_plt_alignment 2
#endif
#ifndef elf_backend_want_dynbss
#define elf_backend_want_dynbss 1
#endif
#ifndef elf_backend_want_p_paddr_set_to_zero
#define elf_backend_want_p_paddr_set_to_zero 0
#endif
#ifndef elf_backend_default_execstack
#define elf_backend_default_execstack 1
#endif
#ifndef elf_backend_stack_align
#define elf_backend_stack_align 16
#endif
#define bfd_elf32_bfd_debug_info_start bfd_void
#define bfd_elf32_bfd_debug_info_end bfd_void
#define bfd_elf32_bfd_debug_info_accumulate \
((void (*) (bfd*, struct bfd_section *)) bfd_void)
#ifndef bfd_elf32_bfd_get_relocated_section_contents
#define bfd_elf32_bfd_get_relocated_section_contents \
bfd_generic_get_relocated_section_contents
#endif
#ifndef bfd_elf32_bfd_relax_section
#define bfd_elf32_bfd_relax_section bfd_generic_relax_section
#endif
#ifndef elf_backend_can_gc_sections
#define elf_backend_can_gc_sections 0
#endif
#ifndef elf_backend_can_refcount
#define elf_backend_can_refcount 0
#endif
#ifndef elf_backend_want_got_sym
#define elf_backend_want_got_sym 1
#endif
#ifndef elf_backend_gc_keep
#define elf_backend_gc_keep _bfd_elf_gc_keep
#endif
#ifndef elf_backend_gc_mark_dynamic_ref
#define elf_backend_gc_mark_dynamic_ref bfd_elf_gc_mark_dynamic_ref_symbol
#endif
#ifndef elf_backend_gc_mark_hook
#define elf_backend_gc_mark_hook _bfd_elf_gc_mark_hook
#endif
#ifndef elf_backend_gc_mark_extra_sections
#define elf_backend_gc_mark_extra_sections _bfd_elf_gc_mark_extra_sections
#endif
#ifndef elf_backend_gc_sweep_hook
#define elf_backend_gc_sweep_hook NULL
#endif
#ifndef bfd_elf32_bfd_gc_sections
#define bfd_elf32_bfd_gc_sections bfd_elf_gc_sections
#endif
#ifndef bfd_elf32_bfd_merge_sections
#define bfd_elf32_bfd_merge_sections \
_bfd_elf_merge_sections
#endif
#ifndef bfd_elf32_bfd_is_group_section
#define bfd_elf32_bfd_is_group_section bfd_elf_is_group_section
#endif
#ifndef bfd_elf32_bfd_discard_group
#define bfd_elf32_bfd_discard_group bfd_generic_discard_group
#endif
#ifndef bfd_elf32_section_already_linked
#define bfd_elf32_section_already_linked \
_bfd_elf_section_already_linked
#endif
#ifndef bfd_elf32_bfd_define_common_symbol
#define bfd_elf32_bfd_define_common_symbol bfd_generic_define_common_symbol
#endif
#ifndef bfd_elf32_bfd_lookup_section_flags
#define bfd_elf32_bfd_lookup_section_flags bfd_elf_lookup_section_flags
#endif
#ifndef bfd_elf32_bfd_make_debug_symbol
#define bfd_elf32_bfd_make_debug_symbol \
((asymbol * (*) (bfd *, void *, unsigned long)) bfd_nullvoidptr)
#endif
#ifndef bfd_elf32_bfd_copy_private_symbol_data
#define bfd_elf32_bfd_copy_private_symbol_data \
_bfd_elf_copy_private_symbol_data
#endif
#ifndef bfd_elf32_bfd_copy_private_section_data
#define bfd_elf32_bfd_copy_private_section_data \
_bfd_elf_copy_private_section_data
#endif
#ifndef bfd_elf32_bfd_copy_private_header_data
#define bfd_elf32_bfd_copy_private_header_data \
_bfd_elf_copy_private_header_data
#endif
#ifndef bfd_elf32_bfd_copy_private_bfd_data
#define bfd_elf32_bfd_copy_private_bfd_data \
_bfd_elf_copy_private_bfd_data
#endif
#ifndef bfd_elf32_bfd_print_private_bfd_data
#define bfd_elf32_bfd_print_private_bfd_data \
_bfd_elf_print_private_bfd_data
#endif
#ifndef bfd_elf32_bfd_merge_private_bfd_data
#define bfd_elf32_bfd_merge_private_bfd_data \
((bfd_boolean (*) (bfd *, bfd *)) bfd_true)
#endif
#ifndef bfd_elf32_bfd_set_private_flags
#define bfd_elf32_bfd_set_private_flags \
((bfd_boolean (*) (bfd *, flagword)) bfd_true)
#endif
#ifndef bfd_elf32_bfd_is_local_label_name
#define bfd_elf32_bfd_is_local_label_name _bfd_elf_is_local_label_name
#endif
#ifndef bfd_elf32_bfd_is_target_special_symbol
#define bfd_elf32_bfd_is_target_special_symbol \
((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
#endif
#ifndef bfd_elf32_get_dynamic_reloc_upper_bound
#define bfd_elf32_get_dynamic_reloc_upper_bound \
_bfd_elf_get_dynamic_reloc_upper_bound
#endif
#ifndef bfd_elf32_canonicalize_dynamic_reloc
#define bfd_elf32_canonicalize_dynamic_reloc \
_bfd_elf_canonicalize_dynamic_reloc
#endif
#ifdef elf_backend_relocate_section
#ifndef bfd_elf32_bfd_link_hash_table_create
#define bfd_elf32_bfd_link_hash_table_create _bfd_elf_link_hash_table_create
#endif
#ifndef bfd_elf32_bfd_link_hash_table_free
#define bfd_elf32_bfd_link_hash_table_free _bfd_elf_link_hash_table_free
#endif
#ifndef bfd_elf32_bfd_link_add_symbols
#define bfd_elf32_bfd_link_add_symbols bfd_elf_link_add_symbols
#endif
#ifndef bfd_elf32_bfd_final_link
#define bfd_elf32_bfd_final_link bfd_elf_final_link
#endif
#else /* ! defined (elf_backend_relocate_section) */
/* If no backend relocate_section routine, use the generic linker.
Note - this will prevent the port from being able to use some of
the other features of the ELF linker, because the generic hash structure
does not have the fields needed by the ELF linker. In particular it
means that linking directly to S-records will not work. */
#ifndef bfd_elf32_bfd_link_hash_table_create
#define bfd_elf32_bfd_link_hash_table_create \
_bfd_generic_link_hash_table_create
#endif
#ifndef bfd_elf32_bfd_link_hash_table_free
#define bfd_elf32_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
#endif
#ifndef bfd_elf32_bfd_link_add_symbols
#define bfd_elf32_bfd_link_add_symbols _bfd_generic_link_add_symbols
#endif
#ifndef bfd_elf32_bfd_final_link
#define bfd_elf32_bfd_final_link _bfd_generic_final_link
#endif
#endif /* ! defined (elf_backend_relocate_section) */
#ifndef bfd_elf32_bfd_link_just_syms
#define bfd_elf32_bfd_link_just_syms _bfd_elf_link_just_syms
#endif
#ifndef bfd_elf32_bfd_copy_link_hash_symbol_type
#define bfd_elf32_bfd_copy_link_hash_symbol_type \
_bfd_elf_copy_link_hash_symbol_type
#endif
#ifndef bfd_elf32_bfd_link_split_section
#define bfd_elf32_bfd_link_split_section _bfd_generic_link_split_section
#endif
#ifndef bfd_elf32_archive_p
#define bfd_elf32_archive_p bfd_generic_archive_p
#endif
#ifndef bfd_elf32_write_archive_contents
#define bfd_elf32_write_archive_contents _bfd_write_archive_contents
#endif
#ifndef bfd_elf32_mkobject
#define bfd_elf32_mkobject bfd_elf_make_object
#endif
#ifndef bfd_elf32_mkcorefile
#define bfd_elf32_mkcorefile bfd_elf_mkcorefile
#endif
#ifndef bfd_elf32_mkarchive
#define bfd_elf32_mkarchive _bfd_generic_mkarchive
#endif
#ifndef bfd_elf32_print_symbol
#define bfd_elf32_print_symbol bfd_elf_print_symbol
#endif
#ifndef elf_symbol_leading_char
#define elf_symbol_leading_char 0
#endif
#ifndef elf_info_to_howto
#define elf_info_to_howto 0
#endif
#ifndef elf_info_to_howto_rel
#define elf_info_to_howto_rel 0
#endif
#ifndef elf_backend_arch_data
#define elf_backend_arch_data NULL
#endif
#ifndef ELF_TARGET_ID
#define ELF_TARGET_ID GENERIC_ELF_DATA
#endif
#ifndef ELF_OSABI
#define ELF_OSABI ELFOSABI_NONE
#endif
#ifndef ELF_MAXPAGESIZE
# error ELF_MAXPAGESIZE is not defined
#define ELF_MAXPAGESIZE 1
#endif
#ifndef ELF_COMMONPAGESIZE
#define ELF_COMMONPAGESIZE ELF_MAXPAGESIZE
#endif
#ifndef ELF_MINPAGESIZE
#define ELF_MINPAGESIZE ELF_COMMONPAGESIZE
#endif
#if ELF_COMMONPAGESIZE > ELF_MAXPAGESIZE
# error ELF_COMMONPAGESIZE > ELF_MAXPAGESIZE
#endif
#if ELF_MINPAGESIZE > ELF_COMMONPAGESIZE
# error ELF_MINPAGESIZE > ELF_COMMONPAGESIZE
#endif
#ifndef ELF_DYNAMIC_SEC_FLAGS
/* Note that we set the SEC_IN_MEMORY flag for these sections. */
#define ELF_DYNAMIC_SEC_FLAGS \
(SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS \
| SEC_IN_MEMORY | SEC_LINKER_CREATED)
#endif
#ifndef elf_backend_collect
#define elf_backend_collect FALSE
#endif
#ifndef elf_backend_type_change_ok
#define elf_backend_type_change_ok FALSE
#endif
#ifndef elf_backend_sym_is_global
#define elf_backend_sym_is_global 0
#endif
#ifndef elf_backend_object_p
#define elf_backend_object_p 0
#endif
#ifndef elf_backend_symbol_processing
#define elf_backend_symbol_processing 0
#endif
#ifndef elf_backend_symbol_table_processing
#define elf_backend_symbol_table_processing 0
#endif
#ifndef elf_backend_get_symbol_type
#define elf_backend_get_symbol_type 0
#endif
#ifndef elf_backend_archive_symbol_lookup
#define elf_backend_archive_symbol_lookup _bfd_elf_archive_symbol_lookup
#endif
#ifndef elf_backend_name_local_section_symbols
#define elf_backend_name_local_section_symbols 0
#endif
#ifndef elf_backend_section_processing
#define elf_backend_section_processing 0
#endif
#ifndef elf_backend_section_from_shdr
#define elf_backend_section_from_shdr _bfd_elf_make_section_from_shdr
#endif
#ifndef elf_backend_section_flags
#define elf_backend_section_flags 0
#endif
#ifndef elf_backend_get_sec_type_attr
#define elf_backend_get_sec_type_attr _bfd_elf_get_sec_type_attr
#endif
#ifndef elf_backend_section_from_phdr
#define elf_backend_section_from_phdr _bfd_elf_make_section_from_phdr
#endif
#ifndef elf_backend_fake_sections
#define elf_backend_fake_sections 0
#endif
#ifndef elf_backend_section_from_bfd_section
#define elf_backend_section_from_bfd_section 0
#endif
#ifndef elf_backend_add_symbol_hook
#define elf_backend_add_symbol_hook 0
#endif
#ifndef elf_backend_link_output_symbol_hook
#define elf_backend_link_output_symbol_hook 0
#endif
#ifndef elf_backend_create_dynamic_sections
#define elf_backend_create_dynamic_sections 0
#endif
#ifndef elf_backend_omit_section_dynsym
#define elf_backend_omit_section_dynsym _bfd_elf_link_omit_section_dynsym
#endif
#ifndef elf_backend_relocs_compatible
#define elf_backend_relocs_compatible _bfd_elf_default_relocs_compatible
#endif
#ifndef elf_backend_check_relocs
#define elf_backend_check_relocs 0
#endif
#ifndef elf_backend_check_directives
#define elf_backend_check_directives 0
#endif
#ifndef elf_backend_notice_as_needed
#define elf_backend_notice_as_needed _bfd_elf_notice_as_needed
#endif
#ifndef elf_backend_adjust_dynamic_symbol
#define elf_backend_adjust_dynamic_symbol 0
#endif
#ifndef elf_backend_always_size_sections
#define elf_backend_always_size_sections 0
#endif
#ifndef elf_backend_size_dynamic_sections
#define elf_backend_size_dynamic_sections 0
#endif
#ifndef elf_backend_init_index_section
#define elf_backend_init_index_section \
((void (*) (bfd *, struct bfd_link_info *)) bfd_void)
#endif
#ifndef elf_backend_relocate_section
#define elf_backend_relocate_section 0
#endif
#ifndef elf_backend_finish_dynamic_symbol
#define elf_backend_finish_dynamic_symbol 0
#endif
#ifndef elf_backend_finish_dynamic_sections
#define elf_backend_finish_dynamic_sections 0
#endif
#ifndef elf_backend_begin_write_processing
#define elf_backend_begin_write_processing 0
#endif
#ifndef elf_backend_final_write_processing
#define elf_backend_final_write_processing 0
#endif
#ifndef elf_backend_additional_program_headers
#define elf_backend_additional_program_headers 0
#endif
#ifndef elf_backend_modify_segment_map
#define elf_backend_modify_segment_map 0
#endif
#ifndef elf_backend_modify_program_headers
#define elf_backend_modify_program_headers 0
#endif
#ifndef elf_backend_ecoff_debug_swap
#define elf_backend_ecoff_debug_swap 0
#endif
#ifndef elf_backend_bfd_from_remote_memory
#define elf_backend_bfd_from_remote_memory _bfd_elf32_bfd_from_remote_memory
#endif
#ifndef elf_backend_got_header_size
#define elf_backend_got_header_size 0
#endif
#ifndef elf_backend_got_elt_size
#define elf_backend_got_elt_size _bfd_elf_default_got_elt_size
#endif
#ifndef elf_backend_obj_attrs_vendor
#define elf_backend_obj_attrs_vendor NULL
#endif
#ifndef elf_backend_obj_attrs_section
#define elf_backend_obj_attrs_section NULL
#endif
#ifndef elf_backend_obj_attrs_arg_type
#define elf_backend_obj_attrs_arg_type NULL
#endif
#ifndef elf_backend_obj_attrs_section_type
#define elf_backend_obj_attrs_section_type SHT_GNU_ATTRIBUTES
#endif
#ifndef elf_backend_obj_attrs_order
#define elf_backend_obj_attrs_order NULL
#endif
#ifndef elf_backend_obj_attrs_handle_unknown
#define elf_backend_obj_attrs_handle_unknown NULL
#endif
#ifndef elf_backend_static_tls_alignment
#define elf_backend_static_tls_alignment 1
#endif
#ifndef elf_backend_post_process_headers
#define elf_backend_post_process_headers NULL
#endif
#ifndef elf_backend_print_symbol_all
#define elf_backend_print_symbol_all NULL
#endif
#ifndef elf_backend_output_arch_local_syms
#define elf_backend_output_arch_local_syms NULL
#endif
#ifndef elf_backend_output_arch_syms
#define elf_backend_output_arch_syms NULL
#endif
#ifndef elf_backend_copy_indirect_symbol
#define elf_backend_copy_indirect_symbol _bfd_elf_link_hash_copy_indirect
#endif
#ifndef elf_backend_hide_symbol
#define elf_backend_hide_symbol _bfd_elf_link_hash_hide_symbol
#endif
#ifndef elf_backend_fixup_symbol
#define elf_backend_fixup_symbol NULL
#endif
#ifndef elf_backend_merge_symbol_attribute
#define elf_backend_merge_symbol_attribute NULL
#endif
#ifndef elf_backend_get_target_dtag
#define elf_backend_get_target_dtag NULL
#endif
#ifndef elf_backend_ignore_undef_symbol
#define elf_backend_ignore_undef_symbol NULL
#endif
#ifndef elf_backend_emit_relocs
#define elf_backend_emit_relocs _bfd_elf_link_output_relocs
#endif
#ifndef elf_backend_count_relocs
#define elf_backend_count_relocs NULL
#endif
#ifndef elf_backend_grok_prstatus
#define elf_backend_grok_prstatus NULL
#endif
#ifndef elf_backend_grok_psinfo
#define elf_backend_grok_psinfo NULL
#endif
#ifndef elf_backend_write_core_note
#define elf_backend_write_core_note NULL
#endif
#ifndef elf_backend_lookup_section_flags_hook
#define elf_backend_lookup_section_flags_hook NULL
#endif
#ifndef elf_backend_reloc_type_class
#define elf_backend_reloc_type_class _bfd_elf_reloc_type_class
#endif
#ifndef elf_backend_discard_info
#define elf_backend_discard_info NULL
#endif
#ifndef elf_backend_ignore_discarded_relocs
#define elf_backend_ignore_discarded_relocs NULL
#endif
#ifndef elf_backend_action_discarded
#define elf_backend_action_discarded _bfd_elf_default_action_discarded
#endif
#ifndef elf_backend_eh_frame_address_size
#define elf_backend_eh_frame_address_size _bfd_elf_eh_frame_address_size
#endif
#ifndef elf_backend_can_make_relative_eh_frame
#define elf_backend_can_make_relative_eh_frame _bfd_elf_can_make_relative
#endif
#ifndef elf_backend_can_make_lsda_relative_eh_frame
#define elf_backend_can_make_lsda_relative_eh_frame _bfd_elf_can_make_relative
#endif
#ifndef elf_backend_encode_eh_address
#define elf_backend_encode_eh_address _bfd_elf_encode_eh_address
#endif
#ifndef elf_backend_write_section
#define elf_backend_write_section NULL
#endif
#ifndef elf_backend_mips_irix_compat
#define elf_backend_mips_irix_compat NULL
#endif
#ifndef elf_backend_mips_rtype_to_howto
#define elf_backend_mips_rtype_to_howto NULL
#endif
/* Previously, backends could only use SHT_REL or SHT_RELA relocation
sections, but not both. They defined USE_REL to indicate SHT_REL
sections, and left it undefined to indicated SHT_RELA sections.
For backwards compatibility, we still support this usage. */
#ifndef USE_REL
#define USE_REL 0
#endif
/* Use these in new code. */
#ifndef elf_backend_may_use_rel_p
#define elf_backend_may_use_rel_p USE_REL
#endif
#ifndef elf_backend_may_use_rela_p
#define elf_backend_may_use_rela_p !USE_REL
#endif
#ifndef elf_backend_default_use_rela_p
#define elf_backend_default_use_rela_p !USE_REL
#endif
#ifndef elf_backend_rela_plts_and_copies_p
#define elf_backend_rela_plts_and_copies_p elf_backend_default_use_rela_p
#endif
#ifndef elf_backend_rela_normal
#define elf_backend_rela_normal 0
#endif
#ifndef elf_backend_plt_sym_val
#define elf_backend_plt_sym_val NULL
#endif
#ifndef elf_backend_relplt_name
#define elf_backend_relplt_name NULL
#endif
#ifndef ELF_MACHINE_ALT1
#define ELF_MACHINE_ALT1 0
#endif
#ifndef ELF_MACHINE_ALT2
#define ELF_MACHINE_ALT2 0
#endif
#ifndef elf_backend_size_info
#define elf_backend_size_info _bfd_elf32_size_info
#endif
#ifndef elf_backend_special_sections
#define elf_backend_special_sections NULL
#endif
#ifndef elf_backend_sign_extend_vma
#define elf_backend_sign_extend_vma 0
#endif
#ifndef elf_backend_link_order_error_handler
#define elf_backend_link_order_error_handler _bfd_default_error_handler
#endif
#ifndef elf_backend_common_definition
#define elf_backend_common_definition _bfd_elf_common_definition
#endif
#ifndef elf_backend_common_section_index
#define elf_backend_common_section_index _bfd_elf_common_section_index
#endif
#ifndef elf_backend_common_section
#define elf_backend_common_section _bfd_elf_common_section
#endif
#ifndef elf_backend_merge_symbol
#define elf_backend_merge_symbol NULL
#endif
#ifndef elf_backend_hash_symbol
#define elf_backend_hash_symbol _bfd_elf_hash_symbol
#endif
#ifndef elf_backend_is_function_type
#define elf_backend_is_function_type _bfd_elf_is_function_type
#endif
#ifndef elf_backend_maybe_function_sym
#define elf_backend_maybe_function_sym _bfd_elf_maybe_function_sym
#endif
#ifndef elf_match_priority
#define elf_match_priority \
(ELF_ARCH == bfd_arch_unknown ? 2 : ELF_OSABI == ELFOSABI_NONE ? 1 : 0)
#endif
extern const struct elf_size_info _bfd_elf32_size_info;
static struct elf_backend_data elf32_bed =
{
ELF_ARCH, /* arch */
ELF_TARGET_ID, /* target_id */
ELF_MACHINE_CODE, /* elf_machine_code */
ELF_OSABI, /* elf_osabi */
ELF_MAXPAGESIZE, /* maxpagesize */
ELF_MINPAGESIZE, /* minpagesize */
ELF_COMMONPAGESIZE, /* commonpagesize */
ELF_DYNAMIC_SEC_FLAGS, /* dynamic_sec_flags */
elf_backend_arch_data,
elf_info_to_howto,
elf_info_to_howto_rel,
elf_backend_sym_is_global,
elf_backend_object_p,
elf_backend_symbol_processing,
elf_backend_symbol_table_processing,
elf_backend_get_symbol_type,
elf_backend_archive_symbol_lookup,
elf_backend_name_local_section_symbols,
elf_backend_section_processing,
elf_backend_section_from_shdr,
elf_backend_section_flags,
elf_backend_get_sec_type_attr,
elf_backend_section_from_phdr,
elf_backend_fake_sections,
elf_backend_section_from_bfd_section,
elf_backend_add_symbol_hook,
elf_backend_link_output_symbol_hook,
elf_backend_create_dynamic_sections,
elf_backend_omit_section_dynsym,
elf_backend_relocs_compatible,
elf_backend_check_relocs,
elf_backend_check_directives,
elf_backend_notice_as_needed,
elf_backend_adjust_dynamic_symbol,
elf_backend_always_size_sections,
elf_backend_size_dynamic_sections,
elf_backend_init_index_section,
elf_backend_relocate_section,
elf_backend_finish_dynamic_symbol,
elf_backend_finish_dynamic_sections,
elf_backend_begin_write_processing,
elf_backend_final_write_processing,
elf_backend_additional_program_headers,
elf_backend_modify_segment_map,
elf_backend_modify_program_headers,
elf_backend_gc_keep,
elf_backend_gc_mark_dynamic_ref,
elf_backend_gc_mark_hook,
elf_backend_gc_mark_extra_sections,
elf_backend_gc_sweep_hook,
elf_backend_post_process_headers,
elf_backend_print_symbol_all,
elf_backend_output_arch_local_syms,
elf_backend_output_arch_syms,
elf_backend_copy_indirect_symbol,
elf_backend_hide_symbol,
elf_backend_fixup_symbol,
elf_backend_merge_symbol_attribute,
elf_backend_get_target_dtag,
elf_backend_ignore_undef_symbol,
elf_backend_emit_relocs,
elf_backend_count_relocs,
elf_backend_grok_prstatus,
elf_backend_grok_psinfo,
elf_backend_write_core_note,
elf_backend_lookup_section_flags_hook,
elf_backend_reloc_type_class,
elf_backend_discard_info,
elf_backend_ignore_discarded_relocs,
elf_backend_action_discarded,
elf_backend_eh_frame_address_size,
elf_backend_can_make_relative_eh_frame,
elf_backend_can_make_lsda_relative_eh_frame,
elf_backend_encode_eh_address,
elf_backend_write_section,
elf_backend_mips_irix_compat,
elf_backend_mips_rtype_to_howto,
elf_backend_ecoff_debug_swap,
elf_backend_bfd_from_remote_memory,
elf_backend_plt_sym_val,
elf_backend_common_definition,
elf_backend_common_section_index,
elf_backend_common_section,
elf_backend_merge_symbol,
elf_backend_hash_symbol,
elf_backend_is_function_type,
elf_backend_maybe_function_sym,
elf_backend_link_order_error_handler,
elf_backend_relplt_name,
ELF_MACHINE_ALT1,
ELF_MACHINE_ALT2,
&elf_backend_size_info,
elf_backend_special_sections,
elf_backend_got_header_size,
elf_backend_got_elt_size,
elf_backend_obj_attrs_vendor,
elf_backend_obj_attrs_section,
elf_backend_obj_attrs_arg_type,
elf_backend_obj_attrs_section_type,
elf_backend_obj_attrs_order,
elf_backend_obj_attrs_handle_unknown,
elf_backend_static_tls_alignment,
elf_backend_stack_align,
elf_backend_collect,
elf_backend_type_change_ok,
elf_backend_may_use_rel_p,
elf_backend_may_use_rela_p,
elf_backend_default_use_rela_p,
elf_backend_rela_plts_and_copies_p,
elf_backend_rela_normal,
elf_backend_sign_extend_vma,
elf_backend_want_got_plt,
elf_backend_plt_readonly,
elf_backend_want_plt_sym,
elf_backend_plt_not_loaded,
elf_backend_plt_alignment,
elf_backend_can_gc_sections,
elf_backend_can_refcount,
elf_backend_want_got_sym,
elf_backend_want_dynbss,
elf_backend_want_p_paddr_set_to_zero,
elf_backend_default_execstack
};
/* Forward declaration for use when initialising alternative_target field. */
#ifdef TARGET_LITTLE_SYM
extern const bfd_target TARGET_LITTLE_SYM;
#endif
#ifdef TARGET_BIG_SYM
const bfd_target TARGET_BIG_SYM =
{
/* name: identify kind of target */
TARGET_BIG_NAME,
/* flavour: general indication about file */
bfd_target_elf_flavour,
/* byteorder: data is big endian */
BFD_ENDIAN_BIG,
/* header_byteorder: header is also big endian */
BFD_ENDIAN_BIG,
/* object_flags: mask of all file flags */
(HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS
| DYNAMIC | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS),
/* section_flags: mask of all section flags */
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY
| SEC_CODE | SEC_DATA | SEC_DEBUGGING | SEC_EXCLUDE | SEC_SORT_ENTRIES
| SEC_SMALL_DATA | SEC_MERGE | SEC_STRINGS | SEC_GROUP),
/* leading_symbol_char: is the first char of a user symbol
predictable, and if so what is it */
elf_symbol_leading_char,
/* ar_pad_char: pad character for filenames within an archive header
FIXME: this really has nothing to do with ELF, this is a characteristic
of the archiver and/or os and should be independently tunable */
'/',
/* ar_max_namelen: maximum number of characters in an archive header
FIXME: this really has nothing to do with ELF, this is a characteristic
of the archiver and should be independently tunable. The System V ABI,
Chapter 7 (Formats & Protocols), Archive section sets this as 15. */
15,
elf_match_priority,
/* Routines to byte-swap various sized integers from the data sections */
bfd_getb64, bfd_getb_signed_64, bfd_putb64,
bfd_getb32, bfd_getb_signed_32, bfd_putb32,
bfd_getb16, bfd_getb_signed_16, bfd_putb16,
/* Routines to byte-swap various sized integers from the file headers */
bfd_getb64, bfd_getb_signed_64, bfd_putb64,
bfd_getb32, bfd_getb_signed_32, bfd_putb32,
bfd_getb16, bfd_getb_signed_16, bfd_putb16,
/* bfd_check_format: check the format of a file being read */
{ _bfd_dummy_target, /* unknown format */
bfd_elf32_object_p, /* assembler/linker output (object file) */
bfd_elf32_archive_p, /* an archive */
bfd_elf32_core_file_p /* a core file */
},
/* bfd_set_format: set the format of a file being written */
{ bfd_false,
bfd_elf32_mkobject,
bfd_elf32_mkarchive,
bfd_elf32_mkcorefile
},
/* bfd_write_contents: write cached information into a file being written */
{ bfd_false,
bfd_elf32_write_object_contents,
bfd_elf32_write_archive_contents,
bfd_elf32_write_corefile_contents,
},
BFD_JUMP_TABLE_GENERIC (bfd_elf32),
BFD_JUMP_TABLE_COPY (bfd_elf32),
BFD_JUMP_TABLE_CORE (bfd_elf32),
#ifdef bfd_elf32_archive_functions
BFD_JUMP_TABLE_ARCHIVE (bfd_elf32_archive),
#else
BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
#endif
BFD_JUMP_TABLE_SYMBOLS (bfd_elf32),
BFD_JUMP_TABLE_RELOCS (bfd_elf32),
BFD_JUMP_TABLE_WRITE (bfd_elf32),
BFD_JUMP_TABLE_LINK (bfd_elf32),
BFD_JUMP_TABLE_DYNAMIC (bfd_elf32),
/* Alternative endian target. */
#ifdef TARGET_LITTLE_SYM
& TARGET_LITTLE_SYM,
#else
NULL,
#endif
/* backend_data: */
&elf32_bed
};
#endif
#ifdef TARGET_LITTLE_SYM
const bfd_target TARGET_LITTLE_SYM =
{
/* name: identify kind of target */
TARGET_LITTLE_NAME,
/* flavour: general indication about file */
bfd_target_elf_flavour,
/* byteorder: data is little endian */
BFD_ENDIAN_LITTLE,
/* header_byteorder: header is also little endian */
BFD_ENDIAN_LITTLE,
/* object_flags: mask of all file flags */
(HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS
| DYNAMIC | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS),
/* section_flags: mask of all section flags */
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY
| SEC_CODE | SEC_DATA | SEC_DEBUGGING | SEC_EXCLUDE | SEC_SORT_ENTRIES
| SEC_SMALL_DATA | SEC_MERGE | SEC_STRINGS | SEC_GROUP),
/* leading_symbol_char: is the first char of a user symbol
predictable, and if so what is it */
elf_symbol_leading_char,
/* ar_pad_char: pad character for filenames within an archive header
FIXME: this really has nothing to do with ELF, this is a characteristic
of the archiver and/or os and should be independently tunable */
'/',
/* ar_max_namelen: maximum number of characters in an archive header
FIXME: this really has nothing to do with ELF, this is a characteristic
of the archiver and should be independently tunable. The System V ABI,
Chapter 7 (Formats & Protocols), Archive section sets this as 15. */
15,
elf_match_priority,
/* Routines to byte-swap various sized integers from the data sections */
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
bfd_getl16, bfd_getl_signed_16, bfd_putl16,
/* Routines to byte-swap various sized integers from the file headers */
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
bfd_getl16, bfd_getl_signed_16, bfd_putl16,
/* bfd_check_format: check the format of a file being read */
{ _bfd_dummy_target, /* unknown format */
bfd_elf32_object_p, /* assembler/linker output (object file) */
bfd_elf32_archive_p, /* an archive */
bfd_elf32_core_file_p /* a core file */
},
/* bfd_set_format: set the format of a file being written */
{ bfd_false,
bfd_elf32_mkobject,
bfd_elf32_mkarchive,
bfd_elf32_mkcorefile
},
/* bfd_write_contents: write cached information into a file being written */
{ bfd_false,
bfd_elf32_write_object_contents,
bfd_elf32_write_archive_contents,
bfd_elf32_write_corefile_contents,
},
BFD_JUMP_TABLE_GENERIC (bfd_elf32),
BFD_JUMP_TABLE_COPY (bfd_elf32),
BFD_JUMP_TABLE_CORE (bfd_elf32),
#ifdef bfd_elf32_archive_functions
BFD_JUMP_TABLE_ARCHIVE (bfd_elf32_archive),
#else
BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
#endif
BFD_JUMP_TABLE_SYMBOLS (bfd_elf32),
BFD_JUMP_TABLE_RELOCS (bfd_elf32),
BFD_JUMP_TABLE_WRITE (bfd_elf32),
BFD_JUMP_TABLE_LINK (bfd_elf32),
BFD_JUMP_TABLE_DYNAMIC (bfd_elf32),
/* Alternative endian target. */
#ifdef TARGET_BIG_SYM
& TARGET_BIG_SYM,
#else
NULL,
#endif
/* backend_data: */
&elf32_bed
};
#endif

View File

@@ -0,0 +1,24 @@
/* ELF 32-bit executable support for BFD.
Copyright 1993, 2001, 2004, 2005, 2006, 2007, 2008, 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. */
#define ARCH_SIZE 32
#include "elfcode.h"

View File

@@ -0,0 +1,999 @@
/* Target definitions for 64-bit ELF
Copyright 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 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. */
/* This structure contains everything that BFD knows about a target.
It includes things like its byte order, name, what routines to call
to do various operations, etc. Every BFD points to a target structure
with its "xvec" member.
There are two such structures here: one for big-endian machines and
one for little-endian machines. */
#ifndef bfd_elf64_close_and_cleanup
#define bfd_elf64_close_and_cleanup _bfd_elf_close_and_cleanup
#endif
#ifndef bfd_elf64_bfd_free_cached_info
#define bfd_elf64_bfd_free_cached_info _bfd_free_cached_info
#endif
#ifndef bfd_elf64_get_section_contents
#define bfd_elf64_get_section_contents _bfd_generic_get_section_contents
#endif
#define bfd_elf64_canonicalize_dynamic_symtab \
_bfd_elf_canonicalize_dynamic_symtab
#ifndef bfd_elf64_get_synthetic_symtab
#define bfd_elf64_get_synthetic_symtab \
_bfd_elf_get_synthetic_symtab
#endif
#ifndef bfd_elf64_canonicalize_reloc
#define bfd_elf64_canonicalize_reloc _bfd_elf_canonicalize_reloc
#endif
#ifndef bfd_elf64_find_nearest_line
#define bfd_elf64_find_nearest_line _bfd_elf_find_nearest_line
#endif
#ifndef bfd_elf64_find_inliner_info
#define bfd_elf64_find_inliner_info _bfd_elf_find_inliner_info
#endif
#define bfd_elf64_read_minisymbols _bfd_elf_read_minisymbols
#define bfd_elf64_minisymbol_to_symbol _bfd_elf_minisymbol_to_symbol
#define bfd_elf64_get_dynamic_symtab_upper_bound \
_bfd_elf_get_dynamic_symtab_upper_bound
#define bfd_elf64_get_lineno _bfd_elf_get_lineno
#ifndef bfd_elf64_get_reloc_upper_bound
#define bfd_elf64_get_reloc_upper_bound _bfd_elf_get_reloc_upper_bound
#endif
#ifndef bfd_elf64_get_symbol_info
#define bfd_elf64_get_symbol_info _bfd_elf_get_symbol_info
#endif
#define bfd_elf64_canonicalize_symtab _bfd_elf_canonicalize_symtab
#define bfd_elf64_get_symtab_upper_bound _bfd_elf_get_symtab_upper_bound
#define bfd_elf64_make_empty_symbol _bfd_elf_make_empty_symbol
#ifndef bfd_elf64_new_section_hook
#define bfd_elf64_new_section_hook _bfd_elf_new_section_hook
#endif
#define bfd_elf64_set_arch_mach _bfd_elf_set_arch_mach
#ifndef bfd_elf64_set_section_contents
#define bfd_elf64_set_section_contents _bfd_elf_set_section_contents
#endif
#define bfd_elf64_sizeof_headers _bfd_elf_sizeof_headers
#define bfd_elf64_write_object_contents _bfd_elf_write_object_contents
#define bfd_elf64_write_corefile_contents _bfd_elf_write_corefile_contents
#define bfd_elf64_get_section_contents_in_window \
_bfd_generic_get_section_contents_in_window
#ifndef elf_backend_can_refcount
#define elf_backend_can_refcount 0
#endif
#ifndef elf_backend_want_got_plt
#define elf_backend_want_got_plt 0
#endif
#ifndef elf_backend_plt_readonly
#define elf_backend_plt_readonly 0
#endif
#ifndef elf_backend_want_plt_sym
#define elf_backend_want_plt_sym 0
#endif
#ifndef elf_backend_plt_not_loaded
#define elf_backend_plt_not_loaded 0
#endif
#ifndef elf_backend_plt_alignment
#define elf_backend_plt_alignment 2
#endif
#ifndef elf_backend_want_dynbss
#define elf_backend_want_dynbss 1
#endif
#ifndef elf_backend_want_p_paddr_set_to_zero
#define elf_backend_want_p_paddr_set_to_zero 0
#endif
#ifndef elf_backend_default_execstack
#define elf_backend_default_execstack 1
#endif
#ifndef elf_backend_stack_align
#define elf_backend_stack_align 16
#endif
#define bfd_elf64_bfd_debug_info_start bfd_void
#define bfd_elf64_bfd_debug_info_end bfd_void
#define bfd_elf64_bfd_debug_info_accumulate \
((void (*) (bfd*, struct bfd_section *)) bfd_void)
#ifndef bfd_elf64_bfd_get_relocated_section_contents
#define bfd_elf64_bfd_get_relocated_section_contents \
bfd_generic_get_relocated_section_contents
#endif
#ifndef bfd_elf64_bfd_relax_section
#define bfd_elf64_bfd_relax_section bfd_generic_relax_section
#endif
#ifndef elf_backend_can_gc_sections
#define elf_backend_can_gc_sections 0
#endif
#ifndef elf_backend_can_refcount
#define elf_backend_can_refcount 0
#endif
#ifndef elf_backend_want_got_sym
#define elf_backend_want_got_sym 1
#endif
#ifndef elf_backend_gc_keep
#define elf_backend_gc_keep _bfd_elf_gc_keep
#endif
#ifndef elf_backend_gc_mark_dynamic_ref
#define elf_backend_gc_mark_dynamic_ref bfd_elf_gc_mark_dynamic_ref_symbol
#endif
#ifndef elf_backend_gc_mark_hook
#define elf_backend_gc_mark_hook _bfd_elf_gc_mark_hook
#endif
#ifndef elf_backend_gc_mark_extra_sections
#define elf_backend_gc_mark_extra_sections _bfd_elf_gc_mark_extra_sections
#endif
#ifndef elf_backend_gc_sweep_hook
#define elf_backend_gc_sweep_hook NULL
#endif
#ifndef bfd_elf64_bfd_gc_sections
#define bfd_elf64_bfd_gc_sections bfd_elf_gc_sections
#endif
#ifndef bfd_elf64_bfd_merge_sections
#define bfd_elf64_bfd_merge_sections \
_bfd_elf_merge_sections
#endif
#ifndef bfd_elf64_bfd_is_group_section
#define bfd_elf64_bfd_is_group_section bfd_elf_is_group_section
#endif
#ifndef bfd_elf64_bfd_discard_group
#define bfd_elf64_bfd_discard_group bfd_generic_discard_group
#endif
#ifndef bfd_elf64_section_already_linked
#define bfd_elf64_section_already_linked \
_bfd_elf_section_already_linked
#endif
#ifndef bfd_elf64_bfd_define_common_symbol
#define bfd_elf64_bfd_define_common_symbol bfd_generic_define_common_symbol
#endif
#ifndef bfd_elf64_bfd_lookup_section_flags
#define bfd_elf64_bfd_lookup_section_flags bfd_elf_lookup_section_flags
#endif
#ifndef bfd_elf64_bfd_make_debug_symbol
#define bfd_elf64_bfd_make_debug_symbol \
((asymbol * (*) (bfd *, void *, unsigned long)) bfd_nullvoidptr)
#endif
#ifndef bfd_elf64_bfd_copy_private_symbol_data
#define bfd_elf64_bfd_copy_private_symbol_data \
_bfd_elf_copy_private_symbol_data
#endif
#ifndef bfd_elf64_bfd_copy_private_section_data
#define bfd_elf64_bfd_copy_private_section_data \
_bfd_elf_copy_private_section_data
#endif
#ifndef bfd_elf64_bfd_copy_private_header_data
#define bfd_elf64_bfd_copy_private_header_data \
_bfd_elf_copy_private_header_data
#endif
#ifndef bfd_elf64_bfd_copy_private_bfd_data
#define bfd_elf64_bfd_copy_private_bfd_data \
_bfd_elf_copy_private_bfd_data
#endif
#ifndef bfd_elf64_bfd_print_private_bfd_data
#define bfd_elf64_bfd_print_private_bfd_data \
_bfd_elf_print_private_bfd_data
#endif
#ifndef bfd_elf64_bfd_merge_private_bfd_data
#define bfd_elf64_bfd_merge_private_bfd_data \
((bfd_boolean (*) (bfd *, bfd *)) bfd_true)
#endif
#ifndef bfd_elf64_bfd_set_private_flags
#define bfd_elf64_bfd_set_private_flags \
((bfd_boolean (*) (bfd *, flagword)) bfd_true)
#endif
#ifndef bfd_elf64_bfd_is_local_label_name
#define bfd_elf64_bfd_is_local_label_name _bfd_elf_is_local_label_name
#endif
#ifndef bfd_elf64_bfd_is_target_special_symbol
#define bfd_elf64_bfd_is_target_special_symbol \
((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
#endif
#ifndef bfd_elf64_get_dynamic_reloc_upper_bound
#define bfd_elf64_get_dynamic_reloc_upper_bound \
_bfd_elf_get_dynamic_reloc_upper_bound
#endif
#ifndef bfd_elf64_canonicalize_dynamic_reloc
#define bfd_elf64_canonicalize_dynamic_reloc \
_bfd_elf_canonicalize_dynamic_reloc
#endif
#ifdef elf_backend_relocate_section
#ifndef bfd_elf64_bfd_link_hash_table_create
#define bfd_elf64_bfd_link_hash_table_create _bfd_elf_link_hash_table_create
#endif
#ifndef bfd_elf64_bfd_link_hash_table_free
#define bfd_elf64_bfd_link_hash_table_free _bfd_elf_link_hash_table_free
#endif
#ifndef bfd_elf64_bfd_link_add_symbols
#define bfd_elf64_bfd_link_add_symbols bfd_elf_link_add_symbols
#endif
#ifndef bfd_elf64_bfd_final_link
#define bfd_elf64_bfd_final_link bfd_elf_final_link
#endif
#else /* ! defined (elf_backend_relocate_section) */
/* If no backend relocate_section routine, use the generic linker.
Note - this will prevent the port from being able to use some of
the other features of the ELF linker, because the generic hash structure
does not have the fields needed by the ELF linker. In particular it
means that linking directly to S-records will not work. */
#ifndef bfd_elf64_bfd_link_hash_table_create
#define bfd_elf64_bfd_link_hash_table_create \
_bfd_generic_link_hash_table_create
#endif
#ifndef bfd_elf64_bfd_link_hash_table_free
#define bfd_elf64_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
#endif
#ifndef bfd_elf64_bfd_link_add_symbols
#define bfd_elf64_bfd_link_add_symbols _bfd_generic_link_add_symbols
#endif
#ifndef bfd_elf64_bfd_final_link
#define bfd_elf64_bfd_final_link _bfd_generic_final_link
#endif
#endif /* ! defined (elf_backend_relocate_section) */
#ifndef bfd_elf64_bfd_link_just_syms
#define bfd_elf64_bfd_link_just_syms _bfd_elf_link_just_syms
#endif
#ifndef bfd_elf64_bfd_copy_link_hash_symbol_type
#define bfd_elf64_bfd_copy_link_hash_symbol_type \
_bfd_elf_copy_link_hash_symbol_type
#endif
#ifndef bfd_elf64_bfd_link_split_section
#define bfd_elf64_bfd_link_split_section _bfd_generic_link_split_section
#endif
#ifndef bfd_elf64_archive_p
#define bfd_elf64_archive_p bfd_generic_archive_p
#endif
#ifndef bfd_elf64_write_archive_contents
#define bfd_elf64_write_archive_contents _bfd_write_archive_contents
#endif
#ifndef bfd_elf64_mkobject
#define bfd_elf64_mkobject bfd_elf_make_object
#endif
#ifndef bfd_elf64_mkcorefile
#define bfd_elf64_mkcorefile bfd_elf_mkcorefile
#endif
#ifndef bfd_elf64_mkarchive
#define bfd_elf64_mkarchive _bfd_generic_mkarchive
#endif
#ifndef bfd_elf64_print_symbol
#define bfd_elf64_print_symbol bfd_elf_print_symbol
#endif
#ifndef elf_symbol_leading_char
#define elf_symbol_leading_char 0
#endif
#ifndef elf_info_to_howto
#define elf_info_to_howto 0
#endif
#ifndef elf_info_to_howto_rel
#define elf_info_to_howto_rel 0
#endif
#ifndef elf_backend_arch_data
#define elf_backend_arch_data NULL
#endif
#ifndef ELF_TARGET_ID
#define ELF_TARGET_ID GENERIC_ELF_DATA
#endif
#ifndef ELF_OSABI
#define ELF_OSABI ELFOSABI_NONE
#endif
#ifndef ELF_MAXPAGESIZE
# error ELF_MAXPAGESIZE is not defined
#define ELF_MAXPAGESIZE 1
#endif
#ifndef ELF_COMMONPAGESIZE
#define ELF_COMMONPAGESIZE ELF_MAXPAGESIZE
#endif
#ifndef ELF_MINPAGESIZE
#define ELF_MINPAGESIZE ELF_COMMONPAGESIZE
#endif
#if ELF_COMMONPAGESIZE > ELF_MAXPAGESIZE
# error ELF_COMMONPAGESIZE > ELF_MAXPAGESIZE
#endif
#if ELF_MINPAGESIZE > ELF_COMMONPAGESIZE
# error ELF_MINPAGESIZE > ELF_COMMONPAGESIZE
#endif
#ifndef ELF_DYNAMIC_SEC_FLAGS
/* Note that we set the SEC_IN_MEMORY flag for these sections. */
#define ELF_DYNAMIC_SEC_FLAGS \
(SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS \
| SEC_IN_MEMORY | SEC_LINKER_CREATED)
#endif
#ifndef elf_backend_collect
#define elf_backend_collect FALSE
#endif
#ifndef elf_backend_type_change_ok
#define elf_backend_type_change_ok FALSE
#endif
#ifndef elf_backend_sym_is_global
#define elf_backend_sym_is_global 0
#endif
#ifndef elf_backend_object_p
#define elf_backend_object_p 0
#endif
#ifndef elf_backend_symbol_processing
#define elf_backend_symbol_processing 0
#endif
#ifndef elf_backend_symbol_table_processing
#define elf_backend_symbol_table_processing 0
#endif
#ifndef elf_backend_get_symbol_type
#define elf_backend_get_symbol_type 0
#endif
#ifndef elf_backend_archive_symbol_lookup
#define elf_backend_archive_symbol_lookup _bfd_elf_archive_symbol_lookup
#endif
#ifndef elf_backend_name_local_section_symbols
#define elf_backend_name_local_section_symbols 0
#endif
#ifndef elf_backend_section_processing
#define elf_backend_section_processing 0
#endif
#ifndef elf_backend_section_from_shdr
#define elf_backend_section_from_shdr _bfd_elf_make_section_from_shdr
#endif
#ifndef elf_backend_section_flags
#define elf_backend_section_flags 0
#endif
#ifndef elf_backend_get_sec_type_attr
#define elf_backend_get_sec_type_attr _bfd_elf_get_sec_type_attr
#endif
#ifndef elf_backend_section_from_phdr
#define elf_backend_section_from_phdr _bfd_elf_make_section_from_phdr
#endif
#ifndef elf_backend_fake_sections
#define elf_backend_fake_sections 0
#endif
#ifndef elf_backend_section_from_bfd_section
#define elf_backend_section_from_bfd_section 0
#endif
#ifndef elf_backend_add_symbol_hook
#define elf_backend_add_symbol_hook 0
#endif
#ifndef elf_backend_link_output_symbol_hook
#define elf_backend_link_output_symbol_hook 0
#endif
#ifndef elf_backend_create_dynamic_sections
#define elf_backend_create_dynamic_sections 0
#endif
#ifndef elf_backend_omit_section_dynsym
#define elf_backend_omit_section_dynsym _bfd_elf_link_omit_section_dynsym
#endif
#ifndef elf_backend_relocs_compatible
#define elf_backend_relocs_compatible _bfd_elf_default_relocs_compatible
#endif
#ifndef elf_backend_check_relocs
#define elf_backend_check_relocs 0
#endif
#ifndef elf_backend_check_directives
#define elf_backend_check_directives 0
#endif
#ifndef elf_backend_notice_as_needed
#define elf_backend_notice_as_needed _bfd_elf_notice_as_needed
#endif
#ifndef elf_backend_adjust_dynamic_symbol
#define elf_backend_adjust_dynamic_symbol 0
#endif
#ifndef elf_backend_always_size_sections
#define elf_backend_always_size_sections 0
#endif
#ifndef elf_backend_size_dynamic_sections
#define elf_backend_size_dynamic_sections 0
#endif
#ifndef elf_backend_init_index_section
#define elf_backend_init_index_section \
((void (*) (bfd *, struct bfd_link_info *)) bfd_void)
#endif
#ifndef elf_backend_relocate_section
#define elf_backend_relocate_section 0
#endif
#ifndef elf_backend_finish_dynamic_symbol
#define elf_backend_finish_dynamic_symbol 0
#endif
#ifndef elf_backend_finish_dynamic_sections
#define elf_backend_finish_dynamic_sections 0
#endif
#ifndef elf_backend_begin_write_processing
#define elf_backend_begin_write_processing 0
#endif
#ifndef elf_backend_final_write_processing
#define elf_backend_final_write_processing 0
#endif
#ifndef elf_backend_additional_program_headers
#define elf_backend_additional_program_headers 0
#endif
#ifndef elf_backend_modify_segment_map
#define elf_backend_modify_segment_map 0
#endif
#ifndef elf_backend_modify_program_headers
#define elf_backend_modify_program_headers 0
#endif
#ifndef elf_backend_ecoff_debug_swap
#define elf_backend_ecoff_debug_swap 0
#endif
#ifndef elf_backend_bfd_from_remote_memory
#define elf_backend_bfd_from_remote_memory _bfd_elf64_bfd_from_remote_memory
#endif
#ifndef elf_backend_got_header_size
#define elf_backend_got_header_size 0
#endif
#ifndef elf_backend_got_elt_size
#define elf_backend_got_elt_size _bfd_elf_default_got_elt_size
#endif
#ifndef elf_backend_obj_attrs_vendor
#define elf_backend_obj_attrs_vendor NULL
#endif
#ifndef elf_backend_obj_attrs_section
#define elf_backend_obj_attrs_section NULL
#endif
#ifndef elf_backend_obj_attrs_arg_type
#define elf_backend_obj_attrs_arg_type NULL
#endif
#ifndef elf_backend_obj_attrs_section_type
#define elf_backend_obj_attrs_section_type SHT_GNU_ATTRIBUTES
#endif
#ifndef elf_backend_obj_attrs_order
#define elf_backend_obj_attrs_order NULL
#endif
#ifndef elf_backend_obj_attrs_handle_unknown
#define elf_backend_obj_attrs_handle_unknown NULL
#endif
#ifndef elf_backend_static_tls_alignment
#define elf_backend_static_tls_alignment 1
#endif
#ifndef elf_backend_post_process_headers
#define elf_backend_post_process_headers NULL
#endif
#ifndef elf_backend_print_symbol_all
#define elf_backend_print_symbol_all NULL
#endif
#ifndef elf_backend_output_arch_local_syms
#define elf_backend_output_arch_local_syms NULL
#endif
#ifndef elf_backend_output_arch_syms
#define elf_backend_output_arch_syms NULL
#endif
#ifndef elf_backend_copy_indirect_symbol
#define elf_backend_copy_indirect_symbol _bfd_elf_link_hash_copy_indirect
#endif
#ifndef elf_backend_hide_symbol
#define elf_backend_hide_symbol _bfd_elf_link_hash_hide_symbol
#endif
#ifndef elf_backend_fixup_symbol
#define elf_backend_fixup_symbol NULL
#endif
#ifndef elf_backend_merge_symbol_attribute
#define elf_backend_merge_symbol_attribute NULL
#endif
#ifndef elf_backend_get_target_dtag
#define elf_backend_get_target_dtag NULL
#endif
#ifndef elf_backend_ignore_undef_symbol
#define elf_backend_ignore_undef_symbol NULL
#endif
#ifndef elf_backend_emit_relocs
#define elf_backend_emit_relocs _bfd_elf_link_output_relocs
#endif
#ifndef elf_backend_count_relocs
#define elf_backend_count_relocs NULL
#endif
#ifndef elf_backend_grok_prstatus
#define elf_backend_grok_prstatus NULL
#endif
#ifndef elf_backend_grok_psinfo
#define elf_backend_grok_psinfo NULL
#endif
#ifndef elf_backend_write_core_note
#define elf_backend_write_core_note NULL
#endif
#ifndef elf_backend_lookup_section_flags_hook
#define elf_backend_lookup_section_flags_hook NULL
#endif
#ifndef elf_backend_reloc_type_class
#define elf_backend_reloc_type_class _bfd_elf_reloc_type_class
#endif
#ifndef elf_backend_discard_info
#define elf_backend_discard_info NULL
#endif
#ifndef elf_backend_ignore_discarded_relocs
#define elf_backend_ignore_discarded_relocs NULL
#endif
#ifndef elf_backend_action_discarded
#define elf_backend_action_discarded _bfd_elf_default_action_discarded
#endif
#ifndef elf_backend_eh_frame_address_size
#define elf_backend_eh_frame_address_size _bfd_elf_eh_frame_address_size
#endif
#ifndef elf_backend_can_make_relative_eh_frame
#define elf_backend_can_make_relative_eh_frame _bfd_elf_can_make_relative
#endif
#ifndef elf_backend_can_make_lsda_relative_eh_frame
#define elf_backend_can_make_lsda_relative_eh_frame _bfd_elf_can_make_relative
#endif
#ifndef elf_backend_encode_eh_address
#define elf_backend_encode_eh_address _bfd_elf_encode_eh_address
#endif
#ifndef elf_backend_write_section
#define elf_backend_write_section NULL
#endif
#ifndef elf_backend_mips_irix_compat
#define elf_backend_mips_irix_compat NULL
#endif
#ifndef elf_backend_mips_rtype_to_howto
#define elf_backend_mips_rtype_to_howto NULL
#endif
/* Previously, backends could only use SHT_REL or SHT_RELA relocation
sections, but not both. They defined USE_REL to indicate SHT_REL
sections, and left it undefined to indicated SHT_RELA sections.
For backwards compatibility, we still support this usage. */
#ifndef USE_REL
#define USE_REL 0
#endif
/* Use these in new code. */
#ifndef elf_backend_may_use_rel_p
#define elf_backend_may_use_rel_p USE_REL
#endif
#ifndef elf_backend_may_use_rela_p
#define elf_backend_may_use_rela_p !USE_REL
#endif
#ifndef elf_backend_default_use_rela_p
#define elf_backend_default_use_rela_p !USE_REL
#endif
#ifndef elf_backend_rela_plts_and_copies_p
#define elf_backend_rela_plts_and_copies_p elf_backend_default_use_rela_p
#endif
#ifndef elf_backend_rela_normal
#define elf_backend_rela_normal 0
#endif
#ifndef elf_backend_plt_sym_val
#define elf_backend_plt_sym_val NULL
#endif
#ifndef elf_backend_relplt_name
#define elf_backend_relplt_name NULL
#endif
#ifndef ELF_MACHINE_ALT1
#define ELF_MACHINE_ALT1 0
#endif
#ifndef ELF_MACHINE_ALT2
#define ELF_MACHINE_ALT2 0
#endif
#ifndef elf_backend_size_info
#define elf_backend_size_info _bfd_elf64_size_info
#endif
#ifndef elf_backend_special_sections
#define elf_backend_special_sections NULL
#endif
#ifndef elf_backend_sign_extend_vma
#define elf_backend_sign_extend_vma 0
#endif
#ifndef elf_backend_link_order_error_handler
#define elf_backend_link_order_error_handler _bfd_default_error_handler
#endif
#ifndef elf_backend_common_definition
#define elf_backend_common_definition _bfd_elf_common_definition
#endif
#ifndef elf_backend_common_section_index
#define elf_backend_common_section_index _bfd_elf_common_section_index
#endif
#ifndef elf_backend_common_section
#define elf_backend_common_section _bfd_elf_common_section
#endif
#ifndef elf_backend_merge_symbol
#define elf_backend_merge_symbol NULL
#endif
#ifndef elf_backend_hash_symbol
#define elf_backend_hash_symbol _bfd_elf_hash_symbol
#endif
#ifndef elf_backend_is_function_type
#define elf_backend_is_function_type _bfd_elf_is_function_type
#endif
#ifndef elf_backend_maybe_function_sym
#define elf_backend_maybe_function_sym _bfd_elf_maybe_function_sym
#endif
#ifndef elf_match_priority
#define elf_match_priority \
(ELF_ARCH == bfd_arch_unknown ? 2 : ELF_OSABI == ELFOSABI_NONE ? 1 : 0)
#endif
extern const struct elf_size_info _bfd_elf64_size_info;
static struct elf_backend_data elf64_bed =
{
ELF_ARCH, /* arch */
ELF_TARGET_ID, /* target_id */
ELF_MACHINE_CODE, /* elf_machine_code */
ELF_OSABI, /* elf_osabi */
ELF_MAXPAGESIZE, /* maxpagesize */
ELF_MINPAGESIZE, /* minpagesize */
ELF_COMMONPAGESIZE, /* commonpagesize */
ELF_DYNAMIC_SEC_FLAGS, /* dynamic_sec_flags */
elf_backend_arch_data,
elf_info_to_howto,
elf_info_to_howto_rel,
elf_backend_sym_is_global,
elf_backend_object_p,
elf_backend_symbol_processing,
elf_backend_symbol_table_processing,
elf_backend_get_symbol_type,
elf_backend_archive_symbol_lookup,
elf_backend_name_local_section_symbols,
elf_backend_section_processing,
elf_backend_section_from_shdr,
elf_backend_section_flags,
elf_backend_get_sec_type_attr,
elf_backend_section_from_phdr,
elf_backend_fake_sections,
elf_backend_section_from_bfd_section,
elf_backend_add_symbol_hook,
elf_backend_link_output_symbol_hook,
elf_backend_create_dynamic_sections,
elf_backend_omit_section_dynsym,
elf_backend_relocs_compatible,
elf_backend_check_relocs,
elf_backend_check_directives,
elf_backend_notice_as_needed,
elf_backend_adjust_dynamic_symbol,
elf_backend_always_size_sections,
elf_backend_size_dynamic_sections,
elf_backend_init_index_section,
elf_backend_relocate_section,
elf_backend_finish_dynamic_symbol,
elf_backend_finish_dynamic_sections,
elf_backend_begin_write_processing,
elf_backend_final_write_processing,
elf_backend_additional_program_headers,
elf_backend_modify_segment_map,
elf_backend_modify_program_headers,
elf_backend_gc_keep,
elf_backend_gc_mark_dynamic_ref,
elf_backend_gc_mark_hook,
elf_backend_gc_mark_extra_sections,
elf_backend_gc_sweep_hook,
elf_backend_post_process_headers,
elf_backend_print_symbol_all,
elf_backend_output_arch_local_syms,
elf_backend_output_arch_syms,
elf_backend_copy_indirect_symbol,
elf_backend_hide_symbol,
elf_backend_fixup_symbol,
elf_backend_merge_symbol_attribute,
elf_backend_get_target_dtag,
elf_backend_ignore_undef_symbol,
elf_backend_emit_relocs,
elf_backend_count_relocs,
elf_backend_grok_prstatus,
elf_backend_grok_psinfo,
elf_backend_write_core_note,
elf_backend_lookup_section_flags_hook,
elf_backend_reloc_type_class,
elf_backend_discard_info,
elf_backend_ignore_discarded_relocs,
elf_backend_action_discarded,
elf_backend_eh_frame_address_size,
elf_backend_can_make_relative_eh_frame,
elf_backend_can_make_lsda_relative_eh_frame,
elf_backend_encode_eh_address,
elf_backend_write_section,
elf_backend_mips_irix_compat,
elf_backend_mips_rtype_to_howto,
elf_backend_ecoff_debug_swap,
elf_backend_bfd_from_remote_memory,
elf_backend_plt_sym_val,
elf_backend_common_definition,
elf_backend_common_section_index,
elf_backend_common_section,
elf_backend_merge_symbol,
elf_backend_hash_symbol,
elf_backend_is_function_type,
elf_backend_maybe_function_sym,
elf_backend_link_order_error_handler,
elf_backend_relplt_name,
ELF_MACHINE_ALT1,
ELF_MACHINE_ALT2,
&elf_backend_size_info,
elf_backend_special_sections,
elf_backend_got_header_size,
elf_backend_got_elt_size,
elf_backend_obj_attrs_vendor,
elf_backend_obj_attrs_section,
elf_backend_obj_attrs_arg_type,
elf_backend_obj_attrs_section_type,
elf_backend_obj_attrs_order,
elf_backend_obj_attrs_handle_unknown,
elf_backend_static_tls_alignment,
elf_backend_stack_align,
elf_backend_collect,
elf_backend_type_change_ok,
elf_backend_may_use_rel_p,
elf_backend_may_use_rela_p,
elf_backend_default_use_rela_p,
elf_backend_rela_plts_and_copies_p,
elf_backend_rela_normal,
elf_backend_sign_extend_vma,
elf_backend_want_got_plt,
elf_backend_plt_readonly,
elf_backend_want_plt_sym,
elf_backend_plt_not_loaded,
elf_backend_plt_alignment,
elf_backend_can_gc_sections,
elf_backend_can_refcount,
elf_backend_want_got_sym,
elf_backend_want_dynbss,
elf_backend_want_p_paddr_set_to_zero,
elf_backend_default_execstack
};
/* Forward declaration for use when initialising alternative_target field. */
#ifdef TARGET_LITTLE_SYM
extern const bfd_target TARGET_LITTLE_SYM;
#endif
#ifdef TARGET_BIG_SYM
const bfd_target TARGET_BIG_SYM =
{
/* name: identify kind of target */
TARGET_BIG_NAME,
/* flavour: general indication about file */
bfd_target_elf_flavour,
/* byteorder: data is big endian */
BFD_ENDIAN_BIG,
/* header_byteorder: header is also big endian */
BFD_ENDIAN_BIG,
/* object_flags: mask of all file flags */
(HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS
| DYNAMIC | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS),
/* section_flags: mask of all section flags */
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY
| SEC_CODE | SEC_DATA | SEC_DEBUGGING | SEC_EXCLUDE | SEC_SORT_ENTRIES
| SEC_SMALL_DATA | SEC_MERGE | SEC_STRINGS | SEC_GROUP),
/* leading_symbol_char: is the first char of a user symbol
predictable, and if so what is it */
elf_symbol_leading_char,
/* ar_pad_char: pad character for filenames within an archive header
FIXME: this really has nothing to do with ELF, this is a characteristic
of the archiver and/or os and should be independently tunable */
'/',
/* ar_max_namelen: maximum number of characters in an archive header
FIXME: this really has nothing to do with ELF, this is a characteristic
of the archiver and should be independently tunable. The System V ABI,
Chapter 7 (Formats & Protocols), Archive section sets this as 15. */
15,
elf_match_priority,
/* Routines to byte-swap various sized integers from the data sections */
bfd_getb64, bfd_getb_signed_64, bfd_putb64,
bfd_getb32, bfd_getb_signed_32, bfd_putb32,
bfd_getb16, bfd_getb_signed_16, bfd_putb16,
/* Routines to byte-swap various sized integers from the file headers */
bfd_getb64, bfd_getb_signed_64, bfd_putb64,
bfd_getb32, bfd_getb_signed_32, bfd_putb32,
bfd_getb16, bfd_getb_signed_16, bfd_putb16,
/* bfd_check_format: check the format of a file being read */
{ _bfd_dummy_target, /* unknown format */
bfd_elf64_object_p, /* assembler/linker output (object file) */
bfd_elf64_archive_p, /* an archive */
bfd_elf64_core_file_p /* a core file */
},
/* bfd_set_format: set the format of a file being written */
{ bfd_false,
bfd_elf64_mkobject,
bfd_elf64_mkarchive,
bfd_elf64_mkcorefile
},
/* bfd_write_contents: write cached information into a file being written */
{ bfd_false,
bfd_elf64_write_object_contents,
bfd_elf64_write_archive_contents,
bfd_elf64_write_corefile_contents,
},
BFD_JUMP_TABLE_GENERIC (bfd_elf64),
BFD_JUMP_TABLE_COPY (bfd_elf64),
BFD_JUMP_TABLE_CORE (bfd_elf64),
#ifdef bfd_elf64_archive_functions
BFD_JUMP_TABLE_ARCHIVE (bfd_elf64_archive),
#else
BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
#endif
BFD_JUMP_TABLE_SYMBOLS (bfd_elf64),
BFD_JUMP_TABLE_RELOCS (bfd_elf64),
BFD_JUMP_TABLE_WRITE (bfd_elf64),
BFD_JUMP_TABLE_LINK (bfd_elf64),
BFD_JUMP_TABLE_DYNAMIC (bfd_elf64),
/* Alternative endian target. */
#ifdef TARGET_LITTLE_SYM
& TARGET_LITTLE_SYM,
#else
NULL,
#endif
/* backend_data: */
&elf64_bed
};
#endif
#ifdef TARGET_LITTLE_SYM
const bfd_target TARGET_LITTLE_SYM =
{
/* name: identify kind of target */
TARGET_LITTLE_NAME,
/* flavour: general indication about file */
bfd_target_elf_flavour,
/* byteorder: data is little endian */
BFD_ENDIAN_LITTLE,
/* header_byteorder: header is also little endian */
BFD_ENDIAN_LITTLE,
/* object_flags: mask of all file flags */
(HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS
| DYNAMIC | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS),
/* section_flags: mask of all section flags */
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY
| SEC_CODE | SEC_DATA | SEC_DEBUGGING | SEC_EXCLUDE | SEC_SORT_ENTRIES
| SEC_SMALL_DATA | SEC_MERGE | SEC_STRINGS | SEC_GROUP),
/* leading_symbol_char: is the first char of a user symbol
predictable, and if so what is it */
elf_symbol_leading_char,
/* ar_pad_char: pad character for filenames within an archive header
FIXME: this really has nothing to do with ELF, this is a characteristic
of the archiver and/or os and should be independently tunable */
'/',
/* ar_max_namelen: maximum number of characters in an archive header
FIXME: this really has nothing to do with ELF, this is a characteristic
of the archiver and should be independently tunable. The System V ABI,
Chapter 7 (Formats & Protocols), Archive section sets this as 15. */
15,
elf_match_priority,
/* Routines to byte-swap various sized integers from the data sections */
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
bfd_getl16, bfd_getl_signed_16, bfd_putl16,
/* Routines to byte-swap various sized integers from the file headers */
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
bfd_getl16, bfd_getl_signed_16, bfd_putl16,
/* bfd_check_format: check the format of a file being read */
{ _bfd_dummy_target, /* unknown format */
bfd_elf64_object_p, /* assembler/linker output (object file) */
bfd_elf64_archive_p, /* an archive */
bfd_elf64_core_file_p /* a core file */
},
/* bfd_set_format: set the format of a file being written */
{ bfd_false,
bfd_elf64_mkobject,
bfd_elf64_mkarchive,
bfd_elf64_mkcorefile
},
/* bfd_write_contents: write cached information into a file being written */
{ bfd_false,
bfd_elf64_write_object_contents,
bfd_elf64_write_archive_contents,
bfd_elf64_write_corefile_contents,
},
BFD_JUMP_TABLE_GENERIC (bfd_elf64),
BFD_JUMP_TABLE_COPY (bfd_elf64),
BFD_JUMP_TABLE_CORE (bfd_elf64),
#ifdef bfd_elf64_archive_functions
BFD_JUMP_TABLE_ARCHIVE (bfd_elf64_archive),
#else
BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
#endif
BFD_JUMP_TABLE_SYMBOLS (bfd_elf64),
BFD_JUMP_TABLE_RELOCS (bfd_elf64),
BFD_JUMP_TABLE_WRITE (bfd_elf64),
BFD_JUMP_TABLE_LINK (bfd_elf64),
BFD_JUMP_TABLE_DYNAMIC (bfd_elf64),
/* Alternative endian target. */
#ifdef TARGET_BIG_SYM
& TARGET_BIG_SYM,
#else
NULL,
#endif
/* backend_data: */
&elf64_bed
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,320 @@
/* ELF core file support for BFD.
Copyright 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007,
2008, 2010 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. */
char*
elf_core_file_failing_command (bfd *abfd)
{
return elf_tdata (abfd)->core->command;
}
int
elf_core_file_failing_signal (bfd *abfd)
{
return elf_tdata (abfd)->core->signal;
}
int
elf_core_file_pid (bfd *abfd)
{
return elf_tdata (abfd)->core->pid;
}
bfd_boolean
elf_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
{
char* corename;
/* xvecs must match if both are ELF files for the same target. */
if (core_bfd->xvec != exec_bfd->xvec)
{
bfd_set_error (bfd_error_system_call);
return FALSE;
}
/* See if the name in the corefile matches the executable name. */
corename = elf_tdata (core_bfd)->core->program;
if (corename != NULL)
{
const char* execname = strrchr (exec_bfd->filename, '/');
execname = execname ? execname + 1 : exec_bfd->filename;
if (strcmp (execname, corename) != 0)
return FALSE;
}
return TRUE;
}
/* Core files are simply standard ELF formatted files that partition
the file using the execution view of the file (program header table)
rather than the linking view. In fact, there is no section header
table in a core file.
The process status information (including the contents of the general
register set) and the floating point register set are stored in a
segment of type PT_NOTE. We handcraft a couple of extra bfd sections
that allow standard bfd access to the general registers (.reg) and the
floating point registers (.reg2). */
const bfd_target *
elf_core_file_p (bfd *abfd)
{
Elf_External_Ehdr x_ehdr; /* Elf file header, external form. */
Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form. */
Elf_Internal_Phdr *i_phdrp; /* Elf program header, internal form. */
unsigned int phindex;
const struct elf_backend_data *ebd;
bfd_size_type amt;
/* Read in the ELF header in external format. */
if (bfd_bread (&x_ehdr, sizeof (x_ehdr), abfd) != sizeof (x_ehdr))
{
if (bfd_get_error () != bfd_error_system_call)
goto wrong;
else
goto fail;
}
/* Check the magic number. */
if (! elf_file_p (&x_ehdr))
goto wrong;
/* FIXME: Check EI_VERSION here ! */
/* Check the address size ("class"). */
if (x_ehdr.e_ident[EI_CLASS] != ELFCLASS)
goto wrong;
/* Check the byteorder. */
switch (x_ehdr.e_ident[EI_DATA])
{
case ELFDATA2MSB: /* Big-endian. */
if (! bfd_big_endian (abfd))
goto wrong;
break;
case ELFDATA2LSB: /* Little-endian. */
if (! bfd_little_endian (abfd))
goto wrong;
break;
default:
goto wrong;
}
/* Give abfd an elf_obj_tdata. */
if (! (*abfd->xvec->_bfd_set_format[bfd_core]) (abfd))
goto fail;
/* Swap in the rest of the header, now that we have the byte order. */
i_ehdrp = elf_elfheader (abfd);
elf_swap_ehdr_in (abfd, &x_ehdr, i_ehdrp);
#if DEBUG & 1
elf_debug_file (i_ehdrp);
#endif
ebd = get_elf_backend_data (abfd);
/* Check that the ELF e_machine field matches what this particular
BFD format expects. */
if (ebd->elf_machine_code != i_ehdrp->e_machine
&& (ebd->elf_machine_alt1 == 0
|| i_ehdrp->e_machine != ebd->elf_machine_alt1)
&& (ebd->elf_machine_alt2 == 0
|| i_ehdrp->e_machine != ebd->elf_machine_alt2))
{
const bfd_target * const *target_ptr;
if (ebd->elf_machine_code != EM_NONE)
goto wrong;
/* This is the generic ELF target. Let it match any ELF target
for which we do not have a specific backend. */
for (target_ptr = bfd_target_vector; *target_ptr != NULL; target_ptr++)
{
const struct elf_backend_data *back;
if ((*target_ptr)->flavour != bfd_target_elf_flavour)
continue;
back = xvec_get_elf_backend_data (*target_ptr);
if (back->s->arch_size != ARCH_SIZE)
continue;
if (back->elf_machine_code == i_ehdrp->e_machine
|| (back->elf_machine_alt1 != 0
&& i_ehdrp->e_machine == back->elf_machine_alt1)
|| (back->elf_machine_alt2 != 0
&& i_ehdrp->e_machine == back->elf_machine_alt2))
{
/* target_ptr is an ELF backend which matches this
object file, so reject the generic ELF target. */
goto wrong;
}
}
}
/* If there is no program header, or the type is not a core file, then
we are hosed. */
if (i_ehdrp->e_phoff == 0 || i_ehdrp->e_type != ET_CORE)
goto wrong;
/* Does BFD's idea of the phdr size match the size
recorded in the file? */
if (i_ehdrp->e_phentsize != sizeof (Elf_External_Phdr))
goto wrong;
/* If the program header count is PN_XNUM(0xffff), the actual
count is in the first section header. */
if (i_ehdrp->e_shoff != 0 && i_ehdrp->e_phnum == PN_XNUM)
{
Elf_External_Shdr x_shdr;
Elf_Internal_Shdr i_shdr;
bfd_signed_vma where = i_ehdrp->e_shoff;
if (where != (file_ptr) where)
goto wrong;
/* Seek to the section header table in the file. */
if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0)
goto fail;
/* Read the first section header at index 0, and convert to internal
form. */
if (bfd_bread (&x_shdr, sizeof (x_shdr), abfd) != sizeof (x_shdr))
goto fail;
elf_swap_shdr_in (abfd, &x_shdr, &i_shdr);
if (i_shdr.sh_info != 0)
{
i_ehdrp->e_phnum = i_shdr.sh_info;
if (i_ehdrp->e_phnum != i_shdr.sh_info)
goto wrong;
}
}
/* Sanity check that we can read all of the program headers.
It ought to be good enough to just read the last one. */
if (i_ehdrp->e_phnum > 1)
{
Elf_External_Phdr x_phdr;
Elf_Internal_Phdr i_phdr;
bfd_signed_vma where;
/* Check that we don't have a totally silly number of
program headers. */
if (i_ehdrp->e_phnum > (unsigned int) -1 / sizeof (x_phdr)
|| i_ehdrp->e_phnum > (unsigned int) -1 / sizeof (i_phdr))
goto wrong;
where = i_ehdrp->e_phoff + (i_ehdrp->e_phnum - 1) * sizeof (x_phdr);
if (where != (file_ptr) where)
goto wrong;
if ((bfd_size_type) where <= i_ehdrp->e_phoff)
goto wrong;
if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0)
goto fail;
if (bfd_bread (&x_phdr, sizeof (x_phdr), abfd) != sizeof (x_phdr))
goto fail;
}
/* Move to the start of the program headers. */
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0)
goto wrong;
/* Allocate space for the program headers. */
amt = sizeof (*i_phdrp) * i_ehdrp->e_phnum;
i_phdrp = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt);
if (!i_phdrp)
goto fail;
elf_tdata (abfd)->phdr = i_phdrp;
/* Read and convert to internal form. */
for (phindex = 0; phindex < i_ehdrp->e_phnum; ++phindex)
{
Elf_External_Phdr x_phdr;
if (bfd_bread (&x_phdr, sizeof (x_phdr), abfd) != sizeof (x_phdr))
goto fail;
elf_swap_phdr_in (abfd, &x_phdr, i_phdrp + phindex);
}
/* Set the machine architecture. Do this before processing the
program headers since we need to know the architecture type
when processing the notes of some systems' core files. */
if (! bfd_default_set_arch_mach (abfd, ebd->arch, 0)
/* It's OK if this fails for the generic target. */
&& ebd->elf_machine_code != EM_NONE)
goto fail;
/* Let the backend double check the format and override global
information. We do this before processing the program headers
to allow the correct machine (as opposed to just the default
machine) to be set, making it possible for grok_prstatus and
grok_psinfo to rely on the mach setting. */
if (ebd->elf_backend_object_p != NULL
&& ! ebd->elf_backend_object_p (abfd))
goto wrong;
/* Process each program header. */
for (phindex = 0; phindex < i_ehdrp->e_phnum; ++phindex)
if (! bfd_section_from_phdr (abfd, i_phdrp + phindex, (int) phindex))
goto fail;
/* Check for core truncation. */
{
bfd_size_type high = 0;
struct stat statbuf;
for (phindex = 0; phindex < i_ehdrp->e_phnum; ++phindex)
{
Elf_Internal_Phdr *p = i_phdrp + phindex;
if (p->p_filesz)
{
bfd_size_type current = p->p_offset + p->p_filesz;
if (high < current)
high = current;
}
}
if (bfd_stat (abfd, &statbuf) == 0)
{
if ((bfd_size_type) statbuf.st_size < high)
{
(*_bfd_error_handler)
(_("Warning: %B is truncated: expected core file "
"size >= %lu, found: %lu."),
abfd, (unsigned long) high, (unsigned long) statbuf.st_size);
}
}
}
/* Save the entry point from the ELF header. */
bfd_get_start_address (abfd) = i_ehdrp->e_entry;
return abfd->xvec;
wrong:
bfd_set_error (bfd_error_wrong_format);
fail:
return NULL;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,561 @@
/* Generic BFD support for file formats.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002,
2003, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
Written by Cygnus Support.
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. */
/*
SECTION
File formats
A format is a BFD concept of high level file contents type. The
formats supported by BFD are:
o <<bfd_object>>
The BFD may contain data, symbols, relocations and debug info.
o <<bfd_archive>>
The BFD contains other BFDs and an optional index.
o <<bfd_core>>
The BFD contains the result of an executable core dump.
SUBSECTION
File format functions
*/
#include "sysdep.h"
#include "bfd.h"
#include "libbfd.h"
/* IMPORT from targets.c. */
extern const size_t _bfd_target_vector_entries;
/*
FUNCTION
bfd_check_format
SYNOPSIS
bfd_boolean bfd_check_format (bfd *abfd, bfd_format format);
DESCRIPTION
Verify if the file attached to the BFD @var{abfd} is compatible
with the format @var{format} (i.e., one of <<bfd_object>>,
<<bfd_archive>> or <<bfd_core>>).
If the BFD has been set to a specific target before the
call, only the named target and format combination is
checked. If the target has not been set, or has been set to
<<default>>, then all the known target backends is
interrogated to determine a match. If the default target
matches, it is used. If not, exactly one target must recognize
the file, or an error results.
The function returns <<TRUE>> on success, otherwise <<FALSE>>
with one of the following error codes:
o <<bfd_error_invalid_operation>> -
if <<format>> is not one of <<bfd_object>>, <<bfd_archive>> or
<<bfd_core>>.
o <<bfd_error_system_call>> -
if an error occured during a read - even some file mismatches
can cause bfd_error_system_calls.
o <<file_not_recognised>> -
none of the backends recognised the file format.
o <<bfd_error_file_ambiguously_recognized>> -
more than one backend recognised the file format.
*/
bfd_boolean
bfd_check_format (bfd *abfd, bfd_format format)
{
return bfd_check_format_matches (abfd, format, NULL);
}
struct bfd_preserve
{
void *marker;
void *tdata;
flagword flags;
const struct bfd_arch_info *arch_info;
struct bfd_section *sections;
struct bfd_section *section_last;
unsigned int section_count;
struct bfd_hash_table section_htab;
};
/* When testing an object for compatibility with a particular target
back-end, the back-end object_p function needs to set up certain
fields in the bfd on successfully recognizing the object. This
typically happens in a piecemeal fashion, with failures possible at
many points. On failure, the bfd is supposed to be restored to its
initial state, which is virtually impossible. However, restoring a
subset of the bfd state works in practice. This function stores
the subset. */
static bfd_boolean
bfd_preserve_save (bfd *abfd, struct bfd_preserve *preserve)
{
preserve->tdata = abfd->tdata.any;
preserve->arch_info = abfd->arch_info;
preserve->flags = abfd->flags;
preserve->sections = abfd->sections;
preserve->section_last = abfd->section_last;
preserve->section_count = abfd->section_count;
preserve->section_htab = abfd->section_htab;
preserve->marker = bfd_alloc (abfd, 1);
if (preserve->marker == NULL)
return FALSE;
return bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc,
sizeof (struct section_hash_entry));
}
/* Clear out a subset of BFD state. */
static void
bfd_reinit (bfd *abfd)
{
abfd->tdata.any = NULL;
abfd->arch_info = &bfd_default_arch_struct;
abfd->flags &= BFD_FLAGS_SAVED;
bfd_section_list_clear (abfd);
}
/* Restores bfd state saved by bfd_preserve_save. */
static void
bfd_preserve_restore (bfd *abfd, struct bfd_preserve *preserve)
{
bfd_hash_table_free (&abfd->section_htab);
abfd->tdata.any = preserve->tdata;
abfd->arch_info = preserve->arch_info;
abfd->flags = preserve->flags;
abfd->section_htab = preserve->section_htab;
abfd->sections = preserve->sections;
abfd->section_last = preserve->section_last;
abfd->section_count = preserve->section_count;
/* bfd_release frees all memory more recently bfd_alloc'd than
its arg, as well as its arg. */
bfd_release (abfd, preserve->marker);
preserve->marker = NULL;
}
/* Called when the bfd state saved by bfd_preserve_save is no longer
needed. */
static void
bfd_preserve_finish (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_preserve *preserve)
{
/* It would be nice to be able to free more memory here, eg. old
tdata, but that's not possible since these blocks are sitting
inside bfd_alloc'd memory. The section hash is on a separate
objalloc. */
bfd_hash_table_free (&preserve->section_htab);
preserve->marker = NULL;
}
/*
FUNCTION
bfd_check_format_matches
SYNOPSIS
bfd_boolean bfd_check_format_matches
(bfd *abfd, bfd_format format, char ***matching);
DESCRIPTION
Like <<bfd_check_format>>, except when it returns FALSE with
<<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>. In that
case, if @var{matching} is not NULL, it will be filled in with
a NULL-terminated list of the names of the formats that matched,
allocated with <<malloc>>.
Then the user may choose a format and try again.
When done with the list that @var{matching} points to, the caller
should free it.
*/
bfd_boolean
bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
{
extern const bfd_target binary_vec;
const bfd_target * const *target;
const bfd_target **matching_vector = NULL;
const bfd_target *save_targ, *right_targ, *ar_right_targ, *match_targ;
int match_count, best_count, best_match;
int ar_match_index;
struct bfd_preserve preserve;
if (matching != NULL)
*matching = NULL;
if (!bfd_read_p (abfd)
|| (unsigned int) abfd->format >= (unsigned int) bfd_type_end)
{
bfd_set_error (bfd_error_invalid_operation);
return FALSE;
}
if (abfd->format != bfd_unknown)
return abfd->format == format;
if (matching != NULL || *bfd_associated_vector != NULL)
{
bfd_size_type amt;
amt = sizeof (*matching_vector) * 2 * _bfd_target_vector_entries;
matching_vector = (const bfd_target **) bfd_malloc (amt);
if (!matching_vector)
return FALSE;
}
/* Presume the answer is yes. */
abfd->format = format;
save_targ = abfd->xvec;
preserve.marker = NULL;
/* If the target type was explicitly specified, just check that target. */
if (!abfd->target_defaulted)
{
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) /* rewind! */
goto err_ret;
right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
if (right_targ)
goto ok_ret;
/* For a long time the code has dropped through to check all
targets if the specified target was wrong. I don't know why,
and I'm reluctant to change it. However, in the case of an
archive, it can cause problems. If the specified target does
not permit archives (e.g., the binary target), then we should
not allow some other target to recognize it as an archive, but
should instead allow the specified target to recognize it as an
object. When I first made this change, it broke the PE target,
because the specified pei-i386 target did not recognize the
actual pe-i386 archive. Since there may be other problems of
this sort, I changed this test to check only for the binary
target. */
if (format == bfd_archive && save_targ == &binary_vec)
goto err_unrecog;
}
/* Since the target type was defaulted, check them all in the hope
that one will be uniquely recognized. */
right_targ = NULL;
ar_right_targ = NULL;
match_targ = NULL;
best_match = 256;
best_count = 0;
match_count = 0;
ar_match_index = _bfd_target_vector_entries;
for (target = bfd_target_vector; *target != NULL; target++)
{
const bfd_target *temp;
/* Don't check the default target twice. */
if (*target == &binary_vec
|| (!abfd->target_defaulted && *target == save_targ)
|| (*target)->match_priority > best_match)
continue;
/* If we already tried a match, the bfd is modified and may
have sections attached, which will confuse the next
_bfd_check_format call. */
bfd_reinit (abfd);
/* Change BFD's target temporarily. */
abfd->xvec = *target;
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
goto err_ret;
/* If _bfd_check_format neglects to set bfd_error, assume
bfd_error_wrong_format. We didn't used to even pay any
attention to bfd_error, so I suspect that some
_bfd_check_format might have this problem. */
bfd_set_error (bfd_error_wrong_format);
temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
if (temp)
{
match_targ = temp;
if (preserve.marker != NULL)
bfd_preserve_finish (abfd, &preserve);
if (abfd->format != bfd_archive
|| (bfd_has_map (abfd)
&& bfd_get_error () != bfd_error_wrong_object_format))
{
/* This format checks out as ok! */
right_targ = temp;
/* If this is the default target, accept it, even if
other targets might match. People who want those
other targets have to set the GNUTARGET variable. */
if (temp == bfd_default_vector[0])
goto ok_ret;
if (matching_vector)
matching_vector[match_count] = temp;
match_count++;
if (temp->match_priority < best_match)
{
best_match = temp->match_priority;
best_count = 0;
}
best_count++;
}
else
{
/* An archive with no armap or objects of the wrong
type. We want this target to match if we get no
better matches. */
if (ar_right_targ != bfd_default_vector[0])
ar_right_targ = *target;
if (matching_vector)
matching_vector[ar_match_index] = *target;
ar_match_index++;
}
if (!bfd_preserve_save (abfd, &preserve))
goto err_ret;
}
else if (bfd_get_error () != bfd_error_wrong_format)
goto err_ret;
}
if (best_count == 1)
match_count = 1;
if (match_count == 0)
{
/* Try partial matches. */
right_targ = ar_right_targ;
if (right_targ == bfd_default_vector[0])
{
match_count = 1;
}
else
{
match_count = ar_match_index - _bfd_target_vector_entries;
if (matching_vector && match_count > 1)
memcpy (matching_vector,
matching_vector + _bfd_target_vector_entries,
sizeof (*matching_vector) * match_count);
}
}
/* We have more than one equally good match. If any of the best
matches is a target in config.bfd targ_defvec or targ_selvecs,
choose it. */
if (match_count > 1)
{
const bfd_target * const *assoc = bfd_associated_vector;
while ((right_targ = *assoc++) != NULL)
{
int i = match_count;
while (--i >= 0)
if (matching_vector[i] == right_targ
&& right_targ->match_priority <= best_match)
break;
if (i >= 0)
{
match_count = 1;
break;
}
}
}
/* We still have more than one equally good match, and at least some
of the targets support match priority. Choose the first of the
best matches. */
if (match_count > 1 && best_count != match_count)
{
int i;
for (i = 0; i < match_count; i++)
{
right_targ = matching_vector[i];
if (right_targ->match_priority <= best_match)
break;
}
match_count = 1;
}
/* There is way too much undoing of half-known state here. We
really shouldn't iterate on live bfd's. Note that saving the
whole bfd and restoring it would be even worse; the first thing
you notice is that the cached bfd file position gets out of sync. */
if (preserve.marker != NULL)
bfd_preserve_restore (abfd, &preserve);
if (match_count == 1)
{
abfd->xvec = right_targ;
/* If we come out of the loop knowing that the last target that
matched is the one we want, then ABFD should still be in a usable
state (except possibly for XVEC). */
if (match_targ != right_targ)
{
bfd_reinit (abfd);
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
goto err_ret;
match_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
BFD_ASSERT (match_targ != NULL);
}
ok_ret:
/* If the file was opened for update, then `output_has_begun'
some time ago when the file was created. Do not recompute
sections sizes or alignments in _bfd_set_section_contents.
We can not set this flag until after checking the format,
because it will interfere with creation of BFD sections. */
if (abfd->direction == both_direction)
abfd->output_has_begun = TRUE;
if (matching_vector)
free (matching_vector);
/* File position has moved, BTW. */
return TRUE;
}
if (match_count == 0)
{
err_unrecog:
bfd_set_error (bfd_error_file_not_recognized);
err_ret:
abfd->xvec = save_targ;
abfd->format = bfd_unknown;
if (matching_vector)
free (matching_vector);
if (preserve.marker != NULL)
bfd_preserve_restore (abfd, &preserve);
return FALSE;
}
/* Restore original target type and format. */
abfd->xvec = save_targ;
abfd->format = bfd_unknown;
bfd_set_error (bfd_error_file_ambiguously_recognized);
if (matching)
{
*matching = (char **) matching_vector;
matching_vector[match_count] = NULL;
/* Return target names. This is a little nasty. Maybe we
should do another bfd_malloc? */
while (--match_count >= 0)
{
const char *name = matching_vector[match_count]->name;
*(const char **) &matching_vector[match_count] = name;
}
}
return FALSE;
}
/*
FUNCTION
bfd_set_format
SYNOPSIS
bfd_boolean bfd_set_format (bfd *abfd, bfd_format format);
DESCRIPTION
This function sets the file format of the BFD @var{abfd} to the
format @var{format}. If the target set in the BFD does not
support the format requested, the format is invalid, or the BFD
is not open for writing, then an error occurs.
*/
bfd_boolean
bfd_set_format (bfd *abfd, bfd_format format)
{
if (bfd_read_p (abfd)
|| (unsigned int) abfd->format >= (unsigned int) bfd_type_end)
{
bfd_set_error (bfd_error_invalid_operation);
return FALSE;
}
if (abfd->format != bfd_unknown)
return abfd->format == format;
/* Presume the answer is yes. */
abfd->format = format;
if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd)))
{
abfd->format = bfd_unknown;
return FALSE;
}
return TRUE;
}
/*
FUNCTION
bfd_format_string
SYNOPSIS
const char *bfd_format_string (bfd_format format);
DESCRIPTION
Return a pointer to a const string
<<invalid>>, <<object>>, <<archive>>, <<core>>, or <<unknown>>,
depending upon the value of @var{format}.
*/
const char *
bfd_format_string (bfd_format format)
{
if (((int) format < (int) bfd_unknown)
|| ((int) format >= (int) bfd_type_end))
return "invalid";
switch (format)
{
case bfd_object:
return "object"; /* Linker/assembler/compiler output. */
case bfd_archive:
return "archive"; /* Object archive file. */
case bfd_core:
return "core"; /* Core dump. */
default:
return "unknown";
}
}

View File

@@ -0,0 +1,110 @@
/* genlink.h -- interface to the BFD generic linker
Copyright 1993, 1994, 1996, 2002, 2005, 2007 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
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. */
#ifndef GENLINK_H
#define GENLINK_H
/* This header file is internal to BFD. It describes the internal
structures and functions used by the BFD generic linker, in case
any of the more specific linkers want to use or call them. Note
that some functions, such as _bfd_generic_link_hash_table_create,
are declared in libbfd.h, because they are expected to be widely
used. The functions and structures in this file will probably only
be used by a few files besides linker.c itself. In fact, this file
is not particularly complete; I have only put in the interfaces I
actually needed. */
/* The generic linker uses a hash table which is a derived class of
the standard linker hash table, just as the other backend specific
linkers do. Do not confuse the generic linker hash table with the
standard BFD linker hash table it is built upon. */
/* Generic linker hash table entries. */
struct generic_link_hash_entry
{
struct bfd_link_hash_entry root;
/* Whether this symbol has been written out. */
bfd_boolean written;
/* Symbol from input BFD. */
asymbol *sym;
};
/* Generic linker hash table. */
struct generic_link_hash_table
{
struct bfd_link_hash_table root;
};
/* Look up an entry in a generic link hash table. */
#define _bfd_generic_link_hash_lookup(table, string, create, copy, follow) \
((struct generic_link_hash_entry *) \
bfd_link_hash_lookup (&(table)->root, (string), (create), (copy), (follow)))
/* Traverse a generic link hash table. */
#define _bfd_generic_link_hash_traverse(table, func, info) \
(bfd_link_hash_traverse \
(&(table)->root, \
(bfd_boolean (*) (struct bfd_link_hash_entry *, void *)) (func), \
(info)))
/* Get the generic link hash table from the info structure. This is
just a cast. */
#define _bfd_generic_hash_table(p) \
((struct generic_link_hash_table *) ((p)->hash))
/* The generic linker reads in the asymbol structures for an input BFD
and keeps them in the outsymbol and symcount fields. */
#define _bfd_generic_link_get_symbols(abfd) ((abfd)->outsymbols)
#define _bfd_generic_link_get_symcount(abfd) ((abfd)->symcount)
/* Add the symbols of input_bfd to the symbols being built for
output_bfd. */
extern bfd_boolean _bfd_generic_link_output_symbols
(bfd *, bfd *, struct bfd_link_info *, size_t *);
/* This structure is used to pass information to
_bfd_generic_link_write_global_symbol, which may be called via
_bfd_generic_link_hash_traverse. */
struct generic_write_global_symbol_info
{
struct bfd_link_info *info;
bfd *output_bfd;
size_t *psymalloc;
};
/* Write out a single global symbol. This is expected to be called
via _bfd_generic_link_hash_traverse. The second argument must
actually be a struct generic_write_global_symbol_info *. */
extern bfd_boolean _bfd_generic_link_write_global_symbol
(struct generic_link_hash_entry *, void *);
/* Generic link hash table entry creation routine. */
struct bfd_hash_entry *_bfd_generic_link_hash_newfunc
(struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
#endif

View File

@@ -0,0 +1,912 @@
/* hash.c -- hash table routines for BFD
Copyright 1993, 1994, 1995, 1997, 1999, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
Written by Steve Chamberlain <sac@cygnus.com>
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"
#include "libbfd.h"
#include "objalloc.h"
#include "libiberty.h"
/*
SECTION
Hash Tables
@cindex Hash tables
BFD provides a simple set of hash table functions. Routines
are provided to initialize a hash table, to free a hash table,
to look up a string in a hash table and optionally create an
entry for it, and to traverse a hash table. There is
currently no routine to delete an string from a hash table.
The basic hash table does not permit any data to be stored
with a string. However, a hash table is designed to present a
base class from which other types of hash tables may be
derived. These derived types may store additional information
with the string. Hash tables were implemented in this way,
rather than simply providing a data pointer in a hash table
entry, because they were designed for use by the linker back
ends. The linker may create thousands of hash table entries,
and the overhead of allocating private data and storing and
following pointers becomes noticeable.
The basic hash table code is in <<hash.c>>.
@menu
@* Creating and Freeing a Hash Table::
@* Looking Up or Entering a String::
@* Traversing a Hash Table::
@* Deriving a New Hash Table Type::
@end menu
INODE
Creating and Freeing a Hash Table, Looking Up or Entering a String, Hash Tables, Hash Tables
SUBSECTION
Creating and freeing a hash table
@findex bfd_hash_table_init
@findex bfd_hash_table_init_n
To create a hash table, create an instance of a <<struct
bfd_hash_table>> (defined in <<bfd.h>>) and call
<<bfd_hash_table_init>> (if you know approximately how many
entries you will need, the function <<bfd_hash_table_init_n>>,
which takes a @var{size} argument, may be used).
<<bfd_hash_table_init>> returns <<FALSE>> if some sort of
error occurs.
@findex bfd_hash_newfunc
The function <<bfd_hash_table_init>> take as an argument a
function to use to create new entries. For a basic hash
table, use the function <<bfd_hash_newfunc>>. @xref{Deriving
a New Hash Table Type}, for why you would want to use a
different value for this argument.
@findex bfd_hash_allocate
<<bfd_hash_table_init>> will create an objalloc which will be
used to allocate new entries. You may allocate memory on this
objalloc using <<bfd_hash_allocate>>.
@findex bfd_hash_table_free
Use <<bfd_hash_table_free>> to free up all the memory that has
been allocated for a hash table. This will not free up the
<<struct bfd_hash_table>> itself, which you must provide.
@findex bfd_hash_set_default_size
Use <<bfd_hash_set_default_size>> to set the default size of
hash table to use.
INODE
Looking Up or Entering a String, Traversing a Hash Table, Creating and Freeing a Hash Table, Hash Tables
SUBSECTION
Looking up or entering a string
@findex bfd_hash_lookup
The function <<bfd_hash_lookup>> is used both to look up a
string in the hash table and to create a new entry.
If the @var{create} argument is <<FALSE>>, <<bfd_hash_lookup>>
will look up a string. If the string is found, it will
returns a pointer to a <<struct bfd_hash_entry>>. If the
string is not found in the table <<bfd_hash_lookup>> will
return <<NULL>>. You should not modify any of the fields in
the returns <<struct bfd_hash_entry>>.
If the @var{create} argument is <<TRUE>>, the string will be
entered into the hash table if it is not already there.
Either way a pointer to a <<struct bfd_hash_entry>> will be
returned, either to the existing structure or to a newly
created one. In this case, a <<NULL>> return means that an
error occurred.
If the @var{create} argument is <<TRUE>>, and a new entry is
created, the @var{copy} argument is used to decide whether to
copy the string onto the hash table objalloc or not. If
@var{copy} is passed as <<FALSE>>, you must be careful not to
deallocate or modify the string as long as the hash table
exists.
INODE
Traversing a Hash Table, Deriving a New Hash Table Type, Looking Up or Entering a String, Hash Tables
SUBSECTION
Traversing a hash table
@findex bfd_hash_traverse
The function <<bfd_hash_traverse>> may be used to traverse a
hash table, calling a function on each element. The traversal
is done in a random order.
<<bfd_hash_traverse>> takes as arguments a function and a
generic <<void *>> pointer. The function is called with a
hash table entry (a <<struct bfd_hash_entry *>>) and the
generic pointer passed to <<bfd_hash_traverse>>. The function
must return a <<boolean>> value, which indicates whether to
continue traversing the hash table. If the function returns
<<FALSE>>, <<bfd_hash_traverse>> will stop the traversal and
return immediately.
INODE
Deriving a New Hash Table Type, , Traversing a Hash Table, Hash Tables
SUBSECTION
Deriving a new hash table type
Many uses of hash tables want to store additional information
which each entry in the hash table. Some also find it
convenient to store additional information with the hash table
itself. This may be done using a derived hash table.
Since C is not an object oriented language, creating a derived
hash table requires sticking together some boilerplate
routines with a few differences specific to the type of hash
table you want to create.
An example of a derived hash table is the linker hash table.
The structures for this are defined in <<bfdlink.h>>. The
functions are in <<linker.c>>.
You may also derive a hash table from an already derived hash
table. For example, the a.out linker backend code uses a hash
table derived from the linker hash table.
@menu
@* Define the Derived Structures::
@* Write the Derived Creation Routine::
@* Write Other Derived Routines::
@end menu
INODE
Define the Derived Structures, Write the Derived Creation Routine, Deriving a New Hash Table Type, Deriving a New Hash Table Type
SUBSUBSECTION
Define the derived structures
You must define a structure for an entry in the hash table,
and a structure for the hash table itself.
The first field in the structure for an entry in the hash
table must be of the type used for an entry in the hash table
you are deriving from. If you are deriving from a basic hash
table this is <<struct bfd_hash_entry>>, which is defined in
<<bfd.h>>. The first field in the structure for the hash
table itself must be of the type of the hash table you are
deriving from itself. If you are deriving from a basic hash
table, this is <<struct bfd_hash_table>>.
For example, the linker hash table defines <<struct
bfd_link_hash_entry>> (in <<bfdlink.h>>). The first field,
<<root>>, is of type <<struct bfd_hash_entry>>. Similarly,
the first field in <<struct bfd_link_hash_table>>, <<table>>,
is of type <<struct bfd_hash_table>>.
INODE
Write the Derived Creation Routine, Write Other Derived Routines, Define the Derived Structures, Deriving a New Hash Table Type
SUBSUBSECTION
Write the derived creation routine
You must write a routine which will create and initialize an
entry in the hash table. This routine is passed as the
function argument to <<bfd_hash_table_init>>.
In order to permit other hash tables to be derived from the
hash table you are creating, this routine must be written in a
standard way.
The first argument to the creation routine is a pointer to a
hash table entry. This may be <<NULL>>, in which case the
routine should allocate the right amount of space. Otherwise
the space has already been allocated by a hash table type
derived from this one.
After allocating space, the creation routine must call the
creation routine of the hash table type it is derived from,
passing in a pointer to the space it just allocated. This
will initialize any fields used by the base hash table.
Finally the creation routine must initialize any local fields
for the new hash table type.
Here is a boilerplate example of a creation routine.
@var{function_name} is the name of the routine.
@var{entry_type} is the type of an entry in the hash table you
are creating. @var{base_newfunc} is the name of the creation
routine of the hash table type your hash table is derived
from.
EXAMPLE
.struct bfd_hash_entry *
.@var{function_name} (struct bfd_hash_entry *entry,
. struct bfd_hash_table *table,
. const char *string)
.{
. struct @var{entry_type} *ret = (@var{entry_type} *) entry;
.
. {* Allocate the structure if it has not already been allocated by a
. derived class. *}
. if (ret == NULL)
. {
. ret = bfd_hash_allocate (table, sizeof (* ret));
. if (ret == NULL)
. return NULL;
. }
.
. {* Call the allocation method of the base class. *}
. ret = ((@var{entry_type} *)
. @var{base_newfunc} ((struct bfd_hash_entry *) ret, table, string));
.
. {* Initialize the local fields here. *}
.
. return (struct bfd_hash_entry *) ret;
.}
DESCRIPTION
The creation routine for the linker hash table, which is in
<<linker.c>>, looks just like this example.
@var{function_name} is <<_bfd_link_hash_newfunc>>.
@var{entry_type} is <<struct bfd_link_hash_entry>>.
@var{base_newfunc} is <<bfd_hash_newfunc>>, the creation
routine for a basic hash table.
<<_bfd_link_hash_newfunc>> also initializes the local fields
in a linker hash table entry: <<type>>, <<written>> and
<<next>>.
INODE
Write Other Derived Routines, , Write the Derived Creation Routine, Deriving a New Hash Table Type
SUBSUBSECTION
Write other derived routines
You will want to write other routines for your new hash table,
as well.
You will want an initialization routine which calls the
initialization routine of the hash table you are deriving from
and initializes any other local fields. For the linker hash
table, this is <<_bfd_link_hash_table_init>> in <<linker.c>>.
You will want a lookup routine which calls the lookup routine
of the hash table you are deriving from and casts the result.
The linker hash table uses <<bfd_link_hash_lookup>> in
<<linker.c>> (this actually takes an additional argument which
it uses to decide how to return the looked up value).
You may want a traversal routine. This should just call the
traversal routine of the hash table you are deriving from with
appropriate casts. The linker hash table uses
<<bfd_link_hash_traverse>> in <<linker.c>>.
These routines may simply be defined as macros. For example,
the a.out backend linker hash table, which is derived from the
linker hash table, uses macros for the lookup and traversal
routines. These are <<aout_link_hash_lookup>> and
<<aout_link_hash_traverse>> in aoutx.h.
*/
/* The default number of entries to use when creating a hash table. */
#define DEFAULT_SIZE 4051
/* The following function returns a nearest prime number which is
greater than N, and near a power of two. Copied from libiberty.
Returns zero for ridiculously large N to signify an error. */
static unsigned long
higher_prime_number (unsigned long n)
{
/* These are primes that are near, but slightly smaller than, a
power of two. */
static const unsigned long primes[] =
{
(unsigned long) 31,
(unsigned long) 61,
(unsigned long) 127,
(unsigned long) 251,
(unsigned long) 509,
(unsigned long) 1021,
(unsigned long) 2039,
(unsigned long) 4093,
(unsigned long) 8191,
(unsigned long) 16381,
(unsigned long) 32749,
(unsigned long) 65521,
(unsigned long) 131071,
(unsigned long) 262139,
(unsigned long) 524287,
(unsigned long) 1048573,
(unsigned long) 2097143,
(unsigned long) 4194301,
(unsigned long) 8388593,
(unsigned long) 16777213,
(unsigned long) 33554393,
(unsigned long) 67108859,
(unsigned long) 134217689,
(unsigned long) 268435399,
(unsigned long) 536870909,
(unsigned long) 1073741789,
(unsigned long) 2147483647,
/* 4294967291L */
((unsigned long) 2147483647) + ((unsigned long) 2147483644),
};
const unsigned long *low = &primes[0];
const unsigned long *high = &primes[sizeof (primes) / sizeof (primes[0])];
while (low != high)
{
const unsigned long *mid = low + (high - low) / 2;
if (n >= *mid)
low = mid + 1;
else
high = mid;
}
if (n >= *low)
return 0;
return *low;
}
static unsigned long bfd_default_hash_table_size = DEFAULT_SIZE;
/* Create a new hash table, given a number of entries. */
bfd_boolean
bfd_hash_table_init_n (struct bfd_hash_table *table,
struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
struct bfd_hash_table *,
const char *),
unsigned int entsize,
unsigned int size)
{
unsigned long alloc;
alloc = size;
alloc *= sizeof (struct bfd_hash_entry *);
if (alloc / sizeof (struct bfd_hash_entry *) != size)
{
bfd_set_error (bfd_error_no_memory);
return FALSE;
}
table->memory = (void *) objalloc_create ();
if (table->memory == NULL)
{
bfd_set_error (bfd_error_no_memory);
return FALSE;
}
table->table = (struct bfd_hash_entry **)
objalloc_alloc ((struct objalloc *) table->memory, alloc);
if (table->table == NULL)
{
bfd_set_error (bfd_error_no_memory);
return FALSE;
}
memset ((void *) table->table, 0, alloc);
table->size = size;
table->entsize = entsize;
table->count = 0;
table->frozen = 0;
table->newfunc = newfunc;
return TRUE;
}
/* Create a new hash table with the default number of entries. */
bfd_boolean
bfd_hash_table_init (struct bfd_hash_table *table,
struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
struct bfd_hash_table *,
const char *),
unsigned int entsize)
{
return bfd_hash_table_init_n (table, newfunc, entsize,
bfd_default_hash_table_size);
}
/* Free a hash table. */
void
bfd_hash_table_free (struct bfd_hash_table *table)
{
objalloc_free ((struct objalloc *) table->memory);
table->memory = NULL;
}
static inline unsigned long
bfd_hash_hash (const char *string, unsigned int *lenp)
{
const unsigned char *s;
unsigned long hash;
unsigned int len;
unsigned int c;
hash = 0;
len = 0;
s = (const unsigned char *) string;
while ((c = *s++) != '\0')
{
hash += c + (c << 17);
hash ^= hash >> 2;
}
len = (s - (const unsigned char *) string) - 1;
hash += len + (len << 17);
hash ^= hash >> 2;
if (lenp != NULL)
*lenp = len;
return hash;
}
/* Look up a string in a hash table. */
struct bfd_hash_entry *
bfd_hash_lookup (struct bfd_hash_table *table,
const char *string,
bfd_boolean create,
bfd_boolean copy)
{
unsigned long hash;
struct bfd_hash_entry *hashp;
unsigned int len;
unsigned int _index;
hash = bfd_hash_hash (string, &len);
_index = hash % table->size;
for (hashp = table->table[_index];
hashp != NULL;
hashp = hashp->next)
{
if (hashp->hash == hash
&& strcmp (hashp->string, string) == 0)
return hashp;
}
if (! create)
return NULL;
if (copy)
{
char *new_string;
new_string = (char *) objalloc_alloc ((struct objalloc *) table->memory,
len + 1);
if (!new_string)
{
bfd_set_error (bfd_error_no_memory);
return NULL;
}
memcpy (new_string, string, len + 1);
string = new_string;
}
return bfd_hash_insert (table, string, hash);
}
/* Insert an entry in a hash table. */
struct bfd_hash_entry *
bfd_hash_insert (struct bfd_hash_table *table,
const char *string,
unsigned long hash)
{
struct bfd_hash_entry *hashp;
unsigned int _index;
hashp = (*table->newfunc) (NULL, table, string);
if (hashp == NULL)
return NULL;
hashp->string = string;
hashp->hash = hash;
_index = hash % table->size;
hashp->next = table->table[_index];
table->table[_index] = hashp;
table->count++;
if (!table->frozen && table->count > table->size * 3 / 4)
{
unsigned long newsize = higher_prime_number (table->size);
struct bfd_hash_entry **newtable;
unsigned int hi;
unsigned long alloc = newsize * sizeof (struct bfd_hash_entry *);
/* If we can't find a higher prime, or we can't possibly alloc
that much memory, don't try to grow the table. */
if (newsize == 0 || alloc / sizeof (struct bfd_hash_entry *) != newsize)
{
table->frozen = 1;
return hashp;
}
newtable = ((struct bfd_hash_entry **)
objalloc_alloc ((struct objalloc *) table->memory, alloc));
if (newtable == NULL)
{
table->frozen = 1;
return hashp;
}
memset (newtable, 0, alloc);
for (hi = 0; hi < table->size; hi ++)
while (table->table[hi])
{
struct bfd_hash_entry *chain = table->table[hi];
struct bfd_hash_entry *chain_end = chain;
while (chain_end->next && chain_end->next->hash == chain->hash)
chain_end = chain_end->next;
table->table[hi] = chain_end->next;
_index = chain->hash % newsize;
chain_end->next = newtable[_index];
newtable[_index] = chain;
}
table->table = newtable;
table->size = newsize;
}
return hashp;
}
/* Rename an entry in a hash table. */
void
bfd_hash_rename (struct bfd_hash_table *table,
const char *string,
struct bfd_hash_entry *ent)
{
unsigned int _index;
struct bfd_hash_entry **pph;
_index = ent->hash % table->size;
for (pph = &table->table[_index]; *pph != NULL; pph = &(*pph)->next)
if (*pph == ent)
break;
if (*pph == NULL)
abort ();
*pph = ent->next;
ent->string = string;
ent->hash = bfd_hash_hash (string, NULL);
_index = ent->hash % table->size;
ent->next = table->table[_index];
table->table[_index] = ent;
}
/* Replace an entry in a hash table. */
void
bfd_hash_replace (struct bfd_hash_table *table,
struct bfd_hash_entry *old,
struct bfd_hash_entry *nw)
{
unsigned int _index;
struct bfd_hash_entry **pph;
_index = old->hash % table->size;
for (pph = &table->table[_index];
(*pph) != NULL;
pph = &(*pph)->next)
{
if (*pph == old)
{
*pph = nw;
return;
}
}
abort ();
}
/* Allocate space in a hash table. */
void *
bfd_hash_allocate (struct bfd_hash_table *table,
unsigned int size)
{
void * ret;
ret = objalloc_alloc ((struct objalloc *) table->memory, size);
if (ret == NULL && size != 0)
bfd_set_error (bfd_error_no_memory);
return ret;
}
/* Base method for creating a new hash table entry. */
struct bfd_hash_entry *
bfd_hash_newfunc (struct bfd_hash_entry *entry,
struct bfd_hash_table *table,
const char *string ATTRIBUTE_UNUSED)
{
if (entry == NULL)
entry = (struct bfd_hash_entry *) bfd_hash_allocate (table,
sizeof (* entry));
return entry;
}
/* Traverse a hash table. */
void
bfd_hash_traverse (struct bfd_hash_table *table,
bfd_boolean (*func) (struct bfd_hash_entry *, void *),
void * info)
{
unsigned int i;
table->frozen = 1;
for (i = 0; i < table->size; i++)
{
struct bfd_hash_entry *p;
for (p = table->table[i]; p != NULL; p = p->next)
if (! (*func) (p, info))
goto out;
}
out:
table->frozen = 0;
}
unsigned long
bfd_hash_set_default_size (unsigned long hash_size)
{
/* Extend this prime list if you want more granularity of hash table size. */
static const unsigned long hash_size_primes[] =
{
31, 61, 127, 251, 509, 1021, 2039, 4091, 8191, 16381, 32749, 65537
};
unsigned int _index;
/* Work out best prime number near the hash_size. */
for (_index = 0; _index < ARRAY_SIZE (hash_size_primes) - 1; ++_index)
if (hash_size <= hash_size_primes[_index])
break;
bfd_default_hash_table_size = hash_size_primes[_index];
return bfd_default_hash_table_size;
}
/* A few different object file formats (a.out, COFF, ELF) use a string
table. These functions support adding strings to a string table,
returning the byte offset, and writing out the table.
Possible improvements:
+ look for strings matching trailing substrings of other strings
+ better data structures? balanced trees?
+ look at reducing memory use elsewhere -- maybe if we didn't have
to construct the entire symbol table at once, we could get by
with smaller amounts of VM? (What effect does that have on the
string table reductions?) */
/* An entry in the strtab hash table. */
struct strtab_hash_entry
{
struct bfd_hash_entry root;
/* Index in string table. */
bfd_size_type index;
/* Next string in strtab. */
struct strtab_hash_entry *next;
};
/* The strtab hash table. */
struct bfd_strtab_hash
{
struct bfd_hash_table table;
/* Size of strtab--also next available index. */
bfd_size_type size;
/* First string in strtab. */
struct strtab_hash_entry *first;
/* Last string in strtab. */
struct strtab_hash_entry *last;
/* Whether to precede strings with a two byte length, as in the
XCOFF .debug section. */
bfd_boolean xcoff;
};
/* Routine to create an entry in a strtab. */
static struct bfd_hash_entry *
strtab_hash_newfunc (struct bfd_hash_entry *entry,
struct bfd_hash_table *table,
const char *string)
{
struct strtab_hash_entry *ret = (struct strtab_hash_entry *) entry;
/* Allocate the structure if it has not already been allocated by a
subclass. */
if (ret == NULL)
ret = (struct strtab_hash_entry *) bfd_hash_allocate (table,
sizeof (* ret));
if (ret == NULL)
return NULL;
/* Call the allocation method of the superclass. */
ret = (struct strtab_hash_entry *)
bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string);
if (ret)
{
/* Initialize the local fields. */
ret->index = (bfd_size_type) -1;
ret->next = NULL;
}
return (struct bfd_hash_entry *) ret;
}
/* Look up an entry in an strtab. */
#define strtab_hash_lookup(t, string, create, copy) \
((struct strtab_hash_entry *) \
bfd_hash_lookup (&(t)->table, (string), (create), (copy)))
/* Create a new strtab. */
struct bfd_strtab_hash *
_bfd_stringtab_init (void)
{
struct bfd_strtab_hash *table;
bfd_size_type amt = sizeof (* table);
table = (struct bfd_strtab_hash *) bfd_malloc (amt);
if (table == NULL)
return NULL;
if (!bfd_hash_table_init (&table->table, strtab_hash_newfunc,
sizeof (struct strtab_hash_entry)))
{
free (table);
return NULL;
}
table->size = 0;
table->first = NULL;
table->last = NULL;
table->xcoff = FALSE;
return table;
}
/* Create a new strtab in which the strings are output in the format
used in the XCOFF .debug section: a two byte length precedes each
string. */
struct bfd_strtab_hash *
_bfd_xcoff_stringtab_init (void)
{
struct bfd_strtab_hash *ret;
ret = _bfd_stringtab_init ();
if (ret != NULL)
ret->xcoff = TRUE;
return ret;
}
/* Free a strtab. */
void
_bfd_stringtab_free (struct bfd_strtab_hash *table)
{
bfd_hash_table_free (&table->table);
free (table);
}
/* Get the index of a string in a strtab, adding it if it is not
already present. If HASH is FALSE, we don't really use the hash
table, and we don't eliminate duplicate strings. If COPY is true
then store a copy of STR if creating a new entry. */
bfd_size_type
_bfd_stringtab_add (struct bfd_strtab_hash *tab,
const char *str,
bfd_boolean hash,
bfd_boolean copy)
{
struct strtab_hash_entry *entry;
if (hash)
{
entry = strtab_hash_lookup (tab, str, TRUE, copy);
if (entry == NULL)
return (bfd_size_type) -1;
}
else
{
entry = (struct strtab_hash_entry *) bfd_hash_allocate (&tab->table,
sizeof (* entry));
if (entry == NULL)
return (bfd_size_type) -1;
if (! copy)
entry->root.string = str;
else
{
size_t len = strlen (str) + 1;
char *n;
n = (char *) bfd_hash_allocate (&tab->table, len);
if (n == NULL)
return (bfd_size_type) -1;
memcpy (n, str, len);
entry->root.string = n;
}
entry->index = (bfd_size_type) -1;
entry->next = NULL;
}
if (entry->index == (bfd_size_type) -1)
{
entry->index = tab->size;
tab->size += strlen (str) + 1;
if (tab->xcoff)
{
entry->index += 2;
tab->size += 2;
}
if (tab->first == NULL)
tab->first = entry;
else
tab->last->next = entry;
tab->last = entry;
}
return entry->index;
}
/* Get the number of bytes in a strtab. */
bfd_size_type
_bfd_stringtab_size (struct bfd_strtab_hash *tab)
{
return tab->size;
}
/* Write out a strtab. ABFD must already be at the right location in
the file. */
bfd_boolean
_bfd_stringtab_emit (bfd *abfd, struct bfd_strtab_hash *tab)
{
bfd_boolean xcoff;
struct strtab_hash_entry *entry;
xcoff = tab->xcoff;
for (entry = tab->first; entry != NULL; entry = entry->next)
{
const char *str;
size_t len;
str = entry->root.string;
len = strlen (str) + 1;
if (xcoff)
{
bfd_byte buf[2];
/* The output length includes the null byte. */
bfd_put_16 (abfd, (bfd_vma) len, buf);
if (bfd_bwrite ((void *) buf, (bfd_size_type) 2, abfd) != 2)
return FALSE;
}
if (bfd_bwrite ((void *) str, (bfd_size_type) len, abfd) != len)
return FALSE;
}
return TRUE;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,55 @@
/* bfd initialization stuff
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 2003, 2005, 2007
Free Software Foundation, Inc.
Written by Steve Chamberlain of Cygnus Support.
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"
#include "libbfd.h"
/*
SECTION
Initialization
SUBSECTION
Initialization functions
These are the functions that handle initializing a BFD.
*/
/*
FUNCTION
bfd_init
SYNOPSIS
void bfd_init (void);
DESCRIPTION
This routine must be called before any other BFD function to
initialize magical internal data structures.
*/
/* Actually, there is currently nothing for this function to do.
However, someday it may be needed, so keep it around. */
void
bfd_init (void)
{
}

View File

@@ -0,0 +1,691 @@
/* BFD back-end data structures for a.out (and similar) files.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
Written by Cygnus Support.
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. */
#ifndef LIBAOUT_H
#define LIBAOUT_H
/* We try to encapsulate the differences in the various a.out file
variants in a few routines, and otherwise share large masses of code.
This means we only have to fix bugs in one place, most of the time. */
#include "bfdlink.h"
/* Macros for accessing components in an aout header. */
#define H_PUT_64 bfd_h_put_64
#define H_PUT_32 bfd_h_put_32
#define H_PUT_16 bfd_h_put_16
#define H_PUT_8 bfd_h_put_8
#define H_PUT_S64 bfd_h_put_signed_64
#define H_PUT_S32 bfd_h_put_signed_32
#define H_PUT_S16 bfd_h_put_signed_16
#define H_PUT_S8 bfd_h_put_signed_8
#define H_GET_64 bfd_h_get_64
#define H_GET_32 bfd_h_get_32
#define H_GET_16 bfd_h_get_16
#define H_GET_8 bfd_h_get_8
#define H_GET_S64 bfd_h_get_signed_64
#define H_GET_S32 bfd_h_get_signed_32
#define H_GET_S16 bfd_h_get_signed_16
#define H_GET_S8 bfd_h_get_signed_8
/* Parameterize the a.out code based on whether it is being built
for a 32-bit architecture or a 64-bit architecture. */
/* Do not "beautify" the CONCAT* macro args. Traditional C will not
remove whitespace added here, and thus will fail to concatenate
the tokens. */
#if ARCH_SIZE==64
#define GET_WORD H_GET_64
#define GET_SWORD H_GET_S64
#define GET_MAGIC H_GET_32
#define PUT_WORD H_PUT_64
#define PUT_MAGIC H_PUT_32
#ifndef NAME
#define NAME(x,y) CONCAT3 (x,_64_,y)
#endif
#define JNAME(x) CONCAT2 (x,_64)
#define BYTES_IN_WORD 8
#else
#if ARCH_SIZE==16
#define GET_WORD H_GET_16
#define GET_SWORD H_GET_S16
#define GET_MAGIC H_GET_16
#define PUT_WORD H_PUT_16
#define PUT_MAGIC H_PUT_16
#ifndef NAME
#define NAME(x,y) CONCAT3 (x,_16_,y)
#endif
#define JNAME(x) CONCAT2 (x,_16)
#define BYTES_IN_WORD 2
#else /* ARCH_SIZE == 32 */
#define GET_WORD H_GET_32
#define GET_SWORD H_GET_S32
#define GET_MAGIC H_GET_32
#define PUT_WORD H_PUT_32
#define PUT_MAGIC H_PUT_32
#ifndef NAME
#define NAME(x,y) CONCAT3 (x,_32_,y)
#endif
#define JNAME(x) CONCAT2 (x,_32)
#define BYTES_IN_WORD 4
#endif /* ARCH_SIZE==32 */
#endif /* ARCH_SIZE==64 */
/* Declare at file level, since used in parameter lists, which have
weird scope. */
struct external_exec;
struct external_nlist;
struct reloc_ext_external;
struct reloc_std_external;
/* a.out backend linker hash table entries. */
struct aout_link_hash_entry
{
struct bfd_link_hash_entry root;
/* Whether this symbol has been written out. */
bfd_boolean written;
/* Symbol index in output file. */
int indx;
};
/* a.out backend linker hash table. */
struct aout_link_hash_table
{
struct bfd_link_hash_table root;
};
/* Look up an entry in an a.out link hash table. */
#define aout_link_hash_lookup(table, string, create, copy, follow) \
((struct aout_link_hash_entry *) \
bfd_link_hash_lookup (&(table)->root, (string), (create), (copy), (follow)))
/* Traverse an a.out link hash table. */
#define aout_link_hash_traverse(table, func, info) \
(bfd_link_hash_traverse \
(&(table)->root, \
(bfd_boolean (*) (struct bfd_link_hash_entry *, void *)) (func), \
(info)))
/* Get the a.out link hash table from the info structure. This is
just a cast. */
#define aout_hash_table(p) ((struct aout_link_hash_table *) ((p)->hash))
/* Back-end information for various a.out targets. */
struct aout_backend_data
{
/* Are ZMAGIC files mapped contiguously? If so, the text section may
need more padding, if the segment size (granularity for memory access
control) is larger than the page size. */
unsigned char zmagic_mapped_contiguous;
/* If this flag is set, ZMAGIC/NMAGIC file headers get mapped in with the
text section, which starts immediately after the file header.
If not, the text section starts on the next page. */
unsigned char text_includes_header;
/* If this flag is set, then if the entry address is not in the
first SEGMENT_SIZE bytes of the text section, it is taken to be
the address of the start of the text section. This can be useful
for kernels. */
unsigned char entry_is_text_address;
/* The value to pass to N_SET_FLAGS. */
unsigned char exec_hdr_flags;
/* If the text section VMA isn't specified, and we need an absolute
address, use this as the default. If we're producing a relocatable
file, zero is always used. */
/* ?? Perhaps a callback would be a better choice? Will this do anything
reasonable for a format that handles multiple CPUs with different
load addresses for each? */
bfd_vma default_text_vma;
/* Callback for setting the page and segment sizes, if they can't be
trivially determined from the architecture. */
bfd_boolean (*set_sizes) (bfd *);
/* zmagic files only. For go32, the length of the exec header contributes
to the size of the text section in the file for alignment purposes but
does *not* get counted in the length of the text section. */
unsigned char exec_header_not_counted;
/* Callback from the add symbols phase of the linker code to handle
a dynamic object. */
bfd_boolean (*add_dynamic_symbols)
(bfd *, struct bfd_link_info *, struct external_nlist **,
bfd_size_type *, char **);
/* Callback from the add symbols phase of the linker code to handle
adding a single symbol to the global linker hash table. */
bfd_boolean (*add_one_symbol)
(struct bfd_link_info *, bfd *, const char *, flagword,
asection *, bfd_vma, const char *, bfd_boolean, bfd_boolean,
struct bfd_link_hash_entry **);
/* Called to handle linking a dynamic object. */
bfd_boolean (*link_dynamic_object)
(struct bfd_link_info *, bfd *);
/* Called for each global symbol being written out by the linker.
This should write out the dynamic symbol information. */
bfd_boolean (*write_dynamic_symbol)
(bfd *, struct bfd_link_info *, struct aout_link_hash_entry *);
/* If this callback is not NULL, the linker calls it for each reloc.
RELOC is a pointer to the unswapped reloc. If *SKIP is set to
TRUE, the reloc will be skipped. *RELOCATION may be changed to
change the effects of the relocation. */
bfd_boolean (*check_dynamic_reloc)
(struct bfd_link_info *info, bfd *input_bfd,
asection *input_section, struct aout_link_hash_entry *h,
void * reloc, bfd_byte *contents, bfd_boolean *skip,
bfd_vma *relocation);
/* Called at the end of a link to finish up any dynamic linking
information. */
bfd_boolean (*finish_dynamic_link) (bfd *, struct bfd_link_info *);
};
#define aout_backend_info(abfd) \
((const struct aout_backend_data *)((abfd)->xvec->backend_data))
/* This is the layout in memory of a "struct exec" while we process it.
All 'lengths' are given as a number of bytes.
All 'alignments' are for relinkable files only; an alignment of
'n' indicates the corresponding segment must begin at an
address that is a multiple of (2**n). */
struct internal_exec
{
long a_info; /* Magic number and flags, packed. */
bfd_vma a_text; /* Length of text, in bytes. */
bfd_vma a_data; /* Length of data, in bytes. */
bfd_vma a_bss; /* Length of uninitialized data area in mem. */
bfd_vma a_syms; /* Length of symbol table data in file. */
bfd_vma a_entry; /* Start address. */
bfd_vma a_trsize; /* Length of text's relocation info, in bytes. */
bfd_vma a_drsize; /* Length of data's relocation info, in bytes. */
/* Added for i960 */
bfd_vma a_tload; /* Text runtime load address. */
bfd_vma a_dload; /* Data runtime load address. */
unsigned char a_talign; /* Alignment of text segment. */
unsigned char a_dalign; /* Alignment of data segment. */
unsigned char a_balign; /* Alignment of bss segment. */
char a_relaxable; /* Enough info for linker relax. */
};
/* Magic number is written
< MSB >
3130292827262524232221201918171615141312111009080706050403020100
< FLAGS >< MACHINE TYPE >< MAGIC NUMBER > */
/* Magic number for NetBSD is
<MSB >
3130292827262524232221201918171615141312111009080706050403020100
< FLAGS >< MACHINE TYPE >< MAGIC NUMBER > */
enum machine_type
{
M_UNKNOWN = 0,
M_68010 = 1,
M_68020 = 2,
M_SPARC = 3,
/* Skip a bunch so we don't run into any of SUN's numbers. */
/* Make these up for the ns32k. */
M_NS32032 = (64), /* NS32032 running ? */
M_NS32532 = (64 + 5), /* NS32532 running mach. */
M_386 = 100,
M_29K = 101, /* AMD 29000. */
M_386_DYNIX = 102, /* Sequent running dynix. */
M_ARM = 103, /* Advanced Risc Machines ARM. */
M_SPARCLET = 131, /* SPARClet = M_SPARC + 128. */
M_386_NETBSD = 134, /* NetBSD/i386 binary. */
M_68K_NETBSD = 135, /* NetBSD/m68k binary. */
M_68K4K_NETBSD = 136, /* NetBSD/m68k4k binary. */
M_532_NETBSD = 137, /* NetBSD/ns32k binary. */
M_SPARC_NETBSD = 138, /* NetBSD/sparc binary. */
M_PMAX_NETBSD = 139, /* NetBSD/pmax (MIPS little-endian) binary. */
M_VAX_NETBSD = 140, /* NetBSD/vax binary. */
M_ALPHA_NETBSD = 141, /* NetBSD/alpha binary. */
M_ARM6_NETBSD = 143, /* NetBSD/arm32 binary. */
M_SPARCLET_1 = 147, /* 0x93, reserved. */
M_POWERPC_NETBSD = 149, /* NetBSD/powerpc (big-endian) binary. */
M_VAX4K_NETBSD = 150, /* NetBSD/vax 4K pages binary. */
M_MIPS1 = 151, /* MIPS R2000/R3000 binary. */
M_MIPS2 = 152, /* MIPS R4000/R6000 binary. */
M_88K_OPENBSD = 153, /* OpenBSD/m88k binary. */
M_HPPA_OPENBSD = 154, /* OpenBSD/hppa binary. */
M_SPARC64_NETBSD = 156, /* NetBSD/sparc64 binary. */
M_X86_64_NETBSD = 157, /* NetBSD/amd64 binary. */
M_SPARCLET_2 = 163, /* 0xa3, reserved. */
M_SPARCLET_3 = 179, /* 0xb3, reserved. */
M_SPARCLET_4 = 195, /* 0xc3, reserved. */
M_HP200 = 200, /* HP 200 (68010) BSD binary. */
M_HP300 = (300 % 256), /* HP 300 (68020+68881) BSD binary. */
M_HPUX = (0x20c % 256), /* HP 200/300 HPUX binary. */
M_SPARCLET_5 = 211, /* 0xd3, reserved. */
M_SPARCLET_6 = 227, /* 0xe3, reserved. */
/*M_SPARCLET_7 = 243 / * 0xf3, reserved. */
M_SPARCLITE_LE = 243,
M_CRIS = 255 /* Axis CRIS binary. */
};
#define N_DYNAMIC(exec) ((exec).a_info & 0x80000000)
#ifndef N_MAGIC
# define N_MAGIC(exec) ((exec).a_info & 0xffff)
#endif
#ifndef N_MACHTYPE
# define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
#endif
#ifndef N_FLAGS
# define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff)
#endif
#ifndef N_SET_INFO
# define N_SET_INFO(exec, magic, type, flags) \
((exec).a_info = ((magic) & 0xffff) \
| (((int)(type) & 0xff) << 16) \
| (((flags) & 0xff) << 24))
#endif
#ifndef N_SET_DYNAMIC
# define N_SET_DYNAMIC(exec, dynamic) \
((exec).a_info = (dynamic) ? (long) ((exec).a_info | 0x80000000) : \
((exec).a_info & 0x7fffffff))
#endif
#ifndef N_SET_MAGIC
# define N_SET_MAGIC(exec, magic) \
((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff)))
#endif
#ifndef N_SET_MACHTYPE
# define N_SET_MACHTYPE(exec, machtype) \
((exec).a_info = \
((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16))
#endif
#ifndef N_SET_FLAGS
# define N_SET_FLAGS(exec, flags) \
((exec).a_info = \
((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24))
#endif
typedef struct aout_symbol
{
asymbol symbol;
short desc;
char other;
unsigned char type;
} aout_symbol_type;
/* The `tdata' struct for all a.out-like object file formats.
Various things depend on this struct being around any time an a.out
file is being handled. An example is dbxread.c in GDB. */
enum aout_subformat {
default_format = 0,
/* Used on HP 9000/300 running HP/UX. See hp300hpux.c. */
gnu_encap_format,
/* Used on Linux, 386BSD, etc. See include/aout/aout64.h. */
q_magic_format
};
enum aout_magic {
undecided_magic = 0,
z_magic,
o_magic,
n_magic
};
struct aoutdata
{
struct internal_exec *hdr; /* Exec file header. */
aout_symbol_type *symbols; /* Symtab for input bfd. */
/* For ease, we do this. */
asection *textsec;
asection *datasec;
asection *bsssec;
/* We remember these offsets so that after check_file_format, we have
no dependencies on the particular format of the exec_hdr. */
file_ptr sym_filepos;
file_ptr str_filepos;
/* Size of a relocation entry in external form. */
unsigned reloc_entry_size;
/* Size of a symbol table entry in external form. */
unsigned symbol_entry_size;
/* Page size - needed for alignment of demand paged files. */
unsigned long page_size;
/* Segment size - needed for alignment of demand paged files. */
unsigned long segment_size;
/* Zmagic disk block size - need to align the start of the text
section in ZMAGIC binaries. Normally the same as page_size. */
unsigned long zmagic_disk_block_size;
unsigned exec_bytes_size;
unsigned vma_adjusted : 1;
/* Used when a bfd supports several highly similar formats. */
enum aout_subformat subformat;
enum aout_magic magic;
/* A buffer for find_nearest_line. */
char *line_buf;
/* The external symbol information. */
struct external_nlist *external_syms;
bfd_size_type external_sym_count;
bfd_window sym_window;
char *external_strings;
bfd_size_type external_string_size;
bfd_window string_window;
struct aout_link_hash_entry **sym_hashes;
/* A pointer for shared library information. */
void * dynamic_info;
/* A mapping from local symbols to offsets into the global offset
table, used when linking on SunOS. This is indexed by the symbol
index. */
bfd_vma *local_got_offsets;
};
struct aout_data_struct
{
struct aoutdata a;
struct internal_exec e;
};
#define adata(bfd) ((bfd)->tdata.aout_data->a)
#define exec_hdr(bfd) (adata (bfd).hdr)
#define obj_aout_symbols(bfd) (adata (bfd).symbols)
#define obj_textsec(bfd) (adata (bfd).textsec)
#define obj_datasec(bfd) (adata (bfd).datasec)
#define obj_bsssec(bfd) (adata (bfd).bsssec)
#define obj_sym_filepos(bfd) (adata (bfd).sym_filepos)
#define obj_str_filepos(bfd) (adata (bfd).str_filepos)
#define obj_reloc_entry_size(bfd) (adata (bfd).reloc_entry_size)
#define obj_symbol_entry_size(bfd) (adata (bfd).symbol_entry_size)
#define obj_aout_subformat(bfd) (adata (bfd).subformat)
#define obj_aout_external_syms(bfd) (adata (bfd).external_syms)
#define obj_aout_external_sym_count(bfd) (adata (bfd).external_sym_count)
#define obj_aout_sym_window(bfd) (adata (bfd).sym_window)
#define obj_aout_external_strings(bfd) (adata (bfd).external_strings)
#define obj_aout_external_string_size(bfd) (adata (bfd).external_string_size)
#define obj_aout_string_window(bfd) (adata (bfd).string_window)
#define obj_aout_sym_hashes(bfd) (adata (bfd).sym_hashes)
#define obj_aout_dynamic_info(bfd) (adata (bfd).dynamic_info)
/* We take the address of the first element of an asymbol to ensure that the
macro is only ever applied to an asymbol. */
#define aout_symbol(asymbol) ((aout_symbol_type *)(&(asymbol)->the_bfd))
/* Information we keep for each a.out section. This is currently only
used by the a.out backend linker. */
struct aout_section_data_struct
{
/* The unswapped relocation entries for this section. */
void * relocs;
};
#define aout_section_data(s) \
((struct aout_section_data_struct *) (s)->used_by_bfd)
#define set_aout_section_data(s,v) \
((s)->used_by_bfd = (void *)&(v)->relocs)
/* Prototype declarations for functions defined in aoutx.h. */
extern bfd_boolean NAME (aout, squirt_out_relocs)
(bfd *, asection *);
extern bfd_boolean NAME (aout, make_sections)
(bfd *);
extern const bfd_target * NAME (aout, some_aout_object_p)
(bfd *, struct internal_exec *, const bfd_target *(*) (bfd *));
extern bfd_boolean NAME (aout, mkobject)
(bfd *);
extern enum machine_type NAME (aout, machine_type)
(enum bfd_architecture, unsigned long, bfd_boolean *);
extern bfd_boolean NAME (aout, set_arch_mach)
(bfd *, enum bfd_architecture, unsigned long);
extern bfd_boolean NAME (aout, new_section_hook)
(bfd *, asection *);
extern bfd_boolean NAME (aout, set_section_contents)
(bfd *, sec_ptr, const void *, file_ptr, bfd_size_type);
extern asymbol * NAME (aout, make_empty_symbol)
(bfd *);
extern bfd_boolean NAME (aout, translate_symbol_table)
(bfd *, aout_symbol_type *, struct external_nlist *, bfd_size_type,
char *, bfd_size_type, bfd_boolean);
extern bfd_boolean NAME (aout, slurp_symbol_table)
(bfd *);
extern bfd_boolean NAME (aout, write_syms)
(bfd *);
extern void NAME (aout, reclaim_symbol_table)
(bfd *);
extern long NAME (aout, get_symtab_upper_bound)
(bfd *);
extern long NAME (aout, canonicalize_symtab)
(bfd *, asymbol **);
extern void NAME (aout, swap_ext_reloc_in)
(bfd *, struct reloc_ext_external *, arelent *, asymbol **,
bfd_size_type);
extern void NAME (aout, swap_std_reloc_in)
(bfd *, struct reloc_std_external *, arelent *, asymbol **,
bfd_size_type);
extern reloc_howto_type * NAME (aout, reloc_type_lookup)
(bfd *, bfd_reloc_code_real_type);
extern reloc_howto_type * NAME (aout, reloc_name_lookup)
(bfd *, const char *);
extern bfd_boolean NAME (aout, slurp_reloc_table)
(bfd *, sec_ptr, asymbol **);
extern long NAME (aout, canonicalize_reloc)
(bfd *, sec_ptr, arelent **, asymbol **);
extern long NAME (aout, get_reloc_upper_bound)
(bfd *, sec_ptr);
extern void NAME (aout, reclaim_reloc)
(bfd *, sec_ptr);
extern alent * NAME (aout, get_lineno)
(bfd *, asymbol *);
extern void NAME (aout, print_symbol)
(bfd *, void *, asymbol *, bfd_print_symbol_type);
extern void NAME (aout, get_symbol_info)
(bfd *, asymbol *, symbol_info *);
extern bfd_boolean NAME (aout, find_nearest_line)
(bfd *, asection *, asymbol **, bfd_vma, const char **,
const char **, unsigned int *);
extern long NAME (aout, read_minisymbols)
(bfd *, bfd_boolean, void * *, unsigned int *);
extern asymbol * NAME (aout, minisymbol_to_symbol)
(bfd *, bfd_boolean, const void *, asymbol *);
extern int NAME (aout, sizeof_headers)
(bfd *, struct bfd_link_info *);
extern bfd_boolean NAME (aout, adjust_sizes_and_vmas)
(bfd *, bfd_size_type *, file_ptr *);
extern void NAME (aout, swap_exec_header_in)
(bfd *, struct external_exec *, struct internal_exec *);
extern void NAME (aout, swap_exec_header_out)
(bfd *, struct internal_exec *, struct external_exec *);
extern struct bfd_hash_entry * NAME (aout, link_hash_newfunc)
(struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
extern bfd_boolean NAME (aout, link_hash_table_init)
(struct aout_link_hash_table *, bfd *,
struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
struct bfd_hash_table *,
const char *),
unsigned int);
extern struct bfd_link_hash_table * NAME (aout, link_hash_table_create)
(bfd *);
extern bfd_boolean NAME (aout, link_add_symbols)
(bfd *, struct bfd_link_info *);
extern bfd_boolean NAME (aout, final_link)
(bfd *, struct bfd_link_info *,
void (*) (bfd *, file_ptr *, file_ptr *, file_ptr *));
extern bfd_boolean NAME (aout, bfd_free_cached_info)
(bfd *);
#define aout_32_find_inliner_info _bfd_nosymbols_find_inliner_info
#if 0 /* Are these needed? */
#define aout_16_find_inliner_info _bfd_nosymbols_find_inliner_info
#define aout_64_find_inliner_info _bfd_nosymbols_find_inliner_info
#endif
/* A.out uses the generic versions of these routines... */
#define aout_16_get_section_contents _bfd_generic_get_section_contents
#define aout_32_get_section_contents _bfd_generic_get_section_contents
#define aout_64_get_section_contents _bfd_generic_get_section_contents
#ifndef NO_WRITE_HEADER_KLUDGE
#define NO_WRITE_HEADER_KLUDGE 0
#endif
#ifndef aout_32_bfd_is_local_label_name
#define aout_32_bfd_is_local_label_name bfd_generic_is_local_label_name
#endif
#ifndef aout_32_bfd_is_target_special_symbol
#define aout_32_bfd_is_target_special_symbol \
((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
#endif
#ifndef WRITE_HEADERS
#define WRITE_HEADERS(abfd, execp) \
{ \
bfd_size_type text_size; /* Dummy vars. */ \
file_ptr text_end; \
\
if (adata(abfd).magic == undecided_magic) \
NAME (aout, adjust_sizes_and_vmas) (abfd, & text_size, & text_end); \
\
execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
execp->a_entry = bfd_get_start_address (abfd); \
\
execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \
obj_reloc_entry_size (abfd)); \
execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \
obj_reloc_entry_size (abfd)); \
NAME (aout, swap_exec_header_out) (abfd, execp, & exec_bytes); \
\
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 \
|| bfd_bwrite (& exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, \
abfd) != EXEC_BYTES_SIZE) \
return FALSE; \
/* Now write out reloc info, followed by syms and strings. */ \
\
if (bfd_get_outsymbols (abfd) != NULL \
&& bfd_get_symcount (abfd) != 0) \
{ \
if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET) != 0)\
return FALSE; \
\
if (! NAME (aout, write_syms) (abfd)) \
return FALSE; \
} \
\
if (bfd_seek (abfd, (file_ptr) (N_TRELOFF (*execp)), SEEK_SET) != 0) \
return FALSE; \
if (!NAME (aout, squirt_out_relocs) (abfd, obj_textsec (abfd))) \
return FALSE; \
\
if (bfd_seek (abfd, (file_ptr) (N_DRELOFF (*execp)), SEEK_SET) != 0) \
return FALSE; \
if (!NAME (aout, squirt_out_relocs) (abfd, obj_datasec (abfd))) \
return FALSE; \
}
#endif
/* Test if a read-only section can be merged with .text. This is
possible if:
1. Section has file contents and is read-only.
2. The VMA of the section is after the end of .text and before
the start of .data.
3. The image is demand-pageable (otherwise, a_text in the header
will not reflect the gap between .text and .data). */
#define aout_section_merge_with_text_p(abfd, sec) \
(((sec)->flags & (SEC_HAS_CONTENTS | SEC_READONLY)) == \
(SEC_HAS_CONTENTS | SEC_READONLY) \
&& obj_textsec (abfd) != NULL \
&& obj_datasec (abfd) != NULL \
&& (sec)->vma >= (obj_textsec (abfd)->vma + \
obj_textsec (abfd)->size) \
&& ((sec)->vma + (sec)->size) <= obj_datasec (abfd)->vma \
&& ((abfd)->flags & D_PAGED) != 0)
#endif /* ! defined (LIBAOUT_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,967 @@
/* DO NOT EDIT! -*- buffer-read-only: t -*- This file is automatically
generated from "libcoff-in.h" and "coffcode.h".
Run "make headers" in your build bfd/ to regenerate. */
/* BFD COFF object file private structure.
Copyright 1990-2013 Free Software Foundation, Inc.
Written by Cygnus Support.
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 "bfdlink.h"
/* Object file tdata; access macros. */
#define coff_data(bfd) ((bfd)->tdata.coff_obj_data)
#define obj_pe(bfd) (coff_data (bfd)->pe)
#define obj_symbols(bfd) (coff_data (bfd)->symbols)
#define obj_sym_filepos(bfd) (coff_data (bfd)->sym_filepos)
#define obj_relocbase(bfd) (coff_data (bfd)->relocbase)
#define obj_raw_syments(bfd) (coff_data (bfd)->raw_syments)
#define obj_raw_syment_count(bfd) (coff_data (bfd)->raw_syment_count)
#define obj_convert(bfd) (coff_data (bfd)->conversion_table)
#define obj_conv_table_size(bfd) (coff_data (bfd)->conv_table_size)
#define obj_coff_external_syms(bfd) (coff_data (bfd)->external_syms)
#define obj_coff_keep_syms(bfd) (coff_data (bfd)->keep_syms)
#define obj_coff_strings(bfd) (coff_data (bfd)->strings)
#define obj_coff_keep_strings(bfd) (coff_data (bfd)->keep_strings)
#define obj_coff_sym_hashes(bfd) (coff_data (bfd)->sym_hashes)
#define obj_coff_strings_written(bfd) (coff_data (bfd)->strings_written)
#define obj_coff_local_toc_table(bfd) (coff_data (bfd)->local_toc_sym_map)
/* `Tdata' information kept for COFF files. */
typedef struct coff_tdata
{
struct coff_symbol_struct *symbols; /* Symtab for input bfd. */
unsigned int *conversion_table;
int conv_table_size;
file_ptr sym_filepos;
struct coff_ptr_struct *raw_syments;
unsigned long raw_syment_count;
/* These are only valid once writing has begun. */
long int relocbase;
/* These members communicate important constants about the symbol table
to GDB's symbol-reading code. These `constants' unfortunately vary
from coff implementation to implementation... */
unsigned local_n_btmask;
unsigned local_n_btshft;
unsigned local_n_tmask;
unsigned local_n_tshift;
unsigned local_symesz;
unsigned local_auxesz;
unsigned local_linesz;
/* The unswapped external symbols. May be NULL. Read by
_bfd_coff_get_external_symbols. */
void * external_syms;
/* If this is TRUE, the external_syms may not be freed. */
bfd_boolean keep_syms;
/* The string table. May be NULL. Read by
_bfd_coff_read_string_table. */
char *strings;
/* If this is TRUE, the strings may not be freed. */
bfd_boolean keep_strings;
/* If this is TRUE, the strings have been written out already. */
bfd_boolean strings_written;
/* Is this a PE format coff file? */
int pe;
/* Used by the COFF backend linker. */
struct coff_link_hash_entry **sym_hashes;
/* Used by the pe linker for PowerPC. */
int *local_toc_sym_map;
struct bfd_link_info *link_info;
/* Used by coff_find_nearest_line. */
void * line_info;
/* A place to stash dwarf2 info for this bfd. */
void * dwarf2_find_line_info;
/* The timestamp from the COFF file header. */
long timestamp;
/* Copy of some of the f_flags bits in the COFF filehdr structure,
used by ARM code. */
flagword flags;
/* coff-stgo32 EXE stub header after BFD tdata has been allocated. Its data
is kept in internal_filehdr.go32stub beforehand. */
char *go32stub;
} coff_data_type;
/* Tdata for pe image files. */
typedef struct pe_tdata
{
coff_data_type coff;
struct internal_extra_pe_aouthdr pe_opthdr;
int dll;
int has_reloc_section;
int dont_strip_reloc;
bfd_boolean insert_timestamp;
bfd_boolean (*in_reloc_p) (bfd *, reloc_howto_type *);
flagword real_flags;
} pe_data_type;
#define pe_data(bfd) ((bfd)->tdata.pe_obj_data)
/* Tdata for XCOFF files. */
struct xcoff_tdata
{
/* Basic COFF information. */
coff_data_type coff;
/* TRUE if this is an XCOFF64 file. */
bfd_boolean xcoff64;
/* TRUE if a large a.out header should be generated. */
bfd_boolean full_aouthdr;
/* TOC value. */
bfd_vma toc;
/* Index of section holding TOC. */
int sntoc;
/* Index of section holding entry point. */
int snentry;
/* .text alignment from optional header. */
int text_align_power;
/* .data alignment from optional header. */
int data_align_power;
/* modtype from optional header. */
short modtype;
/* cputype from optional header. */
short cputype;
/* maxdata from optional header. */
bfd_vma maxdata;
/* maxstack from optional header. */
bfd_vma maxstack;
/* Used by the XCOFF backend linker. */
asection **csects;
long *debug_indices;
unsigned int *lineno_counts;
unsigned int import_file_id;
};
#define xcoff_data(abfd) ((abfd)->tdata.xcoff_obj_data)
/* We take the address of the first element of an asymbol to ensure that the
macro is only ever applied to an asymbol. */
#define coffsymbol(asymbol) ((coff_symbol_type *)(&((asymbol)->the_bfd)))
/* The used_by_bfd field of a section may be set to a pointer to this
structure. */
struct coff_section_tdata
{
/* The relocs, swapped into COFF internal form. This may be NULL. */
struct internal_reloc *relocs;
/* If this is TRUE, the relocs entry may not be freed. */
bfd_boolean keep_relocs;
/* The section contents. This may be NULL. */
bfd_byte *contents;
/* If this is TRUE, the contents entry may not be freed. */
bfd_boolean keep_contents;
/* Information cached by coff_find_nearest_line. */
bfd_vma offset;
unsigned int i;
const char *function;
/* Optional information about a COMDAT entry; NULL if not COMDAT. */
struct coff_comdat_info *comdat;
int line_base;
/* A pointer used for .stab linking optimizations. */
void * stab_info;
/* Available for individual backends. */
void * tdata;
};
/* An accessor macro for the coff_section_tdata structure. */
#define coff_section_data(abfd, sec) \
((struct coff_section_tdata *) (sec)->used_by_bfd)
/* Tdata for sections in XCOFF files. This is used by the linker. */
struct xcoff_section_tdata
{
/* Used for XCOFF csects created by the linker; points to the real
XCOFF section which contains this csect. */
asection *enclosing;
/* The lineno_count field for the enclosing section, because we are
going to clobber it there. */
unsigned int lineno_count;
/* The first and last symbol indices for symbols used by this csect. */
unsigned long first_symndx;
unsigned long last_symndx;
};
/* An accessor macro the xcoff_section_tdata structure. */
#define xcoff_section_data(abfd, sec) \
((struct xcoff_section_tdata *) coff_section_data ((abfd), (sec))->tdata)
/* Tdata for sections in PE files. */
struct pei_section_tdata
{
/* The virtual size of the section. */
bfd_size_type virt_size;
/* The PE section flags. */
long pe_flags;
};
/* An accessor macro for the pei_section_tdata structure. */
#define pei_section_data(abfd, sec) \
((struct pei_section_tdata *) coff_section_data ((abfd), (sec))->tdata)
/* COFF linker hash table entries. */
struct coff_link_hash_entry
{
struct bfd_link_hash_entry root;
/* Symbol index in output file. Set to -1 initially. Set to -2 if
there is a reloc against this symbol. */
long indx;
/* Symbol type. */
unsigned short type;
/* Symbol class. */
unsigned char symbol_class;
/* Number of auxiliary entries. */
char numaux;
/* BFD to take auxiliary entries from. */
bfd *auxbfd;
/* Pointer to array of auxiliary entries, if any. */
union internal_auxent *aux;
/* Flag word; legal values follow. */
unsigned short coff_link_hash_flags;
/* Symbol is a PE section symbol. */
#define COFF_LINK_HASH_PE_SECTION_SYMBOL (01)
};
/* COFF linker hash table. */
struct coff_link_hash_table
{
struct bfd_link_hash_table root;
/* A pointer to information used to link stabs in sections. */
struct stab_info stab_info;
};
/* Look up an entry in a COFF linker hash table. */
#define coff_link_hash_lookup(table, string, create, copy, follow) \
((struct coff_link_hash_entry *) \
bfd_link_hash_lookup (&(table)->root, (string), (create), \
(copy), (follow)))
/* Traverse a COFF linker hash table. */
#define coff_link_hash_traverse(table, func, info) \
(bfd_link_hash_traverse \
(&(table)->root, \
(bfd_boolean (*) (struct bfd_link_hash_entry *, void *)) (func), \
(info)))
/* Get the COFF linker hash table from a link_info structure. */
#define coff_hash_table(p) ((struct coff_link_hash_table *) ((p)->hash))
/* Functions in coffgen.c. */
extern const bfd_target *coff_object_p
(bfd *);
extern struct bfd_section *coff_section_from_bfd_index
(bfd *, int);
extern long coff_get_symtab_upper_bound
(bfd *);
extern long coff_canonicalize_symtab
(bfd *, asymbol **);
extern int coff_count_linenumbers
(bfd *);
extern struct coff_symbol_struct *coff_symbol_from
(bfd *, asymbol *);
extern bfd_boolean coff_renumber_symbols
(bfd *, int *);
extern void coff_mangle_symbols
(bfd *);
extern bfd_boolean coff_write_symbols
(bfd *);
extern bfd_boolean coff_write_alien_symbol
(bfd *, asymbol *, struct internal_syment *, bfd_vma *,
bfd_size_type *, asection **, bfd_size_type *);
extern bfd_boolean coff_write_linenumbers
(bfd *);
extern alent *coff_get_lineno
(bfd *, asymbol *);
extern asymbol *coff_section_symbol
(bfd *, char *);
extern bfd_boolean _bfd_coff_get_external_symbols
(bfd *);
extern const char *_bfd_coff_read_string_table
(bfd *);
extern bfd_boolean _bfd_coff_free_symbols
(bfd *);
extern struct coff_ptr_struct *coff_get_normalized_symtab
(bfd *);
extern long coff_get_reloc_upper_bound
(bfd *, sec_ptr);
extern asymbol *coff_make_empty_symbol
(bfd *);
extern void coff_print_symbol
(bfd *, void * filep, asymbol *, bfd_print_symbol_type);
extern void coff_get_symbol_info
(bfd *, asymbol *, symbol_info *ret);
extern bfd_boolean _bfd_coff_is_local_label_name
(bfd *, const char *);
extern asymbol *coff_bfd_make_debug_symbol
(bfd *, void *, unsigned long);
extern bfd_boolean coff_find_nearest_line
(bfd *, asection *, asymbol **, bfd_vma, const char **,
const char **, unsigned int *);
extern bfd_boolean coff_find_nearest_line_discriminator
(bfd *, asection *, asymbol **, bfd_vma, const char **,
const char **, unsigned int *, unsigned int *);
struct dwarf_debug_section;
extern bfd_boolean coff_find_nearest_line_with_names
(bfd *, const struct dwarf_debug_section *, asection *, asymbol **,
bfd_vma, const char **, const char **, unsigned int *);
extern bfd_boolean coff_find_inliner_info
(bfd *, const char **, const char **, unsigned int *);
extern int coff_sizeof_headers
(bfd *, struct bfd_link_info *);
extern bfd_boolean bfd_coff_reloc16_relax_section
(bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
extern bfd_byte *bfd_coff_reloc16_get_relocated_section_contents
(bfd *, struct bfd_link_info *, struct bfd_link_order *,
bfd_byte *, bfd_boolean, asymbol **);
extern bfd_vma bfd_coff_reloc16_get_value
(arelent *, struct bfd_link_info *, asection *);
extern void bfd_perform_slip
(bfd *, unsigned int, asection *, bfd_vma);
/* Functions and types in cofflink.c. */
#define STRING_SIZE_SIZE 4
/* We use a hash table to merge identical enum, struct, and union
definitions in the linker. */
/* Information we keep for a single element (an enum value, a
structure or union field) in the debug merge hash table. */
struct coff_debug_merge_element
{
/* Next element. */
struct coff_debug_merge_element *next;
/* Name. */
const char *name;
/* Type. */
unsigned int type;
/* Symbol index for complex type. */
long tagndx;
};
/* A linked list of debug merge entries for a given name. */
struct coff_debug_merge_type
{
/* Next type with the same name. */
struct coff_debug_merge_type *next;
/* Class of type. */
int type_class;
/* Symbol index where this type is defined. */
long indx;
/* List of elements. */
struct coff_debug_merge_element *elements;
};
/* Information we store in the debug merge hash table. */
struct coff_debug_merge_hash_entry
{
struct bfd_hash_entry root;
/* A list of types with this name. */
struct coff_debug_merge_type *types;
};
/* The debug merge hash table. */
struct coff_debug_merge_hash_table
{
struct bfd_hash_table root;
};
/* Initialize a COFF debug merge hash table. */
#define coff_debug_merge_hash_table_init(table) \
(bfd_hash_table_init (&(table)->root, _bfd_coff_debug_merge_hash_newfunc, \
sizeof (struct coff_debug_merge_hash_entry)))
/* Free a COFF debug merge hash table. */
#define coff_debug_merge_hash_table_free(table) \
(bfd_hash_table_free (&(table)->root))
/* Look up an entry in a COFF debug merge hash table. */
#define coff_debug_merge_hash_lookup(table, string, create, copy) \
((struct coff_debug_merge_hash_entry *) \
bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
/* Information we keep for each section in the output file when doing
a relocatable link. */
struct coff_link_section_info
{
/* The relocs to be output. */
struct internal_reloc *relocs;
/* For each reloc against a global symbol whose index was not known
when the reloc was handled, the global hash table entry. */
struct coff_link_hash_entry **rel_hashes;
};
/* Information that we pass around while doing the final link step. */
struct coff_final_link_info
{
/* General link information. */
struct bfd_link_info *info;
/* Output BFD. */
bfd *output_bfd;
/* Used to indicate failure in traversal routine. */
bfd_boolean failed;
/* If doing "task linking" set only during the time when we want the
global symbol writer to convert the storage class of defined global
symbols from global to static. */
bfd_boolean global_to_static;
/* Hash table for long symbol names. */
struct bfd_strtab_hash *strtab;
/* When doing a relocatable link, an array of information kept for
each output section, indexed by the target_index field. */
struct coff_link_section_info *section_info;
/* Symbol index of last C_FILE symbol (-1 if none). */
long last_file_index;
/* Contents of last C_FILE symbol. */
struct internal_syment last_file;
/* Symbol index of first aux entry of last .bf symbol with an empty
endndx field (-1 if none). */
long last_bf_index;
/* Contents of last_bf_index aux entry. */
union internal_auxent last_bf;
/* Hash table used to merge debug information. */
struct coff_debug_merge_hash_table debug_merge;
/* Buffer large enough to hold swapped symbols of any input file. */
struct internal_syment *internal_syms;
/* Buffer large enough to hold sections of symbols of any input file. */
asection **sec_ptrs;
/* Buffer large enough to hold output indices of symbols of any
input file. */
long *sym_indices;
/* Buffer large enough to hold output symbols for any input file. */
bfd_byte *outsyms;
/* Buffer large enough to hold external line numbers for any input
section. */
bfd_byte *linenos;
/* Buffer large enough to hold any input section. */
bfd_byte *contents;
/* Buffer large enough to hold external relocs of any input section. */
bfd_byte *external_relocs;
/* Buffer large enough to hold swapped relocs of any input section. */
struct internal_reloc *internal_relocs;
};
/* Most COFF variants have no way to record the alignment of a
section. This struct is used to set a specific alignment based on
the name of the section. */
struct coff_section_alignment_entry
{
/* The section name. */
const char *name;
/* This is either (unsigned int) -1, indicating that the section
name must match exactly, or it is the number of letters which
must match at the start of the name. */
unsigned int comparison_length;
/* These macros may be used to fill in the first two fields in a
structure initialization. */
#define COFF_SECTION_NAME_EXACT_MATCH(name) (name), ((unsigned int) -1)
#define COFF_SECTION_NAME_PARTIAL_MATCH(name) (name), (sizeof (name) - 1)
/* Only use this entry if the default section alignment for this
target is at least that much (as a power of two). If this field
is COFF_ALIGNMENT_FIELD_EMPTY, it should be ignored. */
unsigned int default_alignment_min;
/* Only use this entry if the default section alignment for this
target is no greater than this (as a power of two). If this
field is COFF_ALIGNMENT_FIELD_EMPTY, it should be ignored. */
unsigned int default_alignment_max;
#define COFF_ALIGNMENT_FIELD_EMPTY ((unsigned int) -1)
/* The desired alignment for this section (as a power of two). */
unsigned int alignment_power;
};
extern struct bfd_hash_entry *_bfd_coff_link_hash_newfunc
(struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
extern bfd_boolean _bfd_coff_link_hash_table_init
(struct coff_link_hash_table *, bfd *,
struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
struct bfd_hash_table *,
const char *),
unsigned int);
extern struct bfd_link_hash_table *_bfd_coff_link_hash_table_create
(bfd *);
extern const char *_bfd_coff_internal_syment_name
(bfd *, const struct internal_syment *, char *);
extern bfd_boolean _bfd_coff_section_already_linked
(bfd *, asection *, struct bfd_link_info *);
extern bfd_boolean _bfd_coff_link_add_symbols
(bfd *, struct bfd_link_info *);
extern bfd_boolean _bfd_coff_final_link
(bfd *, struct bfd_link_info *);
extern struct internal_reloc *_bfd_coff_read_internal_relocs
(bfd *, asection *, bfd_boolean, bfd_byte *, bfd_boolean,
struct internal_reloc *);
extern bfd_boolean _bfd_coff_generic_relocate_section
(bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
struct internal_reloc *, struct internal_syment *, asection **);
extern struct bfd_hash_entry *_bfd_coff_debug_merge_hash_newfunc
(struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
extern bfd_boolean _bfd_coff_write_global_sym
(struct bfd_hash_entry *, void *);
extern bfd_boolean _bfd_coff_write_task_globals
(struct coff_link_hash_entry *, void *);
extern bfd_boolean _bfd_coff_link_input_bfd
(struct coff_final_link_info *, bfd *);
extern bfd_boolean _bfd_coff_reloc_link_order
(bfd *, struct coff_final_link_info *, asection *,
struct bfd_link_order *);
#define coff_get_section_contents_in_window \
_bfd_generic_get_section_contents_in_window
/* Functions in xcofflink.c. */
extern long _bfd_xcoff_get_dynamic_symtab_upper_bound
(bfd *);
extern long _bfd_xcoff_canonicalize_dynamic_symtab
(bfd *, asymbol **);
extern long _bfd_xcoff_get_dynamic_reloc_upper_bound
(bfd *);
extern long _bfd_xcoff_canonicalize_dynamic_reloc
(bfd *, arelent **, asymbol **);
extern struct bfd_link_hash_table *_bfd_xcoff_bfd_link_hash_table_create
(bfd *);
extern void _bfd_xcoff_bfd_link_hash_table_free
(struct bfd_link_hash_table *);
extern bfd_boolean _bfd_xcoff_bfd_link_add_symbols
(bfd *, struct bfd_link_info *);
extern bfd_boolean _bfd_xcoff_bfd_final_link
(bfd *, struct bfd_link_info *);
extern bfd_boolean _bfd_xcoff_define_common_symbol
(bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *);
extern bfd_boolean _bfd_ppc_xcoff_relocate_section
(bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
struct internal_reloc *, struct internal_syment *, asection **);
/* Functions in coff-ppc.c. FIXME: These are called by pe.em in the
linker, and so should start with bfd and be declared in bfd.h. */
extern bfd_boolean ppc_allocate_toc_section
(struct bfd_link_info *);
extern bfd_boolean ppc_process_before_allocation
(bfd *, struct bfd_link_info *);
/* Extracted from coffcode.h. */
typedef struct coff_ptr_struct
{
/* Remembers the offset from the first symbol in the file for
this symbol. Generated by coff_renumber_symbols. */
unsigned int offset;
/* Should the value of this symbol be renumbered. Used for
XCOFF C_BSTAT symbols. Set by coff_slurp_symbol_table. */
unsigned int fix_value : 1;
/* Should the tag field of this symbol be renumbered.
Created by coff_pointerize_aux. */
unsigned int fix_tag : 1;
/* Should the endidx field of this symbol be renumbered.
Created by coff_pointerize_aux. */
unsigned int fix_end : 1;
/* Should the x_csect.x_scnlen field be renumbered.
Created by coff_pointerize_aux. */
unsigned int fix_scnlen : 1;
/* Fix up an XCOFF C_BINCL/C_EINCL symbol. The value is the
index into the line number entries. Set by coff_slurp_symbol_table. */
unsigned int fix_line : 1;
/* The container for the symbol structure as read and translated
from the file. */
union
{
union internal_auxent auxent;
struct internal_syment syment;
} u;
} combined_entry_type;
/* Each canonical asymbol really looks like this: */
typedef struct coff_symbol_struct
{
/* The actual symbol which the rest of BFD works with */
asymbol symbol;
/* A pointer to the hidden information for this symbol */
combined_entry_type *native;
/* A pointer to the linenumber information for this symbol */
struct lineno_cache_entry *lineno;
/* Have the line numbers been relocated yet ? */
bfd_boolean done_lineno;
} coff_symbol_type;
/* COFF symbol classifications. */
enum coff_symbol_classification
{
/* Global symbol. */
COFF_SYMBOL_GLOBAL,
/* Common symbol. */
COFF_SYMBOL_COMMON,
/* Undefined symbol. */
COFF_SYMBOL_UNDEFINED,
/* Local symbol. */
COFF_SYMBOL_LOCAL,
/* PE section symbol. */
COFF_SYMBOL_PE_SECTION
};
typedef struct
{
void (*_bfd_coff_swap_aux_in)
(bfd *, void *, int, int, int, int, void *);
void (*_bfd_coff_swap_sym_in)
(bfd *, void *, void *);
void (*_bfd_coff_swap_lineno_in)
(bfd *, void *, void *);
unsigned int (*_bfd_coff_swap_aux_out)
(bfd *, void *, int, int, int, int, void *);
unsigned int (*_bfd_coff_swap_sym_out)
(bfd *, void *, void *);
unsigned int (*_bfd_coff_swap_lineno_out)
(bfd *, void *, void *);
unsigned int (*_bfd_coff_swap_reloc_out)
(bfd *, void *, void *);
unsigned int (*_bfd_coff_swap_filehdr_out)
(bfd *, void *, void *);
unsigned int (*_bfd_coff_swap_aouthdr_out)
(bfd *, void *, void *);
unsigned int (*_bfd_coff_swap_scnhdr_out)
(bfd *, void *, void *);
unsigned int _bfd_filhsz;
unsigned int _bfd_aoutsz;
unsigned int _bfd_scnhsz;
unsigned int _bfd_symesz;
unsigned int _bfd_auxesz;
unsigned int _bfd_relsz;
unsigned int _bfd_linesz;
unsigned int _bfd_filnmlen;
bfd_boolean _bfd_coff_long_filenames;
bfd_boolean _bfd_coff_long_section_names;
bfd_boolean (*_bfd_coff_set_long_section_names)
(bfd *, int);
unsigned int _bfd_coff_default_section_alignment_power;
bfd_boolean _bfd_coff_force_symnames_in_strings;
unsigned int _bfd_coff_debug_string_prefix_length;
void (*_bfd_coff_swap_filehdr_in)
(bfd *, void *, void *);
void (*_bfd_coff_swap_aouthdr_in)
(bfd *, void *, void *);
void (*_bfd_coff_swap_scnhdr_in)
(bfd *, void *, void *);
void (*_bfd_coff_swap_reloc_in)
(bfd *abfd, void *, void *);
bfd_boolean (*_bfd_coff_bad_format_hook)
(bfd *, void *);
bfd_boolean (*_bfd_coff_set_arch_mach_hook)
(bfd *, void *);
void * (*_bfd_coff_mkobject_hook)
(bfd *, void *, void *);
bfd_boolean (*_bfd_styp_to_sec_flags_hook)
(bfd *, void *, const char *, asection *, flagword *);
void (*_bfd_set_alignment_hook)
(bfd *, asection *, void *);
bfd_boolean (*_bfd_coff_slurp_symbol_table)
(bfd *);
bfd_boolean (*_bfd_coff_symname_in_debug)
(bfd *, struct internal_syment *);
bfd_boolean (*_bfd_coff_pointerize_aux_hook)
(bfd *, combined_entry_type *, combined_entry_type *,
unsigned int, combined_entry_type *);
bfd_boolean (*_bfd_coff_print_aux)
(bfd *, FILE *, combined_entry_type *, combined_entry_type *,
combined_entry_type *, unsigned int);
void (*_bfd_coff_reloc16_extra_cases)
(bfd *, struct bfd_link_info *, struct bfd_link_order *, arelent *,
bfd_byte *, unsigned int *, unsigned int *);
int (*_bfd_coff_reloc16_estimate)
(bfd *, asection *, arelent *, unsigned int,
struct bfd_link_info *);
enum coff_symbol_classification (*_bfd_coff_classify_symbol)
(bfd *, struct internal_syment *);
bfd_boolean (*_bfd_coff_compute_section_file_positions)
(bfd *);
bfd_boolean (*_bfd_coff_start_final_link)
(bfd *, struct bfd_link_info *);
bfd_boolean (*_bfd_coff_relocate_section)
(bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
struct internal_reloc *, struct internal_syment *, asection **);
reloc_howto_type *(*_bfd_coff_rtype_to_howto)
(bfd *, asection *, struct internal_reloc *,
struct coff_link_hash_entry *, struct internal_syment *,
bfd_vma *);
bfd_boolean (*_bfd_coff_adjust_symndx)
(bfd *, struct bfd_link_info *, bfd *, asection *,
struct internal_reloc *, bfd_boolean *);
bfd_boolean (*_bfd_coff_link_add_one_symbol)
(struct bfd_link_info *, bfd *, const char *, flagword,
asection *, bfd_vma, const char *, bfd_boolean, bfd_boolean,
struct bfd_link_hash_entry **);
bfd_boolean (*_bfd_coff_link_output_has_begun)
(bfd *, struct coff_final_link_info *);
bfd_boolean (*_bfd_coff_final_link_postscript)
(bfd *, struct coff_final_link_info *);
bfd_boolean (*_bfd_coff_print_pdata)
(bfd *, void *);
} bfd_coff_backend_data;
#define coff_backend_info(abfd) \
((bfd_coff_backend_data *) (abfd)->xvec->backend_data)
#define bfd_coff_swap_aux_in(a,e,t,c,ind,num,i) \
((coff_backend_info (a)->_bfd_coff_swap_aux_in) (a,e,t,c,ind,num,i))
#define bfd_coff_swap_sym_in(a,e,i) \
((coff_backend_info (a)->_bfd_coff_swap_sym_in) (a,e,i))
#define bfd_coff_swap_lineno_in(a,e,i) \
((coff_backend_info ( a)->_bfd_coff_swap_lineno_in) (a,e,i))
#define bfd_coff_swap_reloc_out(abfd, i, o) \
((coff_backend_info (abfd)->_bfd_coff_swap_reloc_out) (abfd, i, o))
#define bfd_coff_swap_lineno_out(abfd, i, o) \
((coff_backend_info (abfd)->_bfd_coff_swap_lineno_out) (abfd, i, o))
#define bfd_coff_swap_aux_out(a,i,t,c,ind,num,o) \
((coff_backend_info (a)->_bfd_coff_swap_aux_out) (a,i,t,c,ind,num,o))
#define bfd_coff_swap_sym_out(abfd, i,o) \
((coff_backend_info (abfd)->_bfd_coff_swap_sym_out) (abfd, i, o))
#define bfd_coff_swap_scnhdr_out(abfd, i,o) \
((coff_backend_info (abfd)->_bfd_coff_swap_scnhdr_out) (abfd, i, o))
#define bfd_coff_swap_filehdr_out(abfd, i,o) \
((coff_backend_info (abfd)->_bfd_coff_swap_filehdr_out) (abfd, i, o))
#define bfd_coff_swap_aouthdr_out(abfd, i,o) \
((coff_backend_info (abfd)->_bfd_coff_swap_aouthdr_out) (abfd, i, o))
#define bfd_coff_filhsz(abfd) (coff_backend_info (abfd)->_bfd_filhsz)
#define bfd_coff_aoutsz(abfd) (coff_backend_info (abfd)->_bfd_aoutsz)
#define bfd_coff_scnhsz(abfd) (coff_backend_info (abfd)->_bfd_scnhsz)
#define bfd_coff_symesz(abfd) (coff_backend_info (abfd)->_bfd_symesz)
#define bfd_coff_auxesz(abfd) (coff_backend_info (abfd)->_bfd_auxesz)
#define bfd_coff_relsz(abfd) (coff_backend_info (abfd)->_bfd_relsz)
#define bfd_coff_linesz(abfd) (coff_backend_info (abfd)->_bfd_linesz)
#define bfd_coff_filnmlen(abfd) (coff_backend_info (abfd)->_bfd_filnmlen)
#define bfd_coff_long_filenames(abfd) \
(coff_backend_info (abfd)->_bfd_coff_long_filenames)
#define bfd_coff_long_section_names(abfd) \
(coff_backend_info (abfd)->_bfd_coff_long_section_names)
#define bfd_coff_set_long_section_names(abfd, enable) \
((coff_backend_info (abfd)->_bfd_coff_set_long_section_names) (abfd, enable))
#define bfd_coff_default_section_alignment_power(abfd) \
(coff_backend_info (abfd)->_bfd_coff_default_section_alignment_power)
#define bfd_coff_swap_filehdr_in(abfd, i,o) \
((coff_backend_info (abfd)->_bfd_coff_swap_filehdr_in) (abfd, i, o))
#define bfd_coff_swap_aouthdr_in(abfd, i,o) \
((coff_backend_info (abfd)->_bfd_coff_swap_aouthdr_in) (abfd, i, o))
#define bfd_coff_swap_scnhdr_in(abfd, i,o) \
((coff_backend_info (abfd)->_bfd_coff_swap_scnhdr_in) (abfd, i, o))
#define bfd_coff_swap_reloc_in(abfd, i, o) \
((coff_backend_info (abfd)->_bfd_coff_swap_reloc_in) (abfd, i, o))
#define bfd_coff_bad_format_hook(abfd, filehdr) \
((coff_backend_info (abfd)->_bfd_coff_bad_format_hook) (abfd, filehdr))
#define bfd_coff_set_arch_mach_hook(abfd, filehdr)\
((coff_backend_info (abfd)->_bfd_coff_set_arch_mach_hook) (abfd, filehdr))
#define bfd_coff_mkobject_hook(abfd, filehdr, aouthdr)\
((coff_backend_info (abfd)->_bfd_coff_mkobject_hook)\
(abfd, filehdr, aouthdr))
#define bfd_coff_styp_to_sec_flags_hook(abfd, scnhdr, name, section, flags_ptr)\
((coff_backend_info (abfd)->_bfd_styp_to_sec_flags_hook)\
(abfd, scnhdr, name, section, flags_ptr))
#define bfd_coff_set_alignment_hook(abfd, sec, scnhdr)\
((coff_backend_info (abfd)->_bfd_set_alignment_hook) (abfd, sec, scnhdr))
#define bfd_coff_slurp_symbol_table(abfd)\
((coff_backend_info (abfd)->_bfd_coff_slurp_symbol_table) (abfd))
#define bfd_coff_symname_in_debug(abfd, sym)\
((coff_backend_info (abfd)->_bfd_coff_symname_in_debug) (abfd, sym))
#define bfd_coff_force_symnames_in_strings(abfd)\
(coff_backend_info (abfd)->_bfd_coff_force_symnames_in_strings)
#define bfd_coff_debug_string_prefix_length(abfd)\
(coff_backend_info (abfd)->_bfd_coff_debug_string_prefix_length)
#define bfd_coff_print_aux(abfd, file, base, symbol, aux, indaux)\
((coff_backend_info (abfd)->_bfd_coff_print_aux)\
(abfd, file, base, symbol, aux, indaux))
#define bfd_coff_reloc16_extra_cases(abfd, link_info, link_order,\
reloc, data, src_ptr, dst_ptr)\
((coff_backend_info (abfd)->_bfd_coff_reloc16_extra_cases)\
(abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr))
#define bfd_coff_reloc16_estimate(abfd, section, reloc, shrink, link_info)\
((coff_backend_info (abfd)->_bfd_coff_reloc16_estimate)\
(abfd, section, reloc, shrink, link_info))
#define bfd_coff_classify_symbol(abfd, sym)\
((coff_backend_info (abfd)->_bfd_coff_classify_symbol)\
(abfd, sym))
#define bfd_coff_compute_section_file_positions(abfd)\
((coff_backend_info (abfd)->_bfd_coff_compute_section_file_positions)\
(abfd))
#define bfd_coff_start_final_link(obfd, info)\
((coff_backend_info (obfd)->_bfd_coff_start_final_link)\
(obfd, info))
#define bfd_coff_relocate_section(obfd,info,ibfd,o,con,rel,isyms,secs)\
((coff_backend_info (ibfd)->_bfd_coff_relocate_section)\
(obfd, info, ibfd, o, con, rel, isyms, secs))
#define bfd_coff_rtype_to_howto(abfd, sec, rel, h, sym, addendp)\
((coff_backend_info (abfd)->_bfd_coff_rtype_to_howto)\
(abfd, sec, rel, h, sym, addendp))
#define bfd_coff_adjust_symndx(obfd, info, ibfd, sec, rel, adjustedp)\
((coff_backend_info (abfd)->_bfd_coff_adjust_symndx)\
(obfd, info, ibfd, sec, rel, adjustedp))
#define bfd_coff_link_add_one_symbol(info, abfd, name, flags, section,\
value, string, cp, coll, hashp)\
((coff_backend_info (abfd)->_bfd_coff_link_add_one_symbol)\
(info, abfd, name, flags, section, value, string, cp, coll, hashp))
#define bfd_coff_link_output_has_begun(a,p) \
((coff_backend_info (a)->_bfd_coff_link_output_has_begun) (a, p))
#define bfd_coff_final_link_postscript(a,p) \
((coff_backend_info (a)->_bfd_coff_final_link_postscript) (a, p))
#define bfd_coff_have_print_pdata(a) \
(coff_backend_info (a)->_bfd_coff_print_pdata)
#define bfd_coff_print_pdata(a,p) \
((coff_backend_info (a)->_bfd_coff_print_pdata) (a, p))
/* Macro: Returns true if the bfd is a PE executable as opposed to a
PE object file. */
#define bfd_pei_p(abfd) \
(CONST_STRNEQ ((abfd)->xvec->name, "pei-"))

View File

@@ -0,0 +1,348 @@
/* BFD ECOFF object file private structure.
Copyright 1993, 1994, 1995, 1996, 1999, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
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 "bfdlink.h"
#ifndef ECOFF_H
#include "coff/ecoff.h"
#endif
/* This is the backend information kept for ECOFF files. This
structure is constant for a particular backend. The first element
is the COFF backend data structure, so that ECOFF targets can use
the generic COFF code. */
#define ecoff_backend(abfd) \
((struct ecoff_backend_data *) (abfd)->xvec->backend_data)
struct ecoff_backend_data
{
/* COFF backend information. This must be the first field. */
bfd_coff_backend_data coff;
/* Supported architecture. */
enum bfd_architecture arch;
/* Initial portion of armap string. */
const char *armap_start;
/* The page boundary used to align sections in a demand-paged
executable file. E.g., 0x1000. */
bfd_vma round;
/* TRUE if the .rdata section is part of the text segment, as on the
Alpha. FALSE if .rdata is part of the data segment, as on the
MIPS. */
bfd_boolean rdata_in_text;
/* Bitsize of constructor entries. */
unsigned int constructor_bitsize;
/* Reloc to use for constructor entries. */
reloc_howto_type *constructor_reloc;
/* How to swap debugging information. */
struct ecoff_debug_swap debug_swap;
/* External reloc size. */
bfd_size_type external_reloc_size;
/* Reloc swapping functions. */
void (*swap_reloc_in) (bfd *, void *, struct internal_reloc *);
void (*swap_reloc_out) (bfd *, const struct internal_reloc *, void *);
/* Backend reloc tweaking. */
void (*adjust_reloc_in)
(bfd *, const struct internal_reloc *, arelent *);
void (*adjust_reloc_out)
(bfd *, const arelent *, struct internal_reloc *);
/* Relocate section contents while linking. */
bfd_boolean (*relocate_section)
(bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, void *);
/* Do final adjustments to filehdr and aouthdr. */
bfd_boolean (*adjust_headers)
(bfd *, struct internal_filehdr *, struct internal_aouthdr *);
/* Read an element from an archive at a given file position. This
is needed because OSF/1 3.2 uses a weird archive format. */
bfd *(*get_elt_at_filepos) (bfd *, file_ptr);
};
/* ECOFF targets don't support COFF long section names, so this
macro is provided to use as an initialiser for the related
members of the embedded bfd_coff_backend_data struct. */
#define ECOFF_NO_LONG_SECTION_NAMES (FALSE), _bfd_ecoff_no_long_sections
/* This is the target specific information kept for ECOFF files. */
#define ecoff_data(abfd) ((abfd)->tdata.ecoff_obj_data)
typedef struct ecoff_tdata
{
/* The reloc file position, set by
ecoff_compute_section_file_positions. */
file_ptr reloc_filepos;
/* The symbol table file position, set by _bfd_ecoff_mkobject_hook. */
file_ptr sym_filepos;
/* The start and end of the text segment. Only valid for an
existing file, not for one we are creating. */
unsigned long text_start;
unsigned long text_end;
/* The cached gp value. This is used when relocating. */
bfd_vma gp;
/* The maximum size of objects to optimize using gp. This is
typically set by the -G option to the compiler, assembler or
linker. */
unsigned int gp_size;
/* The register masks. When linking, all the masks found in the
input files are combined into the masks of the output file.
These are not all used for all targets, but that's OK, because
the relevant ones are the only ones swapped in and out. */
unsigned long gprmask;
unsigned long fprmask;
unsigned long cprmask[4];
/* The ECOFF symbolic debugging information. */
struct ecoff_debug_info debug_info;
/* The unswapped ECOFF symbolic information. */
void * raw_syments;
/* The canonical BFD symbols. */
struct ecoff_symbol_struct *canonical_symbols;
/* A mapping from external symbol numbers to entries in the linker
hash table, used when linking. */
struct ecoff_link_hash_entry **sym_hashes;
/* A mapping from reloc symbol indices to sections, used when
linking. */
asection **symndx_to_section;
/* TRUE if this BFD was written by the backend linker. */
bfd_boolean linker;
/* TRUE if a warning that multiple global pointer values are
needed in the output binary was issued already. */
bfd_boolean issued_multiple_gp_warning;
/* Used by find_nearest_line entry point. The structure could be
included directly in this one, but there's no point to wasting
the memory just for the infrequently called find_nearest_line. */
struct ecoff_find_line *find_line_info;
/* Whether the .rdata section is in the text segment for this
particular ECOFF file. This is not valid until
ecoff_compute_section_file_positions is called. */
bfd_boolean rdata_in_text;
} ecoff_data_type;
/* Each canonical asymbol really looks like this. */
typedef struct ecoff_symbol_struct
{
/* The actual symbol which the rest of BFD works with */
asymbol symbol;
/* The fdr for this symbol. */
FDR *fdr;
/* TRUE if this is a local symbol rather than an external one. */
bfd_boolean local;
/* A pointer to the unswapped hidden information for this symbol.
This is either a struct sym_ext or a struct ext_ext, depending on
the value of the local field above. */
void * native;
} ecoff_symbol_type;
/* We take the address of the first element of an asymbol to ensure that the
macro is only ever applied to an asymbol. */
#define ecoffsymbol(asymbol) ((ecoff_symbol_type *) (&((asymbol)->the_bfd)))
/* We need to save the index of an external symbol when we write it
out so that can set the symbol index correctly when we write out
the relocs. */
#define ecoff_get_sym_index(symbol) ((symbol)->udata.i)
#define ecoff_set_sym_index(symbol, idx) ((symbol)->udata.i = (idx))
/* A pointer to this structure is put in the used_by_bfd pointer of
a section to keep track of any per-section data.
The user_by_bfd pointer will be NULL if the information was not
needed. */
struct ecoff_section_tdata
{
/* When producing an executable (i.e., final, non-relocatable link)
on the Alpha, we may need to use multiple global pointer values
to span the entire .lita section. In essence, we allow each
input .lita section to have its own gp value. To support this,
we need to keep track of the gp values that we picked for each
input .lita section . */
bfd_vma gp;
};
/* An accessor macro for the ecoff_section_tdata structure. */
#define ecoff_section_data(abfd, sec) \
((struct ecoff_section_tdata *) (sec)->used_by_bfd)
/* ECOFF linker hash table entries. */
struct ecoff_link_hash_entry
{
struct bfd_link_hash_entry root;
/* Symbol index in output file. */
long indx;
/* BFD that ext field value came from. */
bfd *abfd;
/* ECOFF external symbol information. */
EXTR esym;
/* Nonzero if this symbol has been written out. */
char written;
/* Nonzero if this symbol was referred to as small undefined. */
char small;
};
/* ECOFF linker hash table. */
struct ecoff_link_hash_table
{
struct bfd_link_hash_table root;
};
/* Make an ECOFF object. */
extern bfd_boolean _bfd_ecoff_mkobject (bfd *);
/* Read in the ECOFF symbolic debugging information. */
extern bfd_boolean _bfd_ecoff_slurp_symbolic_info
(bfd *, asection *, struct ecoff_debug_info *);
/* Generic ECOFF BFD backend vectors. */
extern bfd_boolean _bfd_ecoff_write_object_contents (bfd *);
#define _bfd_ecoff_close_and_cleanup _bfd_generic_close_and_cleanup
#define _bfd_ecoff_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
extern bfd_boolean _bfd_ecoff_new_section_hook
(bfd *, asection *);
extern bfd_boolean _bfd_ecoff_get_section_contents
(bfd *, asection *, void * location, file_ptr, bfd_size_type);
#define _bfd_ecoff_bfd_link_split_section _bfd_generic_link_split_section
extern bfd_boolean _bfd_ecoff_bfd_copy_private_bfd_data
(bfd *, bfd *);
#define _bfd_ecoff_bfd_copy_private_section_data \
_bfd_generic_bfd_copy_private_section_data
#define _bfd_ecoff_bfd_copy_private_symbol_data \
_bfd_generic_bfd_copy_private_symbol_data
#define _bfd_ecoff_bfd_copy_private_header_data \
_bfd_generic_bfd_copy_private_header_data
#define _bfd_ecoff_bfd_print_private_bfd_data \
_bfd_generic_bfd_print_private_bfd_data
#define _bfd_ecoff_bfd_merge_private_bfd_data \
_bfd_generic_bfd_merge_private_bfd_data
#define _bfd_ecoff_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
extern bfd_boolean _bfd_ecoff_slurp_armap (bfd *);
#define _bfd_ecoff_slurp_extended_name_table _bfd_slurp_extended_name_table
#define _bfd_ecoff_construct_extended_name_table \
_bfd_archive_bsd_construct_extended_name_table
#define _bfd_ecoff_truncate_arname bfd_dont_truncate_arname
extern bfd_boolean _bfd_ecoff_write_armap
(bfd *, unsigned int, struct orl *, unsigned int, int);
#define _bfd_ecoff_read_ar_hdr _bfd_generic_read_ar_hdr
#define _bfd_ecoff_write_ar_hdr _bfd_generic_write_ar_hdr
#define _bfd_ecoff_openr_next_archived_file \
bfd_generic_openr_next_archived_file
#define _bfd_ecoff_get_elt_at_index _bfd_generic_get_elt_at_index
#define _bfd_ecoff_generic_stat_arch_elt bfd_generic_stat_arch_elt
#define _bfd_ecoff_update_armap_timestamp bfd_true
#define _bfd_ecoff_bfd_is_target_special_symbol \
((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
extern long _bfd_ecoff_get_symtab_upper_bound (bfd *);
extern long _bfd_ecoff_canonicalize_symtab (bfd *, asymbol **);
extern asymbol *_bfd_ecoff_make_empty_symbol (bfd *);
extern void _bfd_ecoff_print_symbol
(bfd *, void *, asymbol *, bfd_print_symbol_type);
extern void _bfd_ecoff_get_symbol_info
(bfd *, asymbol *, symbol_info *);
extern bfd_boolean _bfd_ecoff_bfd_is_local_label_name
(bfd *, const char *);
#define _bfd_ecoff_get_lineno _bfd_nosymbols_get_lineno
extern bfd_boolean _bfd_ecoff_find_nearest_line
(bfd *, asection *, asymbol **, bfd_vma, const char **, const char **,
unsigned int *);
#define _bfd_ecoff_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
#define _bfd_ecoff_read_minisymbols _bfd_generic_read_minisymbols
#define _bfd_ecoff_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
#define _bfd_ecoff_find_inliner_info _bfd_nosymbols_find_inliner_info
#define _bfd_ecoff_get_reloc_upper_bound coff_get_reloc_upper_bound
extern long _bfd_ecoff_canonicalize_reloc
(bfd *, asection *, arelent **, asymbol **symbols);
/* ecoff_bfd_reloc_type_lookup defined by backend. */
extern bfd_boolean _bfd_ecoff_set_arch_mach
(bfd *, enum bfd_architecture, unsigned long);
extern bfd_boolean _bfd_ecoff_set_section_contents
(bfd *, asection *, const void * location, file_ptr, bfd_size_type);
extern int _bfd_ecoff_sizeof_headers (bfd *, struct bfd_link_info *);
/* ecoff_bfd_get_relocated_section_contents defined by backend. */
/* ecoff_bfd_relax_section defined by backend. */
extern struct bfd_link_hash_table *_bfd_ecoff_bfd_link_hash_table_create
(bfd *);
#define _bfd_ecoff_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
extern bfd_boolean _bfd_ecoff_bfd_link_add_symbols
(bfd *, struct bfd_link_info *);
#define _bfd_ecoff_bfd_link_just_syms _bfd_generic_link_just_syms
#define _bfd_ecoff_bfd_copy_link_hash_symbol_type \
_bfd_generic_copy_link_hash_symbol_type
extern bfd_boolean _bfd_ecoff_bfd_final_link
(bfd *, struct bfd_link_info *);
/* Hook functions for the generic COFF section reading code. */
extern void * _bfd_ecoff_mkobject_hook (bfd *, void *, void *);
#define _bfd_ecoff_set_alignment_hook \
((void (*) (bfd *, asection *, void *)) bfd_void)
extern bfd_boolean _bfd_ecoff_set_arch_mach_hook
(bfd *, void *);
extern bfd_boolean _bfd_ecoff_no_long_sections
(bfd *abfd, int enable);
extern bfd_boolean _bfd_ecoff_styp_to_sec_flags
(bfd *, void *, const char *, asection *, flagword *);
extern bfd_boolean _bfd_ecoff_slurp_symbol_table (bfd *);
/* ECOFF auxiliary information swapping routines. These are the same
for all ECOFF targets, so they are defined in ecofflink.c. */
extern void _bfd_ecoff_swap_tir_in
(int, const struct tir_ext *, TIR *);
extern void _bfd_ecoff_swap_tir_out
(int, const TIR *, struct tir_ext *);
extern void _bfd_ecoff_swap_rndx_in
(int, const struct rndx_ext *, RNDXR *);
extern void _bfd_ecoff_swap_rndx_out
(int, const RNDXR *, struct rndx_ext *);

View File

@@ -0,0 +1,356 @@
/* Support for the generic parts of PE/PEI; common header information.
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005,
2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Written by Cygnus Solutions.
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. */
/* Most of this hacked by Steve Chamberlain,
sac@cygnus.com
PE/PEI rearrangement (and code added): Donn Terry
Softway Systems, Inc. */
/* Hey look, some documentation [and in a place you expect to find it]!
The main reference for the pei format is "Microsoft Portable Executable
and Common Object File Format Specification 4.1". Get it if you need to
do some serious hacking on this code.
Another reference:
"Peering Inside the PE: A Tour of the Win32 Portable Executable
File Format", MSJ 1994, Volume 9.
The *sole* difference between the pe format and the pei format is that the
latter has an MSDOS 2.0 .exe header on the front that prints the message
"This app must be run under Windows." (or some such).
(FIXME: Whether that statement is *really* true or not is unknown.
Are there more subtle differences between pe and pei formats?
For now assume there aren't. If you find one, then for God sakes
document it here!)
The Microsoft docs use the word "image" instead of "executable" because
the former can also refer to a DLL (shared library). Confusion can arise
because the `i' in `pei' also refers to "image". The `pe' format can
also create images (i.e. executables), it's just that to run on a win32
system you need to use the pei format.
FIXME: Please add more docs here so the next poor fool that has to hack
on this code has a chance of getting something accomplished without
wasting too much time. */
#ifndef GET_FCN_LNNOPTR
#define GET_FCN_LNNOPTR(abfd, ext) \
H_GET_32 (abfd, ext->x_sym.x_fcnary.x_fcn.x_lnnoptr)
#endif
#ifndef GET_FCN_ENDNDX
#define GET_FCN_ENDNDX(abfd, ext) \
H_GET_32 (abfd, ext->x_sym.x_fcnary.x_fcn.x_endndx)
#endif
#ifndef PUT_FCN_LNNOPTR
#define PUT_FCN_LNNOPTR(abfd, in, ext) \
H_PUT_32(abfd, in, ext->x_sym.x_fcnary.x_fcn.x_lnnoptr)
#endif
#ifndef PUT_FCN_ENDNDX
#define PUT_FCN_ENDNDX(abfd, in, ext) \
H_PUT_32(abfd, in, ext->x_sym.x_fcnary.x_fcn.x_endndx)
#endif
#ifndef GET_LNSZ_LNNO
#define GET_LNSZ_LNNO(abfd, ext) \
H_GET_16 (abfd, ext->x_sym.x_misc.x_lnsz.x_lnno)
#endif
#ifndef GET_LNSZ_SIZE
#define GET_LNSZ_SIZE(abfd, ext) \
H_GET_16 (abfd, ext->x_sym.x_misc.x_lnsz.x_size)
#endif
#ifndef PUT_LNSZ_LNNO
#define PUT_LNSZ_LNNO(abfd, in, ext) \
H_PUT_16(abfd, in, ext->x_sym.x_misc.x_lnsz.x_lnno)
#endif
#ifndef PUT_LNSZ_SIZE
#define PUT_LNSZ_SIZE(abfd, in, ext) \
H_PUT_16(abfd, in, ext->x_sym.x_misc.x_lnsz.x_size)
#endif
#ifndef GET_SCN_SCNLEN
#define GET_SCN_SCNLEN(abfd, ext) \
H_GET_32 (abfd, ext->x_scn.x_scnlen)
#endif
#ifndef GET_SCN_NRELOC
#define GET_SCN_NRELOC(abfd, ext) \
H_GET_16 (abfd, ext->x_scn.x_nreloc)
#endif
#ifndef GET_SCN_NLINNO
#define GET_SCN_NLINNO(abfd, ext) \
H_GET_16 (abfd, ext->x_scn.x_nlinno)
#endif
#ifndef PUT_SCN_SCNLEN
#define PUT_SCN_SCNLEN(abfd, in, ext) \
H_PUT_32(abfd, in, ext->x_scn.x_scnlen)
#endif
#ifndef PUT_SCN_NRELOC
#define PUT_SCN_NRELOC(abfd, in, ext) \
H_PUT_16(abfd, in, ext->x_scn.x_nreloc)
#endif
#ifndef PUT_SCN_NLINNO
#define PUT_SCN_NLINNO(abfd, in, ext) \
H_PUT_16(abfd,in, ext->x_scn.x_nlinno)
#endif
#ifndef GET_LINENO_LNNO
#define GET_LINENO_LNNO(abfd, ext) \
H_GET_16 (abfd, ext->l_lnno);
#endif
#ifndef PUT_LINENO_LNNO
#define PUT_LINENO_LNNO(abfd, val, ext) \
H_PUT_16(abfd,val, ext->l_lnno);
#endif
/* The f_symptr field in the filehdr is sometimes 64 bits. */
#ifndef GET_FILEHDR_SYMPTR
#define GET_FILEHDR_SYMPTR H_GET_32
#endif
#ifndef PUT_FILEHDR_SYMPTR
#define PUT_FILEHDR_SYMPTR H_PUT_32
#endif
/* Some fields in the aouthdr are sometimes 64 bits. */
#ifndef GET_AOUTHDR_TSIZE
#define GET_AOUTHDR_TSIZE H_GET_32
#endif
#ifndef PUT_AOUTHDR_TSIZE
#define PUT_AOUTHDR_TSIZE H_PUT_32
#endif
#ifndef GET_AOUTHDR_DSIZE
#define GET_AOUTHDR_DSIZE H_GET_32
#endif
#ifndef PUT_AOUTHDR_DSIZE
#define PUT_AOUTHDR_DSIZE H_PUT_32
#endif
#ifndef GET_AOUTHDR_BSIZE
#define GET_AOUTHDR_BSIZE H_GET_32
#endif
#ifndef PUT_AOUTHDR_BSIZE
#define PUT_AOUTHDR_BSIZE H_PUT_32
#endif
#ifndef GET_AOUTHDR_ENTRY
#define GET_AOUTHDR_ENTRY H_GET_32
#endif
#ifndef PUT_AOUTHDR_ENTRY
#define PUT_AOUTHDR_ENTRY H_PUT_32
#endif
#ifndef GET_AOUTHDR_TEXT_START
#define GET_AOUTHDR_TEXT_START H_GET_32
#endif
#ifndef PUT_AOUTHDR_TEXT_START
#define PUT_AOUTHDR_TEXT_START H_PUT_32
#endif
#ifndef GET_AOUTHDR_DATA_START
#define GET_AOUTHDR_DATA_START H_GET_32
#endif
#ifndef PUT_AOUTHDR_DATA_START
#define PUT_AOUTHDR_DATA_START H_PUT_32
#endif
/* Some fields in the scnhdr are sometimes 64 bits. */
#ifndef GET_SCNHDR_PADDR
#define GET_SCNHDR_PADDR H_GET_32
#endif
#ifndef PUT_SCNHDR_PADDR
#define PUT_SCNHDR_PADDR H_PUT_32
#endif
#ifndef GET_SCNHDR_VADDR
#define GET_SCNHDR_VADDR H_GET_32
#endif
#ifndef PUT_SCNHDR_VADDR
#define PUT_SCNHDR_VADDR H_PUT_32
#endif
#ifndef GET_SCNHDR_SIZE
#define GET_SCNHDR_SIZE H_GET_32
#endif
#ifndef PUT_SCNHDR_SIZE
#define PUT_SCNHDR_SIZE H_PUT_32
#endif
#ifndef GET_SCNHDR_SCNPTR
#define GET_SCNHDR_SCNPTR H_GET_32
#endif
#ifndef PUT_SCNHDR_SCNPTR
#define PUT_SCNHDR_SCNPTR H_PUT_32
#endif
#ifndef GET_SCNHDR_RELPTR
#define GET_SCNHDR_RELPTR H_GET_32
#endif
#ifndef PUT_SCNHDR_RELPTR
#define PUT_SCNHDR_RELPTR H_PUT_32
#endif
#ifndef GET_SCNHDR_LNNOPTR
#define GET_SCNHDR_LNNOPTR H_GET_32
#endif
#ifndef PUT_SCNHDR_LNNOPTR
#define PUT_SCNHDR_LNNOPTR H_PUT_32
#endif
#ifdef COFF_WITH_pex64
#define GET_OPTHDR_IMAGE_BASE H_GET_64
#define PUT_OPTHDR_IMAGE_BASE H_PUT_64
#define GET_OPTHDR_SIZE_OF_STACK_RESERVE H_GET_64
#define PUT_OPTHDR_SIZE_OF_STACK_RESERVE H_PUT_64
#define GET_OPTHDR_SIZE_OF_STACK_COMMIT H_GET_64
#define PUT_OPTHDR_SIZE_OF_STACK_COMMIT H_PUT_64
#define GET_OPTHDR_SIZE_OF_HEAP_RESERVE H_GET_64
#define PUT_OPTHDR_SIZE_OF_HEAP_RESERVE H_PUT_64
#define GET_OPTHDR_SIZE_OF_HEAP_COMMIT H_GET_64
#define PUT_OPTHDR_SIZE_OF_HEAP_COMMIT H_PUT_64
#define GET_PDATA_ENTRY bfd_get_32
#define _bfd_XX_bfd_copy_private_bfd_data_common _bfd_pex64_bfd_copy_private_bfd_data_common
#define _bfd_XX_bfd_copy_private_section_data _bfd_pex64_bfd_copy_private_section_data
#define _bfd_XX_get_symbol_info _bfd_pex64_get_symbol_info
#define _bfd_XX_only_swap_filehdr_out _bfd_pex64_only_swap_filehdr_out
#define _bfd_XX_print_private_bfd_data_common _bfd_pex64_print_private_bfd_data_common
#define _bfd_XXi_final_link_postscript _bfd_pex64i_final_link_postscript
#define _bfd_XXi_only_swap_filehdr_out _bfd_pex64i_only_swap_filehdr_out
#define _bfd_XXi_swap_aouthdr_in _bfd_pex64i_swap_aouthdr_in
#define _bfd_XXi_swap_aouthdr_out _bfd_pex64i_swap_aouthdr_out
#define _bfd_XXi_swap_aux_in _bfd_pex64i_swap_aux_in
#define _bfd_XXi_swap_aux_out _bfd_pex64i_swap_aux_out
#define _bfd_XXi_swap_lineno_in _bfd_pex64i_swap_lineno_in
#define _bfd_XXi_swap_lineno_out _bfd_pex64i_swap_lineno_out
#define _bfd_XXi_swap_scnhdr_out _bfd_pex64i_swap_scnhdr_out
#define _bfd_XXi_swap_sym_in _bfd_pex64i_swap_sym_in
#define _bfd_XXi_swap_sym_out _bfd_pex64i_swap_sym_out
#elif defined COFF_WITH_pep
#define GET_OPTHDR_IMAGE_BASE H_GET_64
#define PUT_OPTHDR_IMAGE_BASE H_PUT_64
#define GET_OPTHDR_SIZE_OF_STACK_RESERVE H_GET_64
#define PUT_OPTHDR_SIZE_OF_STACK_RESERVE H_PUT_64
#define GET_OPTHDR_SIZE_OF_STACK_COMMIT H_GET_64
#define PUT_OPTHDR_SIZE_OF_STACK_COMMIT H_PUT_64
#define GET_OPTHDR_SIZE_OF_HEAP_RESERVE H_GET_64
#define PUT_OPTHDR_SIZE_OF_HEAP_RESERVE H_PUT_64
#define GET_OPTHDR_SIZE_OF_HEAP_COMMIT H_GET_64
#define PUT_OPTHDR_SIZE_OF_HEAP_COMMIT H_PUT_64
#define GET_PDATA_ENTRY bfd_get_64
#define _bfd_XX_bfd_copy_private_bfd_data_common _bfd_pep_bfd_copy_private_bfd_data_common
#define _bfd_XX_bfd_copy_private_section_data _bfd_pep_bfd_copy_private_section_data
#define _bfd_XX_get_symbol_info _bfd_pep_get_symbol_info
#define _bfd_XX_only_swap_filehdr_out _bfd_pep_only_swap_filehdr_out
#define _bfd_XX_print_private_bfd_data_common _bfd_pep_print_private_bfd_data_common
#define _bfd_XXi_final_link_postscript _bfd_pepi_final_link_postscript
#define _bfd_XXi_only_swap_filehdr_out _bfd_pepi_only_swap_filehdr_out
#define _bfd_XXi_swap_aouthdr_in _bfd_pepi_swap_aouthdr_in
#define _bfd_XXi_swap_aouthdr_out _bfd_pepi_swap_aouthdr_out
#define _bfd_XXi_swap_aux_in _bfd_pepi_swap_aux_in
#define _bfd_XXi_swap_aux_out _bfd_pepi_swap_aux_out
#define _bfd_XXi_swap_lineno_in _bfd_pepi_swap_lineno_in
#define _bfd_XXi_swap_lineno_out _bfd_pepi_swap_lineno_out
#define _bfd_XXi_swap_scnhdr_out _bfd_pepi_swap_scnhdr_out
#define _bfd_XXi_swap_sym_in _bfd_pepi_swap_sym_in
#define _bfd_XXi_swap_sym_out _bfd_pepi_swap_sym_out
#else /* !COFF_WITH_pep */
#define GET_OPTHDR_IMAGE_BASE H_GET_32
#define PUT_OPTHDR_IMAGE_BASE H_PUT_32
#define GET_OPTHDR_SIZE_OF_STACK_RESERVE H_GET_32
#define PUT_OPTHDR_SIZE_OF_STACK_RESERVE H_PUT_32
#define GET_OPTHDR_SIZE_OF_STACK_COMMIT H_GET_32
#define PUT_OPTHDR_SIZE_OF_STACK_COMMIT H_PUT_32
#define GET_OPTHDR_SIZE_OF_HEAP_RESERVE H_GET_32
#define PUT_OPTHDR_SIZE_OF_HEAP_RESERVE H_PUT_32
#define GET_OPTHDR_SIZE_OF_HEAP_COMMIT H_GET_32
#define PUT_OPTHDR_SIZE_OF_HEAP_COMMIT H_PUT_32
#define GET_PDATA_ENTRY bfd_get_32
#define _bfd_XX_bfd_copy_private_bfd_data_common _bfd_pe_bfd_copy_private_bfd_data_common
#define _bfd_XX_bfd_copy_private_section_data _bfd_pe_bfd_copy_private_section_data
#define _bfd_XX_get_symbol_info _bfd_pe_get_symbol_info
#define _bfd_XX_only_swap_filehdr_out _bfd_pe_only_swap_filehdr_out
#define _bfd_XX_print_private_bfd_data_common _bfd_pe_print_private_bfd_data_common
#define _bfd_XXi_final_link_postscript _bfd_pei_final_link_postscript
#define _bfd_XXi_only_swap_filehdr_out _bfd_pei_only_swap_filehdr_out
#define _bfd_XXi_swap_aouthdr_in _bfd_pei_swap_aouthdr_in
#define _bfd_XXi_swap_aouthdr_out _bfd_pei_swap_aouthdr_out
#define _bfd_XXi_swap_aux_in _bfd_pei_swap_aux_in
#define _bfd_XXi_swap_aux_out _bfd_pei_swap_aux_out
#define _bfd_XXi_swap_lineno_in _bfd_pei_swap_lineno_in
#define _bfd_XXi_swap_lineno_out _bfd_pei_swap_lineno_out
#define _bfd_XXi_swap_scnhdr_out _bfd_pei_swap_scnhdr_out
#define _bfd_XXi_swap_sym_in _bfd_pei_swap_sym_in
#define _bfd_XXi_swap_sym_out _bfd_pei_swap_sym_out
#endif /* !COFF_WITH_pep */
/* These functions are architecture dependent, and are in peicode.h:
coff_swap_reloc_in
int coff_swap_reloc_out
coff_swap_filehdr_in
coff_swap_scnhdr_in
pe_mkobject
pe_mkobject_hook */
/* The functions described below are common across all PE/PEI
implementations architecture types, and actually appear in
peigen.c. */
#define coff_swap_sym_in _bfd_XXi_swap_sym_in
#define coff_swap_sym_out _bfd_XXi_swap_sym_out
#define coff_swap_aux_in _bfd_XXi_swap_aux_in
#define coff_swap_aux_out _bfd_XXi_swap_aux_out
#define coff_swap_lineno_in _bfd_XXi_swap_lineno_in
#define coff_swap_lineno_out _bfd_XXi_swap_lineno_out
#define coff_swap_aouthdr_in _bfd_XXi_swap_aouthdr_in
#define coff_swap_aouthdr_out _bfd_XXi_swap_aouthdr_out
#define coff_swap_scnhdr_out _bfd_XXi_swap_scnhdr_out
#ifndef coff_final_link_postscript
#define coff_final_link_postscript _bfd_XXi_final_link_postscript
#endif
void _bfd_XXi_swap_sym_in (bfd *, void *, void *);
unsigned _bfd_XXi_swap_sym_out (bfd *, void *, void *);
void _bfd_XXi_swap_aux_in (bfd *, void *, int, int, int, int, void *);
unsigned _bfd_XXi_swap_aux_out (bfd *, void *, int, int, int, int, void *);
void _bfd_XXi_swap_lineno_in (bfd *, void *, void *);
unsigned _bfd_XXi_swap_lineno_out (bfd *, void *, void *);
void _bfd_XXi_swap_aouthdr_in (bfd *, void *, void *);
unsigned _bfd_XXi_swap_aouthdr_out (bfd *, void *, void *);
unsigned _bfd_XXi_swap_scnhdr_out (bfd *, void *, void *);
bfd_boolean _bfd_XX_print_private_bfd_data_common (bfd *, void *);
bfd_boolean _bfd_XX_bfd_copy_private_bfd_data_common (bfd *, bfd *);
void _bfd_XX_get_symbol_info (bfd *, asymbol *, symbol_info *);
bfd_boolean _bfd_XXi_final_link_postscript (bfd *, struct coff_final_link_info *);
/* The following are needed only for ONE of pe or pei, but don't
otherwise vary; peicode.h fixes up ifdefs but we provide the
prototype. */
unsigned _bfd_XX_only_swap_filehdr_out (bfd *, void *, void *);
unsigned _bfd_XXi_only_swap_filehdr_out (bfd *, void *, void *);
bfd_boolean _bfd_XX_bfd_copy_private_section_data (bfd *, asection *, bfd *, asection *);
bfd_boolean _bfd_pe_print_ce_compressed_pdata (bfd *, void *);
bfd_boolean _bfd_pe64_print_ce_compressed_pdata (bfd *, void *);
bfd_boolean _bfd_pex64_print_ce_compressed_pdata (bfd *, void *);
bfd_boolean _bfd_pep_print_ce_compressed_pdata (bfd *, void *);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,901 @@
/* SEC_MERGE support.
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Written by Jakub Jelinek <jakub@redhat.com>.
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. */
/* This file contains support for merging duplicate entities within sections,
as used in ELF SHF_MERGE. */
#include "sysdep.h"
#include "bfd.h"
#include "libbfd.h"
#include "hashtab.h"
#include "libiberty.h"
struct sec_merge_sec_info;
/* An entry in the section merge hash table. */
struct sec_merge_hash_entry
{
struct bfd_hash_entry root;
/* Length of this entry. This includes the zero terminator. */
unsigned int len;
/* Start of this string needs to be aligned to
alignment octets (not 1 << align). */
unsigned int alignment;
union
{
/* Index within the merged section. */
bfd_size_type index;
/* Entry this is a suffix of (if alignment is 0). */
struct sec_merge_hash_entry *suffix;
} u;
/* Which section is it in. */
struct sec_merge_sec_info *secinfo;
/* Next entity in the hash table. */
struct sec_merge_hash_entry *next;
};
/* The section merge hash table. */
struct sec_merge_hash
{
struct bfd_hash_table table;
/* Next available index. */
bfd_size_type size;
/* First entity in the SEC_MERGE sections of this type. */
struct sec_merge_hash_entry *first;
/* Last entity in the SEC_MERGE sections of this type. */
struct sec_merge_hash_entry *last;
/* Entity size. */
unsigned int entsize;
/* Are entries fixed size or zero terminated strings? */
bfd_boolean strings;
};
struct sec_merge_info
{
/* Chain of sec_merge_infos. */
struct sec_merge_info *next;
/* Chain of sec_merge_sec_infos. */
struct sec_merge_sec_info *chain;
/* A hash table used to hold section content. */
struct sec_merge_hash *htab;
};
struct sec_merge_sec_info
{
/* Chain of sec_merge_sec_infos. */
struct sec_merge_sec_info *next;
/* The corresponding section. */
asection *sec;
/* Pointer to merge_info pointing to us. */
void **psecinfo;
/* A hash table used to hold section content. */
struct sec_merge_hash *htab;
/* First string in this section. */
struct sec_merge_hash_entry *first_str;
/* Original section content. */
unsigned char contents[1];
};
/* Routine to create an entry in a section merge hashtab. */
static struct bfd_hash_entry *
sec_merge_hash_newfunc (struct bfd_hash_entry *entry,
struct bfd_hash_table *table, const char *string)
{
/* Allocate the structure if it has not already been allocated by a
subclass. */
if (entry == NULL)
entry = (struct bfd_hash_entry *)
bfd_hash_allocate (table, sizeof (struct sec_merge_hash_entry));
if (entry == NULL)
return NULL;
/* Call the allocation method of the superclass. */
entry = bfd_hash_newfunc (entry, table, string);
if (entry != NULL)
{
/* Initialize the local fields. */
struct sec_merge_hash_entry *ret = (struct sec_merge_hash_entry *) entry;
ret->u.suffix = NULL;
ret->alignment = 0;
ret->secinfo = NULL;
ret->next = NULL;
}
return entry;
}
/* Look up an entry in a section merge hash table. */
static struct sec_merge_hash_entry *
sec_merge_hash_lookup (struct sec_merge_hash *table, const char *string,
unsigned int alignment, bfd_boolean create)
{
const unsigned char *s;
unsigned long hash;
unsigned int c;
struct sec_merge_hash_entry *hashp;
unsigned int len, i;
unsigned int _index;
hash = 0;
len = 0;
s = (const unsigned char *) string;
if (table->strings)
{
if (table->entsize == 1)
{
while ((c = *s++) != '\0')
{
hash += c + (c << 17);
hash ^= hash >> 2;
++len;
}
hash += len + (len << 17);
}
else
{
for (;;)
{
for (i = 0; i < table->entsize; ++i)
if (s[i] != '\0')
break;
if (i == table->entsize)
break;
for (i = 0; i < table->entsize; ++i)
{
c = *s++;
hash += c + (c << 17);
hash ^= hash >> 2;
}
++len;
}
hash += len + (len << 17);
len *= table->entsize;
}
hash ^= hash >> 2;
len += table->entsize;
}
else
{
for (i = 0; i < table->entsize; ++i)
{
c = *s++;
hash += c + (c << 17);
hash ^= hash >> 2;
}
len = table->entsize;
}
_index = hash % table->table.size;
for (hashp = (struct sec_merge_hash_entry *) table->table.table[_index];
hashp != NULL;
hashp = (struct sec_merge_hash_entry *) hashp->root.next)
{
if (hashp->root.hash == hash
&& len == hashp->len
&& memcmp (hashp->root.string, string, len) == 0)
{
/* If the string we found does not have at least the required
alignment, we need to insert another copy. */
if (hashp->alignment < alignment)
{
if (create)
{
/* Mark the less aligned copy as deleted. */
hashp->len = 0;
hashp->alignment = 0;
}
break;
}
return hashp;
}
}
if (! create)
return NULL;
hashp = ((struct sec_merge_hash_entry *)
bfd_hash_insert (&table->table, string, hash));
if (hashp == NULL)
return NULL;
hashp->len = len;
hashp->alignment = alignment;
return hashp;
}
/* Create a new hash table. */
static struct sec_merge_hash *
sec_merge_init (unsigned int entsize, bfd_boolean strings)
{
struct sec_merge_hash *table;
table = (struct sec_merge_hash *) bfd_malloc (sizeof (struct sec_merge_hash));
if (table == NULL)
return NULL;
if (! bfd_hash_table_init_n (&table->table, sec_merge_hash_newfunc,
sizeof (struct sec_merge_hash_entry), 16699))
{
free (table);
return NULL;
}
table->size = 0;
table->first = NULL;
table->last = NULL;
table->entsize = entsize;
table->strings = strings;
return table;
}
/* Get the index of an entity in a hash table, adding it if it is not
already present. */
static struct sec_merge_hash_entry *
sec_merge_add (struct sec_merge_hash *tab, const char *str,
unsigned int alignment, struct sec_merge_sec_info *secinfo)
{
struct sec_merge_hash_entry *entry;
entry = sec_merge_hash_lookup (tab, str, alignment, TRUE);
if (entry == NULL)
return NULL;
if (entry->secinfo == NULL)
{
tab->size++;
entry->secinfo = secinfo;
if (tab->first == NULL)
tab->first = entry;
else
tab->last->next = entry;
tab->last = entry;
}
return entry;
}
static bfd_boolean
sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry)
{
struct sec_merge_sec_info *secinfo = entry->secinfo;
asection *sec = secinfo->sec;
char *pad = NULL;
bfd_size_type off = 0;
int alignment_power = sec->output_section->alignment_power;
if (alignment_power)
{
pad = (char *) bfd_zmalloc ((bfd_size_type) 1 << alignment_power);
if (pad == NULL)
return FALSE;
}
for (; entry != NULL && entry->secinfo == secinfo; entry = entry->next)
{
const char *str;
bfd_size_type len;
len = -off & (entry->alignment - 1);
if (len != 0)
{
if (bfd_bwrite (pad, len, abfd) != len)
goto err;
off += len;
}
str = entry->root.string;
len = entry->len;
if (bfd_bwrite (str, len, abfd) != len)
goto err;
off += len;
}
/* Trailing alignment needed? */
off = sec->size - off;
if (off != 0
&& bfd_bwrite (pad, off, abfd) != off)
goto err;
if (pad != NULL)
free (pad);
return TRUE;
err:
if (pad != NULL)
free (pad);
return FALSE;
}
/* Register a SEC_MERGE section as a candidate for merging.
This function is called for all non-dynamic SEC_MERGE input sections. */
bfd_boolean
_bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec,
void **psecinfo)
{
struct sec_merge_info *sinfo;
struct sec_merge_sec_info *secinfo;
unsigned int align;
bfd_size_type amt;
bfd_byte *contents;
if ((abfd->flags & DYNAMIC) != 0
|| (sec->flags & SEC_MERGE) == 0)
abort ();
if (sec->size == 0
|| (sec->flags & SEC_EXCLUDE) != 0
|| sec->entsize == 0)
return TRUE;
if ((sec->flags & SEC_RELOC) != 0)
{
/* We aren't prepared to handle relocations in merged sections. */
return TRUE;
}
align = sec->alignment_power;
if ((sec->entsize < (unsigned) 1 << align
&& ((sec->entsize & (sec->entsize - 1))
|| !(sec->flags & SEC_STRINGS)))
|| (sec->entsize > (unsigned) 1 << align
&& (sec->entsize & (((unsigned) 1 << align) - 1))))
{
/* Sanity check. If string character size is smaller than
alignment, then we require character size to be a power
of 2, otherwise character size must be integer multiple
of alignment. For non-string constants, alignment must
be smaller than or equal to entity size and entity size
must be integer multiple of alignment. */
return TRUE;
}
for (sinfo = (struct sec_merge_info *) *psinfo; sinfo; sinfo = sinfo->next)
if ((secinfo = sinfo->chain)
&& ! ((secinfo->sec->flags ^ sec->flags) & (SEC_MERGE | SEC_STRINGS))
&& secinfo->sec->entsize == sec->entsize
&& secinfo->sec->alignment_power == sec->alignment_power
&& secinfo->sec->output_section == sec->output_section)
break;
if (sinfo == NULL)
{
/* Initialize the information we need to keep track of. */
sinfo = (struct sec_merge_info *)
bfd_alloc (abfd, sizeof (struct sec_merge_info));
if (sinfo == NULL)
goto error_return;
sinfo->next = (struct sec_merge_info *) *psinfo;
sinfo->chain = NULL;
*psinfo = sinfo;
sinfo->htab = sec_merge_init (sec->entsize, (sec->flags & SEC_STRINGS));
if (sinfo->htab == NULL)
goto error_return;
}
/* Read the section from abfd. */
amt = sizeof (struct sec_merge_sec_info) - 1 + sec->size;
if (sec->flags & SEC_STRINGS)
/* Some versions of gcc may emit a string without a zero terminator.
See http://gcc.gnu.org/ml/gcc-patches/2006-06/msg01004.html
Allocate space for an extra zero. */
amt += sec->entsize;
*psecinfo = bfd_alloc (abfd, amt);
if (*psecinfo == NULL)
goto error_return;
secinfo = (struct sec_merge_sec_info *) *psecinfo;
if (sinfo->chain)
{
secinfo->next = sinfo->chain->next;
sinfo->chain->next = secinfo;
}
else
secinfo->next = secinfo;
sinfo->chain = secinfo;
secinfo->sec = sec;
secinfo->psecinfo = psecinfo;
secinfo->htab = sinfo->htab;
secinfo->first_str = NULL;
sec->rawsize = sec->size;
if (sec->flags & SEC_STRINGS)
memset (secinfo->contents + sec->size, 0, sec->entsize);
contents = secinfo->contents;
if (! bfd_get_full_section_contents (sec->owner, sec, &contents))
goto error_return;
return TRUE;
error_return:
*psecinfo = NULL;
return FALSE;
}
/* Record one section into the hash table. */
static bfd_boolean
record_section (struct sec_merge_info *sinfo,
struct sec_merge_sec_info *secinfo)
{
asection *sec = secinfo->sec;
struct sec_merge_hash_entry *entry;
bfd_boolean nul;
unsigned char *p, *end;
bfd_vma mask, eltalign;
unsigned int align, i;
align = sec->alignment_power;
end = secinfo->contents + sec->size;
nul = FALSE;
mask = ((bfd_vma) 1 << align) - 1;
if (sec->flags & SEC_STRINGS)
{
for (p = secinfo->contents; p < end; )
{
eltalign = p - secinfo->contents;
eltalign = ((eltalign ^ (eltalign - 1)) + 1) >> 1;
if (!eltalign || eltalign > mask)
eltalign = mask + 1;
entry = sec_merge_add (sinfo->htab, (char *) p, (unsigned) eltalign,
secinfo);
if (! entry)
goto error_return;
p += entry->len;
if (sec->entsize == 1)
{
while (p < end && *p == 0)
{
if (!nul && !((p - secinfo->contents) & mask))
{
nul = TRUE;
entry = sec_merge_add (sinfo->htab, "",
(unsigned) mask + 1, secinfo);
if (! entry)
goto error_return;
}
p++;
}
}
else
{
while (p < end)
{
for (i = 0; i < sec->entsize; i++)
if (p[i] != '\0')
break;
if (i != sec->entsize)
break;
if (!nul && !((p - secinfo->contents) & mask))
{
nul = TRUE;
entry = sec_merge_add (sinfo->htab, (char *) p,
(unsigned) mask + 1, secinfo);
if (! entry)
goto error_return;
}
p += sec->entsize;
}
}
}
}
else
{
for (p = secinfo->contents; p < end; p += sec->entsize)
{
entry = sec_merge_add (sinfo->htab, (char *) p, 1, secinfo);
if (! entry)
goto error_return;
}
}
return TRUE;
error_return:
for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
*secinfo->psecinfo = NULL;
return FALSE;
}
static int
strrevcmp (const void *a, const void *b)
{
struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a;
struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b;
unsigned int lenA = A->len;
unsigned int lenB = B->len;
const unsigned char *s = (const unsigned char *) A->root.string + lenA - 1;
const unsigned char *t = (const unsigned char *) B->root.string + lenB - 1;
int l = lenA < lenB ? lenA : lenB;
while (l)
{
if (*s != *t)
return (int) *s - (int) *t;
s--;
t--;
l--;
}
return lenA - lenB;
}
/* Like strrevcmp, but for the case where all strings have the same
alignment > entsize. */
static int
strrevcmp_align (const void *a, const void *b)
{
struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a;
struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b;
unsigned int lenA = A->len;
unsigned int lenB = B->len;
const unsigned char *s = (const unsigned char *) A->root.string + lenA - 1;
const unsigned char *t = (const unsigned char *) B->root.string + lenB - 1;
int l = lenA < lenB ? lenA : lenB;
int tail_align = (lenA & (A->alignment - 1)) - (lenB & (A->alignment - 1));
if (tail_align != 0)
return tail_align;
while (l)
{
if (*s != *t)
return (int) *s - (int) *t;
s--;
t--;
l--;
}
return lenA - lenB;
}
static inline int
is_suffix (const struct sec_merge_hash_entry *A,
const struct sec_merge_hash_entry *B)
{
if (A->len <= B->len)
/* B cannot be a suffix of A unless A is equal to B, which is guaranteed
not to be equal by the hash table. */
return 0;
return memcmp (A->root.string + (A->len - B->len),
B->root.string, B->len) == 0;
}
/* This is a helper function for _bfd_merge_sections. It attempts to
merge strings matching suffixes of longer strings. */
static void
merge_strings (struct sec_merge_info *sinfo)
{
struct sec_merge_hash_entry **array, **a, *e;
struct sec_merge_sec_info *secinfo;
bfd_size_type size, amt;
unsigned int alignment = 0;
/* Now sort the strings */
amt = sinfo->htab->size * sizeof (struct sec_merge_hash_entry *);
array = (struct sec_merge_hash_entry **) bfd_malloc (amt);
if (array == NULL)
goto alloc_failure;
for (e = sinfo->htab->first, a = array; e; e = e->next)
if (e->alignment)
{
*a++ = e;
/* Adjust the length to not include the zero terminator. */
e->len -= sinfo->htab->entsize;
if (alignment != e->alignment)
{
if (alignment == 0)
alignment = e->alignment;
else
alignment = (unsigned) -1;
}
}
sinfo->htab->size = a - array;
if (sinfo->htab->size != 0)
{
qsort (array, (size_t) sinfo->htab->size,
sizeof (struct sec_merge_hash_entry *),
(alignment != (unsigned) -1 && alignment > sinfo->htab->entsize
? strrevcmp_align : strrevcmp));
/* Loop over the sorted array and merge suffixes */
e = *--a;
e->len += sinfo->htab->entsize;
while (--a >= array)
{
struct sec_merge_hash_entry *cmp = *a;
cmp->len += sinfo->htab->entsize;
if (e->alignment >= cmp->alignment
&& !((e->len - cmp->len) & (cmp->alignment - 1))
&& is_suffix (e, cmp))
{
cmp->u.suffix = e;
cmp->alignment = 0;
}
else
e = cmp;
}
}
alloc_failure:
if (array)
free (array);
/* Now assign positions to the strings we want to keep. */
size = 0;
secinfo = sinfo->htab->first->secinfo;
for (e = sinfo->htab->first; e; e = e->next)
{
if (e->secinfo != secinfo)
{
secinfo->sec->size = size;
secinfo = e->secinfo;
}
if (e->alignment)
{
if (e->secinfo->first_str == NULL)
{
e->secinfo->first_str = e;
size = 0;
}
size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1);
e->u.index = size;
size += e->len;
}
}
secinfo->sec->size = size;
if (secinfo->sec->alignment_power != 0)
{
bfd_size_type align = (bfd_size_type) 1 << secinfo->sec->alignment_power;
secinfo->sec->size = (secinfo->sec->size + align - 1) & -align;
}
/* And now adjust the rest, removing them from the chain (but not hashtable)
at the same time. */
for (a = &sinfo->htab->first, e = *a; e; e = e->next)
if (e->alignment)
a = &e->next;
else
{
*a = e->next;
if (e->len)
{
e->secinfo = e->u.suffix->secinfo;
e->alignment = e->u.suffix->alignment;
e->u.index = e->u.suffix->u.index + (e->u.suffix->len - e->len);
}
}
}
/* This function is called once after all SEC_MERGE sections are registered
with _bfd_merge_section. */
bfd_boolean
_bfd_merge_sections (bfd *abfd,
struct bfd_link_info *info ATTRIBUTE_UNUSED,
void *xsinfo,
void (*remove_hook) (bfd *, asection *))
{
struct sec_merge_info *sinfo;
for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
{
struct sec_merge_sec_info * secinfo;
if (! sinfo->chain)
continue;
/* Move sinfo->chain to head of the chain, terminate it. */
secinfo = sinfo->chain;
sinfo->chain = secinfo->next;
secinfo->next = NULL;
/* Record the sections into the hash table. */
for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
if (secinfo->sec->flags & SEC_EXCLUDE)
{
*secinfo->psecinfo = NULL;
if (remove_hook)
(*remove_hook) (abfd, secinfo->sec);
}
else if (! record_section (sinfo, secinfo))
break;
if (secinfo)
continue;
if (sinfo->htab->first == NULL)
continue;
if (sinfo->htab->strings)
merge_strings (sinfo);
else
{
struct sec_merge_hash_entry *e;
bfd_size_type size = 0;
/* Things are much simpler for non-strings.
Just assign them slots in the section. */
secinfo = NULL;
for (e = sinfo->htab->first; e; e = e->next)
{
if (e->secinfo->first_str == NULL)
{
if (secinfo)
secinfo->sec->size = size;
e->secinfo->first_str = e;
size = 0;
}
size = (size + e->alignment - 1)
& ~((bfd_vma) e->alignment - 1);
e->u.index = size;
size += e->len;
secinfo = e->secinfo;
}
secinfo->sec->size = size;
}
/* Finally remove all input sections which have not made it into
the hash table at all. */
for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
if (secinfo->first_str == NULL)
secinfo->sec->flags |= SEC_EXCLUDE | SEC_KEEP;
}
return TRUE;
}
/* Write out the merged section. */
bfd_boolean
_bfd_write_merged_section (bfd *output_bfd, asection *sec, void *psecinfo)
{
struct sec_merge_sec_info *secinfo;
file_ptr pos;
secinfo = (struct sec_merge_sec_info *) psecinfo;
if (!secinfo)
return FALSE;
if (secinfo->first_str == NULL)
return TRUE;
/* FIXME: octets_per_byte. */
pos = sec->output_section->filepos + sec->output_offset;
if (bfd_seek (output_bfd, pos, SEEK_SET) != 0)
return FALSE;
if (! sec_merge_emit (output_bfd, secinfo->first_str))
return FALSE;
return TRUE;
}
/* Adjust an address in the SEC_MERGE section. Given OFFSET within
*PSEC, this returns the new offset in the adjusted SEC_MERGE
section and writes the new section back into *PSEC. */
bfd_vma
_bfd_merged_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, asection **psec,
void *psecinfo, bfd_vma offset)
{
struct sec_merge_sec_info *secinfo;
struct sec_merge_hash_entry *entry;
unsigned char *p;
asection *sec = *psec;
secinfo = (struct sec_merge_sec_info *) psecinfo;
if (!secinfo)
return offset;
if (offset >= sec->rawsize)
{
if (offset > sec->rawsize)
{
(*_bfd_error_handler)
(_("%s: access beyond end of merged section (%ld)"),
bfd_get_filename (sec->owner), (long) offset);
}
return secinfo->first_str ? sec->size : 0;
}
if (secinfo->htab->strings)
{
if (sec->entsize == 1)
{
p = secinfo->contents + offset - 1;
while (p >= secinfo->contents && *p)
--p;
++p;
}
else
{
p = secinfo->contents + (offset / sec->entsize) * sec->entsize;
p -= sec->entsize;
while (p >= secinfo->contents)
{
unsigned int i;
for (i = 0; i < sec->entsize; ++i)
if (p[i] != '\0')
break;
if (i == sec->entsize)
break;
p -= sec->entsize;
}
p += sec->entsize;
}
}
else
{
p = secinfo->contents + (offset / sec->entsize) * sec->entsize;
}
entry = sec_merge_hash_lookup (secinfo->htab, (char *) p, 0, FALSE);
if (!entry)
{
if (! secinfo->htab->strings)
abort ();
/* This should only happen if somebody points into the padding
after a NUL character but before next entity. */
if (*p)
abort ();
if (! secinfo->htab->first)
abort ();
entry = secinfo->htab->first;
p = (secinfo->contents + (offset / sec->entsize + 1) * sec->entsize
- entry->len);
}
*psec = entry->secinfo->sec;
return entry->u.index + (secinfo->contents + offset - p);
}
/* Tidy up when done. */
void
_bfd_merge_sections_free (void *xsinfo)
{
struct sec_merge_info *sinfo;
for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
{
bfd_hash_table_free (&sinfo->htab->table);
free (sinfo->htab);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
/* BFD back-end for Intel 386 PECOFF files.
Copyright 1995, 1996, 1999, 2001, 2002, 2004, 2005, 2006, 2007
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 i386pe_vec
#define TARGET_NAME "pe-i386"
#define COFF_WITH_PE
#define PCRELOFFSET TRUE
#define TARGET_UNDERSCORE '_'
#define COFF_LONG_SECTION_NAMES
#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 (".zdebug"), \
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"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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,253 @@
/* simple.c -- BFD simple client routines
Copyright 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by MontaVista Software, 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"
#include "libbfd.h"
#include "bfdlink.h"
static bfd_boolean
simple_dummy_warning (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
const char *warning ATTRIBUTE_UNUSED,
const char *symbol ATTRIBUTE_UNUSED,
bfd *abfd ATTRIBUTE_UNUSED,
asection *section ATTRIBUTE_UNUSED,
bfd_vma address ATTRIBUTE_UNUSED)
{
return TRUE;
}
static bfd_boolean
simple_dummy_undefined_symbol (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
const char *name ATTRIBUTE_UNUSED,
bfd *abfd ATTRIBUTE_UNUSED,
asection *section ATTRIBUTE_UNUSED,
bfd_vma address ATTRIBUTE_UNUSED,
bfd_boolean fatal ATTRIBUTE_UNUSED)
{
return TRUE;
}
static bfd_boolean
simple_dummy_reloc_overflow (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
struct bfd_link_hash_entry *entry ATTRIBUTE_UNUSED,
const char *name ATTRIBUTE_UNUSED,
const char *reloc_name ATTRIBUTE_UNUSED,
bfd_vma addend ATTRIBUTE_UNUSED,
bfd *abfd ATTRIBUTE_UNUSED,
asection *section ATTRIBUTE_UNUSED,
bfd_vma address ATTRIBUTE_UNUSED)
{
return TRUE;
}
static bfd_boolean
simple_dummy_reloc_dangerous (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
const char *message ATTRIBUTE_UNUSED,
bfd *abfd ATTRIBUTE_UNUSED,
asection *section ATTRIBUTE_UNUSED,
bfd_vma address ATTRIBUTE_UNUSED)
{
return TRUE;
}
static bfd_boolean
simple_dummy_unattached_reloc (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
const char *name ATTRIBUTE_UNUSED,
bfd *abfd ATTRIBUTE_UNUSED,
asection *section ATTRIBUTE_UNUSED,
bfd_vma address ATTRIBUTE_UNUSED)
{
return TRUE;
}
static bfd_boolean
simple_dummy_multiple_definition (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED,
bfd *nbfd ATTRIBUTE_UNUSED,
asection *nsec ATTRIBUTE_UNUSED,
bfd_vma nval ATTRIBUTE_UNUSED)
{
return TRUE;
}
static void
simple_dummy_einfo (const char *fmt ATTRIBUTE_UNUSED, ...)
{
}
struct saved_output_info
{
bfd_vma offset;
asection *section;
};
static void
simple_save_output_info (bfd *abfd ATTRIBUTE_UNUSED,
asection *section,
void *ptr)
{
struct saved_output_info *output_info = (struct saved_output_info *) ptr;
output_info[section->index].offset = section->output_offset;
output_info[section->index].section = section->output_section;
if ((section->flags & SEC_DEBUGGING) != 0
|| section->output_section == NULL)
{
section->output_offset = 0;
section->output_section = section;
}
}
static void
simple_restore_output_info (bfd *abfd ATTRIBUTE_UNUSED,
asection *section,
void *ptr)
{
struct saved_output_info *output_info = (struct saved_output_info *) ptr;
section->output_offset = output_info[section->index].offset;
section->output_section = output_info[section->index].section;
}
/*
FUNCTION
bfd_simple_relocate_secton
SYNOPSIS
bfd_byte *bfd_simple_get_relocated_section_contents
(bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table);
DESCRIPTION
Returns the relocated contents of section @var{sec}. The symbols in
@var{symbol_table} will be used, or the symbols from @var{abfd} if
@var{symbol_table} is NULL. The output offsets for debug sections will
be temporarily reset to 0. The result will be stored at @var{outbuf}
or allocated with @code{bfd_malloc} if @var{outbuf} is @code{NULL}.
Returns @code{NULL} on a fatal error; ignores errors applying
particular relocations.
*/
bfd_byte *
bfd_simple_get_relocated_section_contents (bfd *abfd,
asection *sec,
bfd_byte *outbuf,
asymbol **symbol_table)
{
struct bfd_link_info link_info;
struct bfd_link_order link_order;
struct bfd_link_callbacks callbacks;
bfd_byte *contents, *data;
int storage_needed;
void *saved_offsets;
/* Don't apply relocation on executable and shared library. See
PR 4756. */
if ((abfd->flags & (HAS_RELOC | EXEC_P | DYNAMIC)) != HAS_RELOC
|| ! (sec->flags & SEC_RELOC))
{
contents = outbuf;
if (!bfd_get_full_section_contents (abfd, sec, &contents))
return NULL;
return contents;
}
/* In order to use bfd_get_relocated_section_contents, we need
to forge some data structures that it expects. */
/* Fill in the bare minimum number of fields for our purposes. */
memset (&link_info, 0, sizeof (link_info));
link_info.output_bfd = abfd;
link_info.input_bfds = abfd;
link_info.input_bfds_tail = &abfd->link_next;
link_info.hash = _bfd_generic_link_hash_table_create (abfd);
link_info.callbacks = &callbacks;
callbacks.warning = simple_dummy_warning;
callbacks.undefined_symbol = simple_dummy_undefined_symbol;
callbacks.reloc_overflow = simple_dummy_reloc_overflow;
callbacks.reloc_dangerous = simple_dummy_reloc_dangerous;
callbacks.unattached_reloc = simple_dummy_unattached_reloc;
callbacks.multiple_definition = simple_dummy_multiple_definition;
callbacks.einfo = simple_dummy_einfo;
memset (&link_order, 0, sizeof (link_order));
link_order.next = NULL;
link_order.type = bfd_indirect_link_order;
link_order.offset = 0;
link_order.size = sec->size;
link_order.u.indirect.section = sec;
data = NULL;
if (outbuf == NULL)
{
bfd_size_type amt = sec->rawsize > sec->size ? sec->rawsize : sec->size;
data = (bfd_byte *) bfd_malloc (amt);
if (data == NULL)
return NULL;
outbuf = data;
}
/* The sections in ABFD may already have output sections and offsets set.
Because this function is primarily for debug sections, and GCC uses the
knowledge that debug sections will generally have VMA 0 when emitting
relocations between DWARF-2 sections (which are supposed to be
section-relative offsets anyway), we need to reset the output offsets
to zero. We also need to arrange for section->output_section->vma plus
section->output_offset to equal section->vma, which we do by setting
section->output_section to point back to section. Save the original
output offset and output section to restore later. */
saved_offsets = malloc (sizeof (struct saved_output_info)
* abfd->section_count);
if (saved_offsets == NULL)
{
if (data)
free (data);
return NULL;
}
bfd_map_over_sections (abfd, simple_save_output_info, saved_offsets);
if (symbol_table == NULL)
{
_bfd_generic_link_add_symbols (abfd, &link_info);
storage_needed = bfd_get_symtab_upper_bound (abfd);
symbol_table = (asymbol **) bfd_malloc (storage_needed);
bfd_canonicalize_symtab (abfd, symbol_table);
}
else
storage_needed = 0;
contents = bfd_get_relocated_section_contents (abfd,
&link_info,
&link_order,
outbuf,
0,
symbol_table);
if (contents == NULL && data != NULL)
free (data);
bfd_map_over_sections (abfd, simple_restore_output_info, saved_offsets);
free (saved_offsets);
_bfd_generic_link_hash_table_free (link_info.hash);
return contents;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,60 @@
/* Table of stab names for the BFD library.
Copyright 1990, 1991, 1992, 1994, 1995, 1996, 2000, 2005, 2007, 2012
Free Software Foundation, Inc.
Written by Cygnus Support.
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 ARCH_SIZE 32 /* Value doesn't matter. */
#include "libaout.h"
#include "aout/aout64.h"
/* Ignore duplicate stab codes; just return the string for the first
one. */
#define __define_stab(NAME, CODE, STRING) __define_name(CODE, STRING)
#define __define_stab_duplicate(NAME, CODE, STRING)
/* These are not really stab symbols, but it is
convenient to have them here for the sake of nm.
For completeness, we could also add N_TEXT etc, but those
are never needed, since nm treats those specially. */
#define EXTRA_SYMBOLS \
__define_name (N_SETA, "SETA")/* Absolute set element symbol */ \
__define_name (N_SETT, "SETT")/* Text set element symbol */ \
__define_name (N_SETD, "SETD")/* Data set element symbol */ \
__define_name (N_SETB, "SETB")/* Bss set element symbol */ \
__define_name (N_SETV, "SETV")/* Pointer to set vector in data area. */ \
__define_name (N_INDR, "INDR") \
__define_name (N_WARNING, "WARNING")
const char *
bfd_get_stab_name (code)
int code;
{
switch (code)
{
#define __define_name(val, str) case val: return str;
#include "aout/stab.def"
EXTRA_SYMBOLS
}
return (const char *) 0;
}

View File

@@ -0,0 +1,789 @@
/* Stabs in sections linking support.
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
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. */
/* This file contains support for linking stabs in sections, as used
on COFF and ELF. */
#include "sysdep.h"
#include "bfd.h"
#include "libbfd.h"
#include "aout/stab_gnu.h"
#include "safe-ctype.h"
/* Stabs entries use a 12 byte format:
4 byte string table index
1 byte stab type
1 byte stab other field
2 byte stab desc field
4 byte stab value
FIXME: This will have to change for a 64 bit object format.
The stabs symbols are divided into compilation units. For the
first entry in each unit, the type of 0, the value is the length of
the string table for this unit, and the desc field is the number of
stabs symbols for this unit. */
#define STRDXOFF 0
#define TYPEOFF 4
#define OTHEROFF 5
#define DESCOFF 6
#define VALOFF 8
#define STABSIZE 12
/* A linked list of totals that we have found for a particular header
file. A total is a unique identifier for a particular BINCL...EINCL
sequence of STABs that can be used to identify duplicate sequences.
It consists of three fields, 'sum_chars' which is the sum of all the
STABS characters; 'num_chars' which is the number of these charactes
and 'symb' which is a buffer of all the symbols in the sequence. This
buffer is only checked as a last resort. */
struct stab_link_includes_totals
{
struct stab_link_includes_totals *next;
bfd_vma sum_chars; /* Accumulated sum of STABS characters. */
bfd_vma num_chars; /* Number of STABS characters. */
const char* symb; /* The STABS characters themselves. */
};
/* An entry in the header file hash table. */
struct stab_link_includes_entry
{
struct bfd_hash_entry root;
/* List of totals we have found for this file. */
struct stab_link_includes_totals *totals;
};
/* This structure is used to hold a list of N_BINCL symbols, some of
which might be converted into N_EXCL symbols. */
struct stab_excl_list
{
/* The next symbol to convert. */
struct stab_excl_list *next;
/* The offset to this symbol in the section contents. */
bfd_size_type offset;
/* The value to use for the symbol. */
bfd_vma val;
/* The type of this symbol (N_BINCL or N_EXCL). */
int type;
};
/* This structure is stored with each .stab section. */
struct stab_section_info
{
/* This is a linked list of N_BINCL symbols which should be
converted into N_EXCL symbols. */
struct stab_excl_list *excls;
/* This is used to map input stab offsets within their sections
to output stab offsets, to take into account stabs that have
been deleted. If it is NULL, the output offsets are the same
as the input offsets, because no stabs have been deleted from
this section. Otherwise the i'th entry is the number of
bytes of stabs that have been deleted prior to the i'th
stab. */
bfd_size_type *cumulative_skips;
/* This is an array of string indices. For each stab symbol, we
store the string index here. If a stab symbol should not be
included in the final output, the string index is -1. */
bfd_size_type stridxs[1];
};
/* The function to create a new entry in the header file hash table. */
static struct bfd_hash_entry *
stab_link_includes_newfunc (struct bfd_hash_entry *entry,
struct bfd_hash_table *table,
const char *string)
{
struct stab_link_includes_entry *ret =
(struct stab_link_includes_entry *) entry;
/* Allocate the structure if it has not already been allocated by a
subclass. */
if (ret == NULL)
ret = (struct stab_link_includes_entry *)
bfd_hash_allocate (table, sizeof (struct stab_link_includes_entry));
if (ret == NULL)
return NULL;
/* Call the allocation method of the superclass. */
ret = ((struct stab_link_includes_entry *)
bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
if (ret)
/* Set local fields. */
ret->totals = NULL;
return (struct bfd_hash_entry *) ret;
}
/* This function is called for each input file from the add_symbols
pass of the linker. */
bfd_boolean
_bfd_link_section_stabs (bfd *abfd,
struct stab_info *sinfo,
asection *stabsec,
asection *stabstrsec,
void * *psecinfo,
bfd_size_type *pstring_offset)
{
bfd_boolean first;
bfd_size_type count, amt;
struct stab_section_info *secinfo;
bfd_byte *stabbuf = NULL;
bfd_byte *stabstrbuf = NULL;
bfd_byte *sym, *symend;
bfd_size_type stroff, next_stroff, skip;
bfd_size_type *pstridx;
if (stabsec->size == 0
|| stabstrsec->size == 0)
/* This file does not contain stabs debugging information. */
return TRUE;
if (stabsec->size % STABSIZE != 0)
/* Something is wrong with the format of these stab symbols.
Don't try to optimize them. */
return TRUE;
if ((stabstrsec->flags & SEC_RELOC) != 0)
/* We shouldn't see relocations in the strings, and we aren't
prepared to handle them. */
return TRUE;
if (bfd_is_abs_section (stabsec->output_section)
|| bfd_is_abs_section (stabstrsec->output_section))
/* At least one of the sections is being discarded from the
link, so we should just ignore them. */
return TRUE;
first = FALSE;
if (sinfo->stabstr == NULL)
{
flagword flags;
/* Initialize the stabs information we need to keep track of. */
first = TRUE;
sinfo->strings = _bfd_stringtab_init ();
if (sinfo->strings == NULL)
goto error_return;
/* Make sure the first byte is zero. */
(void) _bfd_stringtab_add (sinfo->strings, "", TRUE, TRUE);
if (! bfd_hash_table_init (&sinfo->includes,
stab_link_includes_newfunc,
sizeof (struct stab_link_includes_entry)))
goto error_return;
flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING
| SEC_LINKER_CREATED);
sinfo->stabstr = bfd_make_section_anyway_with_flags (abfd, ".stabstr",
flags);
if (sinfo->stabstr == NULL)
goto error_return;
}
/* Initialize the information we are going to store for this .stab
section. */
count = stabsec->size / STABSIZE;
amt = sizeof (struct stab_section_info);
amt += (count - 1) * sizeof (bfd_size_type);
*psecinfo = bfd_alloc (abfd, amt);
if (*psecinfo == NULL)
goto error_return;
secinfo = (struct stab_section_info *) *psecinfo;
secinfo->excls = NULL;
stabsec->rawsize = stabsec->size;
secinfo->cumulative_skips = NULL;
memset (secinfo->stridxs, 0, (size_t) count * sizeof (bfd_size_type));
/* Read the stabs information from abfd. */
if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf)
|| !bfd_malloc_and_get_section (abfd, stabstrsec, &stabstrbuf))
goto error_return;
/* Look through the stabs symbols, work out the new string indices,
and identify N_BINCL symbols which can be eliminated. */
stroff = 0;
/* The stabs sections can be split when
-split-by-reloc/-split-by-file is used. We must keep track of
each stab section's place in the single concatenated string
table. */
next_stroff = pstring_offset ? *pstring_offset : 0;
skip = 0;
symend = stabbuf + stabsec->size;
for (sym = stabbuf, pstridx = secinfo->stridxs;
sym < symend;
sym += STABSIZE, ++pstridx)
{
bfd_size_type symstroff;
int type;
const char *string;
if (*pstridx != 0)
/* This symbol has already been handled by an N_BINCL pass. */
continue;
type = sym[TYPEOFF];
if (type == 0)
{
/* Special type 0 stabs indicate the offset to the next
string table. We only copy the very first one. */
stroff = next_stroff;
next_stroff += bfd_get_32 (abfd, sym + 8);
if (pstring_offset)
*pstring_offset = next_stroff;
if (! first)
{
*pstridx = (bfd_size_type) -1;
++skip;
continue;
}
first = FALSE;
}
/* Store the string in the hash table, and record the index. */
symstroff = stroff + bfd_get_32 (abfd, sym + STRDXOFF);
if (symstroff >= stabstrsec->size)
{
(*_bfd_error_handler)
(_("%B(%A+0x%lx): Stabs entry has invalid string index."),
abfd, stabsec, (long) (sym - stabbuf));
bfd_set_error (bfd_error_bad_value);
goto error_return;
}
string = (char *) stabstrbuf + symstroff;
*pstridx = _bfd_stringtab_add (sinfo->strings, string, TRUE, TRUE);
/* An N_BINCL symbol indicates the start of the stabs entries
for a header file. We need to scan ahead to the next N_EINCL
symbol, ignoring nesting, adding up all the characters in the
symbol names, not including the file numbers in types (the
first number after an open parenthesis). */
if (type == (int) N_BINCL)
{
bfd_vma sum_chars;
bfd_vma num_chars;
bfd_vma buf_len = 0;
char * symb;
char * symb_rover;
int nest;
bfd_byte * incl_sym;
struct stab_link_includes_entry * incl_entry;
struct stab_link_includes_totals * t;
struct stab_excl_list * ne;
symb = symb_rover = NULL;
sum_chars = num_chars = 0;
nest = 0;
for (incl_sym = sym + STABSIZE;
incl_sym < symend;
incl_sym += STABSIZE)
{
int incl_type;
incl_type = incl_sym[TYPEOFF];
if (incl_type == 0)
break;
else if (incl_type == (int) N_EXCL)
continue;
else if (incl_type == (int) N_EINCL)
{
if (nest == 0)
break;
--nest;
}
else if (incl_type == (int) N_BINCL)
++nest;
else if (nest == 0)
{
const char *str;
str = ((char *) stabstrbuf
+ stroff
+ bfd_get_32 (abfd, incl_sym + STRDXOFF));
for (; *str != '\0'; str++)
{
if (num_chars >= buf_len)
{
buf_len += 32 * 1024;
symb = (char *) bfd_realloc_or_free (symb, buf_len);
if (symb == NULL)
goto error_return;
symb_rover = symb + num_chars;
}
* symb_rover ++ = * str;
sum_chars += *str;
num_chars ++;
if (*str == '(')
{
/* Skip the file number. */
++str;
while (ISDIGIT (*str))
++str;
--str;
}
}
}
}
BFD_ASSERT (num_chars == (bfd_vma) (symb_rover - symb));
/* If we have already included a header file with the same
value, then replaced this one with an N_EXCL symbol. */
incl_entry = (struct stab_link_includes_entry * )
bfd_hash_lookup (&sinfo->includes, string, TRUE, TRUE);
if (incl_entry == NULL)
goto error_return;
for (t = incl_entry->totals; t != NULL; t = t->next)
if (t->sum_chars == sum_chars
&& t->num_chars == num_chars
&& memcmp (t->symb, symb, num_chars) == 0)
break;
/* Record this symbol, so that we can set the value
correctly. */
amt = sizeof *ne;
ne = (struct stab_excl_list *) bfd_alloc (abfd, amt);
if (ne == NULL)
goto error_return;
ne->offset = sym - stabbuf;
ne->val = sum_chars;
ne->type = (int) N_BINCL;
ne->next = secinfo->excls;
secinfo->excls = ne;
if (t == NULL)
{
/* This is the first time we have seen this header file
with this set of stabs strings. */
t = (struct stab_link_includes_totals *)
bfd_hash_allocate (&sinfo->includes, sizeof *t);
if (t == NULL)
goto error_return;
t->sum_chars = sum_chars;
t->num_chars = num_chars;
/* Trim data down. */
t->symb = symb = (char *) bfd_realloc_or_free (symb, num_chars);
t->next = incl_entry->totals;
incl_entry->totals = t;
}
else
{
bfd_size_type *incl_pstridx;
/* We have seen this header file before. Tell the final
pass to change the type to N_EXCL. */
ne->type = (int) N_EXCL;
/* Free off superfluous symbols. */
free (symb);
/* Mark the skipped symbols. */
nest = 0;
for (incl_sym = sym + STABSIZE, incl_pstridx = pstridx + 1;
incl_sym < symend;
incl_sym += STABSIZE, ++incl_pstridx)
{
int incl_type;
incl_type = incl_sym[TYPEOFF];
if (incl_type == (int) N_EINCL)
{
if (nest == 0)
{
*incl_pstridx = (bfd_size_type) -1;
++skip;
break;
}
--nest;
}
else if (incl_type == (int) N_BINCL)
++nest;
else if (incl_type == (int) N_EXCL)
/* Keep existing exclusion marks. */
continue;
else if (nest == 0)
{
*incl_pstridx = (bfd_size_type) -1;
++skip;
}
}
}
}
}
free (stabbuf);
stabbuf = NULL;
free (stabstrbuf);
stabstrbuf = NULL;
/* We need to set the section sizes such that the linker will
compute the output section sizes correctly. We set the .stab
size to not include the entries we don't want. We set
SEC_EXCLUDE for the .stabstr section, so that it will be dropped
from the link. We record the size of the strtab in the first
.stabstr section we saw, and make sure we don't set SEC_EXCLUDE
for that section. */
stabsec->size = (count - skip) * STABSIZE;
if (stabsec->size == 0)
stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
stabstrsec->flags |= SEC_EXCLUDE | SEC_KEEP;
sinfo->stabstr->size = _bfd_stringtab_size (sinfo->strings);
/* Calculate the `cumulative_skips' array now that stabs have been
deleted for this section. */
if (skip != 0)
{
bfd_size_type i, offset;
bfd_size_type *pskips;
amt = count * sizeof (bfd_size_type);
secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt);
if (secinfo->cumulative_skips == NULL)
goto error_return;
pskips = secinfo->cumulative_skips;
pstridx = secinfo->stridxs;
offset = 0;
for (i = 0; i < count; i++, pskips++, pstridx++)
{
*pskips = offset;
if (*pstridx == (bfd_size_type) -1)
offset += STABSIZE;
}
BFD_ASSERT (offset != 0);
}
return TRUE;
error_return:
if (stabbuf != NULL)
free (stabbuf);
if (stabstrbuf != NULL)
free (stabstrbuf);
return FALSE;
}
/* This function is called for each input file before the stab
section is relocated. It discards stab entries for discarded
functions and variables. The function returns TRUE iff
any entries have been deleted.
*/
bfd_boolean
_bfd_discard_section_stabs (bfd *abfd,
asection *stabsec,
void * psecinfo,
bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *),
void * cookie)
{
bfd_size_type count, amt;
struct stab_section_info *secinfo;
bfd_byte *stabbuf = NULL;
bfd_byte *sym, *symend;
bfd_size_type skip;
bfd_size_type *pstridx;
int deleting;
if (stabsec->size == 0)
/* This file does not contain stabs debugging information. */
return FALSE;
if (stabsec->size % STABSIZE != 0)
/* Something is wrong with the format of these stab symbols.
Don't try to optimize them. */
return FALSE;
if ((stabsec->output_section != NULL
&& bfd_is_abs_section (stabsec->output_section)))
/* At least one of the sections is being discarded from the
link, so we should just ignore them. */
return FALSE;
/* We should have initialized our data in _bfd_link_stab_sections.
If there was some bizarre error reading the string sections, though,
we might not have. Bail rather than asserting. */
if (psecinfo == NULL)
return FALSE;
count = stabsec->rawsize / STABSIZE;
secinfo = (struct stab_section_info *) psecinfo;
/* Read the stabs information from abfd. */
if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf))
goto error_return;
/* Look through the stabs symbols and discard any information for
discarded functions. */
skip = 0;
deleting = -1;
symend = stabbuf + stabsec->rawsize;
for (sym = stabbuf, pstridx = secinfo->stridxs;
sym < symend;
sym += STABSIZE, ++pstridx)
{
int type;
if (*pstridx == (bfd_size_type) -1)
/* This stab was deleted in a previous pass. */
continue;
type = sym[TYPEOFF];
if (type == (int) N_FUN)
{
int strx = bfd_get_32 (abfd, sym + STRDXOFF);
if (strx == 0)
{
if (deleting)
{
skip++;
*pstridx = -1;
}
deleting = -1;
continue;
}
deleting = 0;
if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
deleting = 1;
}
if (deleting == 1)
{
*pstridx = -1;
skip++;
}
else if (deleting == -1)
{
/* Outside of a function. Check for deleted variables. */
if (type == (int) N_STSYM || type == (int) N_LCSYM)
if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
{
*pstridx = -1;
skip ++;
}
/* We should also check for N_GSYM entries which reference a
deleted global, but those are less harmful to debuggers
and would require parsing the stab strings. */
}
}
free (stabbuf);
stabbuf = NULL;
/* Shrink the stabsec as needed. */
stabsec->size -= skip * STABSIZE;
if (stabsec->size == 0)
stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
/* Recalculate the `cumulative_skips' array now that stabs have been
deleted for this section. */
if (skip != 0)
{
bfd_size_type i, offset;
bfd_size_type *pskips;
if (secinfo->cumulative_skips == NULL)
{
amt = count * sizeof (bfd_size_type);
secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt);
if (secinfo->cumulative_skips == NULL)
goto error_return;
}
pskips = secinfo->cumulative_skips;
pstridx = secinfo->stridxs;
offset = 0;
for (i = 0; i < count; i++, pskips++, pstridx++)
{
*pskips = offset;
if (*pstridx == (bfd_size_type) -1)
offset += STABSIZE;
}
BFD_ASSERT (offset != 0);
}
return skip > 0;
error_return:
if (stabbuf != NULL)
free (stabbuf);
return FALSE;
}
/* Write out the stab section. This is called with the relocated
contents. */
bfd_boolean
_bfd_write_section_stabs (bfd *output_bfd,
struct stab_info *sinfo,
asection *stabsec,
void * *psecinfo,
bfd_byte *contents)
{
struct stab_section_info *secinfo;
struct stab_excl_list *e;
bfd_byte *sym, *tosym, *symend;
bfd_size_type *pstridx;
secinfo = (struct stab_section_info *) *psecinfo;
if (secinfo == NULL)
return bfd_set_section_contents (output_bfd, stabsec->output_section,
contents, stabsec->output_offset,
stabsec->size);
/* Handle each N_BINCL entry. */
for (e = secinfo->excls; e != NULL; e = e->next)
{
bfd_byte *excl_sym;
BFD_ASSERT (e->offset < stabsec->rawsize);
excl_sym = contents + e->offset;
bfd_put_32 (output_bfd, e->val, excl_sym + VALOFF);
excl_sym[TYPEOFF] = e->type;
}
/* Copy over all the stabs symbols, omitting the ones we don't want,
and correcting the string indices for those we do want. */
tosym = contents;
symend = contents + stabsec->rawsize;
for (sym = contents, pstridx = secinfo->stridxs;
sym < symend;
sym += STABSIZE, ++pstridx)
{
if (*pstridx != (bfd_size_type) -1)
{
if (tosym != sym)
memcpy (tosym, sym, STABSIZE);
bfd_put_32 (output_bfd, *pstridx, tosym + STRDXOFF);
if (sym[TYPEOFF] == 0)
{
/* This is the header symbol for the stabs section. We
don't really need one, since we have merged all the
input stabs sections into one, but we generate one
for the benefit of readers which expect to see one. */
BFD_ASSERT (sym == contents);
bfd_put_32 (output_bfd, _bfd_stringtab_size (sinfo->strings),
tosym + VALOFF);
bfd_put_16 (output_bfd,
stabsec->output_section->size / STABSIZE - 1,
tosym + DESCOFF);
}
tosym += STABSIZE;
}
}
BFD_ASSERT ((bfd_size_type) (tosym - contents) == stabsec->size);
return bfd_set_section_contents (output_bfd, stabsec->output_section,
contents, (file_ptr) stabsec->output_offset,
stabsec->size);
}
/* Write out the .stabstr section. */
bfd_boolean
_bfd_write_stab_strings (bfd *output_bfd, struct stab_info *sinfo)
{
if (bfd_is_abs_section (sinfo->stabstr->output_section))
/* The section was discarded from the link. */
return TRUE;
BFD_ASSERT ((sinfo->stabstr->output_offset
+ _bfd_stringtab_size (sinfo->strings))
<= sinfo->stabstr->output_section->size);
if (bfd_seek (output_bfd,
(file_ptr) (sinfo->stabstr->output_section->filepos
+ sinfo->stabstr->output_offset),
SEEK_SET) != 0)
return FALSE;
if (! _bfd_stringtab_emit (output_bfd, sinfo->strings))
return FALSE;
/* We no longer need the stabs information. */
_bfd_stringtab_free (sinfo->strings);
bfd_hash_table_free (&sinfo->includes);
return TRUE;
}
/* Adjust an address in the .stab section. Given OFFSET within
STABSEC, this returns the new offset in the adjusted stab section,
or -1 if the address refers to a stab which has been removed. */
bfd_vma
_bfd_stab_section_offset (asection *stabsec,
void * psecinfo,
bfd_vma offset)
{
struct stab_section_info *secinfo;
secinfo = (struct stab_section_info *) psecinfo;
if (secinfo == NULL)
return offset;
if (offset >= stabsec->rawsize)
return offset - stabsec->rawsize + stabsec->size;
if (secinfo->cumulative_skips)
{
bfd_vma i;
i = offset / STABSIZE;
if (secinfo->stridxs [i] == (bfd_size_type) -1)
return (bfd_vma) -1;
return offset - secinfo->cumulative_skips [i];
}
return offset;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,210 @@
/* sysdep.h -- handle host dependencies for the BFD library
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2005, 2007, 2009
Free Software Foundation, Inc.
Written by Cygnus Support.
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. */
#ifndef BFD_SYSDEP_H
#define BFD_SYSDEP_H
#ifdef PACKAGE
#error sysdep.h must be included in lieu of config.h
#endif
#include "config.h"
#include "ansidecl.h"
#ifdef HAVE_STDDEF_H
#include <stddef.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#if !(defined(errno) || defined(_MSC_VER) && defined(_INC_ERRNO))
extern int errno;
#endif
#ifdef STRING_WITH_STRINGS
#include <string.h>
#include <strings.h>
#else
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#else
extern char *strchr ();
extern char *strrchr ();
#endif
#endif
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif /* HAVE_SYS_RESOURCE_H */
#ifdef USE_BINARY_FOPEN
#include "fopen-bin.h"
#else
#include "fopen-same.h"
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#else
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#endif
#ifndef O_RDONLY
#define O_RDONLY 0
#endif
#ifndef O_WRONLY
#define O_WRONLY 1
#endif
#ifndef O_RDWR
#define O_RDWR 2
#endif
#ifndef O_ACCMODE
#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif
#include "filenames.h"
#if !HAVE_DECL_FFS
extern int ffs (int);
#endif
#if !HAVE_DECL_FREE
extern void free ();
#endif
#if !HAVE_DECL_GETENV
extern char *getenv ();
#endif
#if !HAVE_DECL_MALLOC
extern PTR malloc ();
#endif
#if !HAVE_DECL_REALLOC
extern PTR realloc ();
#endif
#if !HAVE_DECL_STPCPY
extern char *stpcpy (char *__dest, const char *__src);
#endif
#if !HAVE_DECL_STRSTR
extern char *strstr ();
#endif
#ifdef HAVE_FTELLO
#if !HAVE_DECL_FTELLO
extern off_t ftello (FILE *stream);
#endif
#endif
#ifdef HAVE_FTELLO64
#if !HAVE_DECL_FTELLO64
extern off64_t ftello64 (FILE *stream);
#endif
#endif
#ifdef HAVE_FSEEKO
#if !HAVE_DECL_FSEEKO
extern int fseeko (FILE *stream, off_t offset, int whence);
#endif
#endif
#ifdef HAVE_FSEEKO64
#if !HAVE_DECL_FSEEKO64
extern int fseeko64 (FILE *stream, off64_t offset, int whence);
#endif
#endif
/* Define offsetof for those systems which lack it */
#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#ifdef ENABLE_NLS
#include <libintl.h>
/* Note the use of dgetext() and PACKAGE here, rather than gettext().
This is because the code in this directory is used to build a library which
will be linked with code in other directories to form programs. We want to
maintain a seperate translation file for this directory however, rather
than being forced to merge it with that of any program linked to libbfd.
This is a library, so it cannot depend on the catalog currently loaded.
In order to do this, we have to make sure that when we extract messages we
use the OPCODES domain rather than the domain of the program that included
the bfd library, (eg OBJDUMP). Hence we use dgettext (PACKAGE, String)
and define PACKAGE to be 'bfd'. (See the code in configure). */
#define _(String) dgettext (PACKAGE, 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
#endif /* ! defined (BFD_SYSDEP_H) */

File diff suppressed because it is too large Load Diff

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,375 @@
/* BFD back-end for verilog hex memory dump files.
Copyright 2009, 2010, 2011
Free Software Foundation, Inc.
Written by Anthony Green <green@moxielogic.com>
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. */
/* SUBSECTION
Verilog hex memory file handling
DESCRIPTION
Verilog hex memory files cannot hold anything but addresses
and data, so that's all that we implement.
The syntax of the text file is described in the IEEE standard
for Verilog. Briefly, the file contains two types of tokens:
data and optional addresses. The tokens are separated by
whitespace and comments. Comments may be single line or
multiline, using syntax similar to C++. Addresses are
specified by a leading "at" character (@) and are always
hexadecimal strings. Data and addresses may contain
underscore (_) characters.
If no address is specified, the data is assumed to start at
address 0. Similarly, if data exists before the first
specified address, then that data is assumed to start at
address 0.
EXAMPLE
@1000
01 ae 3f 45 12
DESCRIPTION
@1000 specifies the starting address for the memory data.
The following characters describe the 5 bytes at 0x1000. */
#include "sysdep.h"
#include "bfd.h"
#include "libbfd.h"
#include "libiberty.h"
#include "safe-ctype.h"
/* Macros for converting between hex and binary. */
static const char digs[] = "0123456789ABCDEF";
#define NIBBLE(x) hex_value(x)
#define HEX(buffer) ((NIBBLE ((buffer)[0])<<4) + NIBBLE ((buffer)[1]))
#define TOHEX(d, x) \
d[1] = digs[(x) & 0xf]; \
d[0] = digs[((x) >> 4) & 0xf];
/* When writing a verilog memory dump file, we write them in the order
in which they appear in memory. This structure is used to hold them
in memory. */
struct verilog_data_list_struct
{
struct verilog_data_list_struct *next;
bfd_byte * data;
bfd_vma where;
bfd_size_type size;
};
typedef struct verilog_data_list_struct verilog_data_list_type;
/* The verilog tdata information. */
typedef struct verilog_data_struct
{
verilog_data_list_type *head;
verilog_data_list_type *tail;
}
tdata_type;
static bfd_boolean
verilog_set_arch_mach (bfd *abfd, enum bfd_architecture arch, unsigned long mach)
{
if (arch != bfd_arch_unknown)
return bfd_default_set_arch_mach (abfd, arch, mach);
abfd->arch_info = & bfd_default_arch_struct;
return TRUE;
}
/* We have to save up all the outpu for a splurge before output. */
static bfd_boolean
verilog_set_section_contents (bfd *abfd,
sec_ptr section,
const void * location,
file_ptr offset,
bfd_size_type bytes_to_do)
{
tdata_type *tdata = abfd->tdata.verilog_data;
verilog_data_list_type *entry;
entry = (verilog_data_list_type *) bfd_alloc (abfd, sizeof (* entry));
if (entry == NULL)
return FALSE;
if (bytes_to_do
&& (section->flags & SEC_ALLOC)
&& (section->flags & SEC_LOAD))
{
bfd_byte *data;
data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do);
if (data == NULL)
return FALSE;
memcpy ((void *) data, location, (size_t) bytes_to_do);
entry->data = data;
entry->where = section->lma + offset;
entry->size = bytes_to_do;
/* Sort the records by address. Optimize for the common case of
adding a record to the end of the list. */
if (tdata->tail != NULL
&& entry->where >= tdata->tail->where)
{
tdata->tail->next = entry;
entry->next = NULL;
tdata->tail = entry;
}
else
{
verilog_data_list_type **look;
for (look = &tdata->head;
*look != NULL && (*look)->where < entry->where;
look = &(*look)->next)
;
entry->next = *look;
*look = entry;
if (entry->next == NULL)
tdata->tail = entry;
}
}
return TRUE;
}
static bfd_boolean
verilog_write_address (bfd *abfd, bfd_vma address)
{
char buffer[12];
char *dst = buffer;
bfd_size_type wrlen;
/* Write the address. */
*dst++ = '@';
TOHEX (dst, (address >> 24));
dst += 2;
TOHEX (dst, (address >> 16));
dst += 2;
TOHEX (dst, (address >> 8));
dst += 2;
TOHEX (dst, (address));
dst += 2;
*dst++ = '\r';
*dst++ = '\n';
wrlen = dst - buffer;
return bfd_bwrite ((void *) buffer, wrlen, abfd) == wrlen;
}
/* Write a record of type, of the supplied number of bytes. The
supplied bytes and length don't have a checksum. That's worked out
here. */
static bfd_boolean
verilog_write_record (bfd *abfd,
const bfd_byte *data,
const bfd_byte *end)
{
char buffer[48];
const bfd_byte *src = data;
char *dst = buffer;
bfd_size_type wrlen;
/* Write the data. */
for (src = data; src < end; src++)
{
TOHEX (dst, *src);
dst += 2;
*dst++ = ' ';
}
*dst++ = '\r';
*dst++ = '\n';
wrlen = dst - buffer;
return bfd_bwrite ((void *) buffer, wrlen, abfd) == wrlen;
}
static bfd_boolean
verilog_write_section (bfd *abfd,
tdata_type *tdata ATTRIBUTE_UNUSED,
verilog_data_list_type *list)
{
unsigned int octets_written = 0;
bfd_byte *location = list->data;
verilog_write_address (abfd, list->where);
while (octets_written < list->size)
{
unsigned int octets_this_chunk = list->size - octets_written;
if (octets_this_chunk > 16)
octets_this_chunk = 16;
if (! verilog_write_record (abfd,
location,
location + octets_this_chunk))
return FALSE;
octets_written += octets_this_chunk;
location += octets_this_chunk;
}
return TRUE;
}
static bfd_boolean
verilog_write_object_contents (bfd *abfd)
{
tdata_type *tdata = abfd->tdata.verilog_data;
verilog_data_list_type *list;
/* Now wander though all the sections provided and output them. */
list = tdata->head;
while (list != (verilog_data_list_type *) NULL)
{
if (! verilog_write_section (abfd, tdata, list))
return FALSE;
list = list->next;
}
return TRUE;
}
/* Initialize by filling in the hex conversion array. */
static void
verilog_init (void)
{
static bfd_boolean inited = FALSE;
if (! inited)
{
inited = TRUE;
hex_init ();
}
}
/* Set up the verilog tdata information. */
static bfd_boolean
verilog_mkobject (bfd *abfd)
{
tdata_type *tdata;
verilog_init ();
tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
if (tdata == NULL)
return FALSE;
abfd->tdata.verilog_data = tdata;
tdata->head = NULL;
tdata->tail = NULL;
return TRUE;
}
#define verilog_close_and_cleanup _bfd_generic_close_and_cleanup
#define verilog_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
#define verilog_new_section_hook _bfd_generic_new_section_hook
#define verilog_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
#define verilog_bfd_is_local_label_name bfd_generic_is_local_label_name
#define verilog_get_lineno _bfd_nosymbols_get_lineno
#define verilog_find_nearest_line _bfd_nosymbols_find_nearest_line
#define verilog_find_inliner_info _bfd_nosymbols_find_inliner_info
#define verilog_make_empty_symbol _bfd_generic_make_empty_symbol
#define verilog_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
#define verilog_read_minisymbols _bfd_generic_read_minisymbols
#define verilog_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
#define verilog_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
#define verilog_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
#define verilog_bfd_relax_section bfd_generic_relax_section
#define verilog_bfd_gc_sections bfd_generic_gc_sections
#define verilog_bfd_merge_sections bfd_generic_merge_sections
#define verilog_bfd_is_group_section bfd_generic_is_group_section
#define verilog_bfd_discard_group bfd_generic_discard_group
#define verilog_section_already_linked _bfd_generic_section_already_linked
#define verilog_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define verilog_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
#define verilog_bfd_link_add_symbols _bfd_generic_link_add_symbols
#define verilog_bfd_link_just_syms _bfd_generic_link_just_syms
#define verilog_bfd_final_link _bfd_generic_final_link
#define verilog_bfd_link_split_section _bfd_generic_link_split_section
const bfd_target verilog_vec =
{
"verilog", /* Name. */
bfd_target_verilog_flavour,
BFD_ENDIAN_UNKNOWN, /* Target byte order. */
BFD_ENDIAN_UNKNOWN, /* Target headers byte order. */
(HAS_RELOC | EXEC_P | /* Object flags. */
HAS_LINENO | HAS_DEBUG |
HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
(SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
| SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags. */
0, /* Leading underscore. */
' ', /* AR_pad_char. */
16, /* AR_max_namelen. */
0, /* match priority. */
bfd_getb64, bfd_getb_signed_64, bfd_putb64,
bfd_getb32, bfd_getb_signed_32, bfd_putb32,
bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */
bfd_getb64, bfd_getb_signed_64, bfd_putb64,
bfd_getb32, bfd_getb_signed_32, bfd_putb32,
bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Hdrs. */
{
_bfd_dummy_target,
_bfd_dummy_target,
_bfd_dummy_target,
_bfd_dummy_target,
},
{
bfd_false,
verilog_mkobject,
bfd_false,
bfd_false,
},
{ /* bfd_write_contents. */
bfd_false,
verilog_write_object_contents,
bfd_false,
bfd_false,
},
BFD_JUMP_TABLE_GENERIC (_bfd_generic),
BFD_JUMP_TABLE_COPY (_bfd_generic),
BFD_JUMP_TABLE_CORE (_bfd_nocore),
BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
BFD_JUMP_TABLE_WRITE (verilog),
BFD_JUMP_TABLE_LINK (_bfd_nolink),
BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
NULL,
NULL
};