X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Fbfd.c;h=5a23c5d690f406cbd8245cf3345273ff2b83bd18;hb=e98fe4f7b54cbdf29aef9287bbb1bea8801dd05a;hp=7d919da7c81faa063dfc35b8e7de0e703a841cc8;hpb=e98e6ec1117b83defce2b1ccce6fd4ec3877bbfb;p=binutils-gdb.git diff --git a/bfd/bfd.c b/bfd/bfd.c index 7d919da7c81..5a23c5d690f 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -1,5 +1,5 @@ /* Generic BFD library interface and support routines. - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -16,21 +16,18 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* $Id$ */ +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* SECTION <> - A BFD is has type <>; objects of this type are the - cornerstone of any application using <>. References - though the BFD and to data in the BFD give the entire BFD - functionality. + A BFD has type <>; objects of this type are the + cornerstone of any application using BFD. Using BFD + consists of making references though the BFD and to data in the BFD. - Here is the struct used to define the type <>. This - contains he major data about the file, and contains pointers + Here is the structure that defines the type <>. It + contains the major data about the file and pointers to the rest of the data. CODE_FRAGMENT @@ -41,22 +38,25 @@ CODE_FRAGMENT . CONST char *filename; . . {* A pointer to the target jump table. *} -. struct bfd_target *xvec; +. const struct bfd_target *xvec; . . {* To avoid dragging too many header files into every file that -. includes @file{bfd.h}, IOSTREAM has been declared as a "char +. includes `<>', IOSTREAM has been declared as a "char . *", and MTIME as a "long". Their correct types, to which they . are cast when used, are "FILE *" and "time_t". The iostream -. is the result of an fopen on the filename. *} -. char *iostream; +. is the result of an fopen on the filename. However, if the +. BFD_IN_MEMORY flag is set, then iostream is actually a pointer +. to a bfd_in_memory struct. *} +. PTR iostream; . -. {* Is the file being cached *} +. {* Is the file descriptor being cached? That is, can it be closed as +. needed, and re-opened when accessed later? *} . . boolean cacheable; . . {* Marks whether there was a default target specified when the -. BFD was opened. This is used to select what matching algorithm -. to use to chose the back end. *} +. BFD was opened. This is used to select which matching algorithm +. to use to choose the back end. *} . . boolean target_defaulted; . @@ -66,12 +66,11 @@ CODE_FRAGMENT . struct _bfd *lru_prev, *lru_next; . . {* When a file is closed by the caching routines, BFD retains -. state information on the file here: -. *} +. state information on the file here: *} . . file_ptr where; . -. {* and here:*} +. {* and here: (``once'' means at least once) *} . . boolean opened_once; . @@ -88,7 +87,7 @@ CODE_FRAGMENT . . int ifd; . -. {* The format which belongs to the BFD.*} +. {* The format which belongs to the BFD. (object, core, etc.) *} . . bfd_format format; . @@ -110,7 +109,7 @@ CODE_FRAGMENT . file_ptr origin; . . {* Remember when output has begun, to stop strange things -. happening. *} +. from happening. *} . boolean output_has_begun; . . {* Pointer to linked list of sections*} @@ -126,19 +125,26 @@ CODE_FRAGMENT . {* Used for input and output*} . unsigned int symcount; . -. {* Symbol table for output BFD*} +. {* Symbol table for output BFD (with symcount entries) *} . struct symbol_cache_entry **outsymbols; . . {* Pointer to structure which contains architecture information*} -. struct bfd_arch_info *arch_info; +. const struct bfd_arch_info *arch_info; . . {* Stuff only useful for archives:*} . PTR arelt_data; -. struct _bfd *my_archive; -. struct _bfd *next; -. struct _bfd *archive_head; +. struct _bfd *my_archive; {* The containing archive BFD. *} +. struct _bfd *next; {* The next BFD in the archive. *} +. struct _bfd *archive_head; {* The first BFD in the archive. *} . boolean has_armap; . +. {* A chain of BFD structures involved in a link. *} +. struct _bfd *link_next; +. +. {* A field used by _bfd_generic_link_add_archive_symbols. This will +. be used only for archive elements. *} +. int archive_pass; +. . {* Used by the back end to hold private data. *} . . union @@ -148,13 +154,28 @@ CODE_FRAGMENT . struct _oasys_data *oasys_obj_data; . struct _oasys_ar_data *oasys_ar_data; . struct coff_tdata *coff_obj_data; +. struct pe_tdata *pe_obj_data; +. struct xcoff_tdata *xcoff_obj_data; +. struct ecoff_tdata *ecoff_obj_data; . struct ieee_data_struct *ieee_data; . struct ieee_ar_data_struct *ieee_ar_data; . struct srec_data_struct *srec_data; -. struct elf_obj_tdata_struct *elf_obj_data; -. struct elf_core_tdata_struct *elf_core_data; +. struct ihex_data_struct *ihex_data; +. struct tekhex_data_struct *tekhex_data; +. struct elf_obj_tdata *elf_obj_data; +. struct nlm_obj_tdata *nlm_obj_data; . struct bout_data_struct *bout_data; . struct sun_core_struct *sun_core_data; +. struct trad_core_struct *trad_core_data; +. struct som_data_struct *som_data; +. struct hpux_core_struct *hpux_core_data; +. struct hppabsd_core_struct *hppabsd_core_data; +. struct sgi_core_struct *sgi_core_data; +. struct lynx_core_struct *lynx_core_data; +. struct osf_core_struct *osf_core_data; +. struct cisco_core_struct *cisco_core_data; +. struct versados_data_struct *versados_data; +. struct netbsd_core_struct *netbsd_core_data; . PTR any; . } tdata; . @@ -163,177 +184,354 @@ CODE_FRAGMENT . . {* Where all the allocated stuff under this BFD goes *} . struct obstack memory; -. -. asymbol **ld_symbols; .}; . */ #include "bfd.h" #include "sysdep.h" -#include "libbfd.h" -#undef strerror -extern char *strerror(); +#ifdef ANSI_PROTOTYPES +#include +#else +#include +#endif + +#include "bfdlink.h" +#include "libbfd.h" +#include "coff/internal.h" +#include "coff/sym.h" +#include "libcoff.h" +#include "libecoff.h" +#undef obj_symbols +#include "elf-bfd.h" + +#include + +/* provide storage for subsystem, stack and heap data which may have been + passed in on the command line. Ld puts this data into a bfd_link_info + struct which ultimately gets passed in to the bfd. When it arrives, copy + it to the following struct so that the data will be available in coffcode.h + where it is needed. The typedef's used are defined in bfd.h */ -CONST short _bfd_host_big_endian = 0x0100; - /* Accessing the above as (*(char*)&_bfd_host_big_endian), will - return 1 if the host is big-endian, 0 otherwise. - (assuming that a short is two bytes long!!! FIXME) - (See HOST_IS_BIG_ENDIAN_P in bfd.h.) */ -/** Error handling - o - Most functions return nonzero on success (check doc for - precise semantics); 0 or NULL on error. - o - Internal errors are documented by the value of bfd_error. - If that is system_call_error then check errno. - o - The easiest way to report this to the user is to use bfd_perror. +/* +SECTION + Error reporting + + Most BFD functions return nonzero on success (check their + individual documentation for precise semantics). On an error, + they call <> to set an error condition that callers + can check by calling <>. + If that returns <>, then check + <>. + + The easiest way to report a BFD error to the user is to + use <>. + +SUBSECTION + Type <> + + The values returned by <> are defined by the + enumerated type <>. + +CODE_FRAGMENT +. +.typedef enum bfd_error +.{ +. bfd_error_no_error = 0, +. bfd_error_system_call, +. bfd_error_invalid_target, +. bfd_error_wrong_format, +. bfd_error_invalid_operation, +. bfd_error_no_memory, +. bfd_error_no_symbols, +. bfd_error_no_armap, +. bfd_error_no_more_archived_files, +. bfd_error_malformed_archive, +. bfd_error_file_not_recognized, +. bfd_error_file_ambiguously_recognized, +. bfd_error_no_contents, +. bfd_error_nonrepresentable_section, +. bfd_error_no_debug_section, +. bfd_error_bad_value, +. bfd_error_file_truncated, +. bfd_error_file_too_big, +. bfd_error_invalid_error_code +.} bfd_error_type; +. */ -bfd_ec bfd_error = no_error; +#undef strerror +extern char *strerror(); + +static bfd_error_type bfd_error = bfd_error_no_error; -char *bfd_errmsgs[] = { "No error", +CONST char *CONST bfd_errmsgs[] = { + "No error", "System call error", - "Invalid target", + "Invalid bfd target", "File in wrong format", "Invalid operation", "Memory exhausted", "No symbols", - "No relocation info", + "Archive has no index; run ranlib to add one", "No more archived files", "Malformed archive", - "Symbol not found", "File format not recognized", "File format is ambiguous", "Section has no contents", "Nonrepresentable section on output", "Symbol needs debug section which does not exist", + "Bad value", + "File truncated", + "File too big", "#" }; -static -void -DEFUN(bfd_nonrepresentable_section,(abfd, name), - CONST bfd * CONST abfd AND - CONST char * CONST name) -{ - printf("bfd error writing file %s, format %s can't represent section %s\n", - abfd->filename, - abfd->xvec->name, - name); - exit(1); -} +/* +FUNCTION + bfd_get_error -static -void -DEFUN(bfd_undefined_symbol,(relent, seclet), - CONST arelent *relent AND - CONST struct bfd_seclet_struct *seclet) -{ - asymbol *symbol = *(relent->sym_ptr_ptr); - printf("bfd error relocating, symbol %s is undefined\n", - symbol->name); - exit(1); -} -static -void -DEFUN(bfd_reloc_value_truncated,(relent, seclet), - CONST arelent *relent AND - struct bfd_seclet_struct *seclet) +SYNOPSIS + bfd_error_type bfd_get_error (void); + +DESCRIPTION + Return the current BFD error condition. +*/ + +bfd_error_type +bfd_get_error () { - asymbol *symbol = *(relent->sym_ptr_ptr); - printf("bfd error relocating, value truncated\n"); - exit(1); + return bfd_error; } -static -void -DEFUN(bfd_reloc_is_dangerous,(relent, seclet), - CONST arelent *relent AND - CONST struct bfd_seclet_struct *seclet) + +/* +FUNCTION + bfd_set_error + +SYNOPSIS + void bfd_set_error (bfd_error_type error_tag); + +DESCRIPTION + Set the BFD error condition to be @var{error_tag}. +*/ + +void +bfd_set_error (error_tag) + bfd_error_type error_tag; { - asymbol *symbol = *(relent->sym_ptr_ptr); - printf("bfd error relocating, dangerous\n"); - exit(1); + bfd_error = error_tag; } -bfd_error_vector_type bfd_error_vector = - { - bfd_nonrepresentable_section , - bfd_undefined_symbol, - bfd_reloc_value_truncated, - bfd_reloc_is_dangerous, - }; +/* +FUNCTION + bfd_errmsg +SYNOPSIS + CONST char *bfd_errmsg (bfd_error_type error_tag); -char * +DESCRIPTION + Return a string describing the error @var{error_tag}, or + the system error if @var{error_tag} is <>. +*/ + +CONST char * bfd_errmsg (error_tag) - bfd_ec error_tag; + bfd_error_type error_tag; { #ifndef errno extern int errno; #endif - if (error_tag == system_call_error) + if (error_tag == bfd_error_system_call) return strerror (errno); - if ((((int)error_tag <(int) no_error) || - ((int)error_tag > (int)invalid_error_code))) - error_tag = invalid_error_code;/* sanity check */ + if ((((int)error_tag <(int) bfd_error_no_error) || + ((int)error_tag > (int)bfd_error_invalid_error_code))) + error_tag = bfd_error_invalid_error_code;/* sanity check */ return bfd_errmsgs [(int)error_tag]; } +/* +FUNCTION + bfd_perror -void bfd_default_error_trap(error_tag) -bfd_ec error_tag; -{ - printf("bfd assert fail (%s)\n", bfd_errmsg(error_tag)); -} +SYNOPSIS + void bfd_perror (CONST char *message); -void (*bfd_error_trap)() = bfd_default_error_trap; -void (*bfd_error_nonrepresentabltrap)() = bfd_default_error_trap; +DESCRIPTION + Print to the standard error stream a string describing the + last BFD error that occurred, or the last system error if + the last BFD error was a system call failure. If @var{message} + is non-NULL and non-empty, the error string printed is preceded + by @var{message}, a colon, and a space. It is followed by a newline. +*/ void -DEFUN(bfd_perror,(message), - CONST char *message) +bfd_perror (message) + CONST char *message; { - if (bfd_error == system_call_error) + if (bfd_get_error () == bfd_error_system_call) perror((char *)message); /* must be system error then... */ else { if (message == NULL || *message == '\0') - fprintf (stderr, "%s\n", bfd_errmsg (bfd_error)); + fprintf (stderr, "%s\n", bfd_errmsg (bfd_get_error ())); else - fprintf (stderr, "%s: %s\n", message, bfd_errmsg (bfd_error)); + fprintf (stderr, "%s: %s\n", message, bfd_errmsg (bfd_get_error ())); } } - -/** Symbols */ +/* +SUBSECTION + BFD error handler + + Some BFD functions want to print messages describing the + problem. They call a BFD error handler function. This + function may be overriden by the program. + + The BFD error handler acts like printf. + +CODE_FRAGMENT +. +.typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...)); +. +*/ + +/* The program name used when printing BFD error messages. */ + +static const char *_bfd_error_program_name; + +/* This is the default routine to handle BFD error messages. */ + +#ifdef ANSI_PROTOTYPES + +static void _bfd_default_error_handler PARAMS ((const char *s, ...)); + +static void +_bfd_default_error_handler (const char *s, ...) +{ + va_list p; + + if (_bfd_error_program_name != NULL) + fprintf (stderr, "%s: ", _bfd_error_program_name); + + va_start (p, s); + + vfprintf (stderr, s, p); + + va_end (p); + + fprintf (stderr, "\n"); +} + +#else /* ! defined (ANSI_PROTOTYPES) */ + +static void _bfd_default_error_handler (); + +static void +_bfd_default_error_handler (va_alist) + va_dcl +{ + va_list p; + const char *s; + + if (_bfd_error_program_name != NULL) + fprintf (stderr, "%s: ", _bfd_error_program_name); + + va_start (p); + + s = va_arg (p, const char *); + vfprintf (stderr, s, p); + + va_end (p); + + fprintf (stderr, "\n"); +} + +#endif /* ! defined (ANSI_PROTOTYPES) */ + +/* This is a function pointer to the routine which should handle BFD + error messages. It is called when a BFD routine encounters an + error for which it wants to print a message. Going through a + function pointer permits a program linked against BFD to intercept + the messages and deal with them itself. */ + +bfd_error_handler_type _bfd_error_handler = _bfd_default_error_handler; + +/* +FUNCTION + bfd_set_error_handler + +SYNOPSIS + bfd_error_handler_type bfd_set_error_handler (bfd_error_handler_type); + +DESCRIPTION + Set the BFD error handler function. Returns the previous + function. +*/ + +bfd_error_handler_type +bfd_set_error_handler (pnew) + bfd_error_handler_type pnew; +{ + bfd_error_handler_type pold; + + pold = _bfd_error_handler; + _bfd_error_handler = pnew; + return pold; +} + +/* +FUNCTION + bfd_set_error_program_name + +SYNOPSIS + void bfd_set_error_program_name (const char *); +DESCRIPTION + Set the program name to use when printing a BFD error. This + is printed before the error message followed by a colon and + space. The string must not be changed after it is passed to + this function. +*/ + +void +bfd_set_error_program_name (name) + const char *name; +{ + _bfd_error_program_name = name; +} + +/* +SECTION + Symbols +*/ /* FUNCTION bfd_get_reloc_upper_bound SYNOPSIS - unsigned int bfd_get_reloc_upper_bound(bfd *abfd, asection *sect); + long bfd_get_reloc_upper_bound(bfd *abfd, asection *sect); DESCRIPTION - This function return the number of bytes required to store the - relocation information associated with section <> - attached to bfd <> + Return the number of bytes required to store the + relocation information associated with section @var{sect} + attached to bfd @var{abfd}. If an error occurs, return -1. */ -unsigned int -DEFUN(bfd_get_reloc_upper_bound,(abfd, asect), - bfd *abfd AND - sec_ptr asect) +long +bfd_get_reloc_upper_bound (abfd, asect) + bfd *abfd; + sec_ptr asect; { if (abfd->format != bfd_object) { - bfd_error = invalid_operation; - return 0; + bfd_set_error (bfd_error_invalid_operation); + return -1; } return BFD_SEND (abfd, _get_reloc_upper_bound, (abfd, asect)); @@ -344,40 +542,66 @@ FUNCTION bfd_canonicalize_reloc SYNOPSIS - unsigned int bfd_canonicalize_reloc + long bfd_canonicalize_reloc (bfd *abfd, asection *sec, arelent **loc, asymbol **syms); DESCRIPTION - This function calls the back end associated with the open - <> and translates the external form of the relocation - information attached to <> into the internal canonical - form. The table is placed into memory at <>, which has + Call the back end associated with the open BFD + @var{abfd} and translate the external form of the relocation + information attached to @var{sec} into the internal canonical + form. Place the table into memory at @var{loc}, which has been preallocated, usually by a call to - <>. + <>. Returns the number of relocs, or + -1 on error. - The <> table is also needed for horrible internal magic + The @var{syms} table is also needed for horrible internal magic reasons. */ -unsigned int -DEFUN(bfd_canonicalize_reloc,(abfd, asect, location, symbols), - bfd *abfd AND - sec_ptr asect AND - arelent **location AND - asymbol **symbols) +long +bfd_canonicalize_reloc (abfd, asect, location, symbols) + bfd *abfd; + sec_ptr asect; + arelent **location; + asymbol **symbols; { - if (abfd->format != bfd_object) { - bfd_error = invalid_operation; - return 0; - } - return BFD_SEND (abfd, _bfd_canonicalize_reloc, - (abfd, asect, location, symbols)); + if (abfd->format != bfd_object) { + bfd_set_error (bfd_error_invalid_operation); + return -1; + } + return BFD_SEND (abfd, _bfd_canonicalize_reloc, + (abfd, asect, location, symbols)); } +/* +FUNCTION + bfd_set_reloc + +SYNOPSIS + void bfd_set_reloc + (bfd *abfd, asection *sec, arelent **rel, unsigned int count) + +DESCRIPTION + Set the relocation pointer and count within + section @var{sec} to the values @var{rel} and @var{count}. + The argument @var{abfd} is ignored. + +*/ +/*ARGSUSED*/ +void +bfd_set_reloc (ignore_abfd, asect, location, count) + bfd *ignore_abfd; + sec_ptr asect; + arelent **location; + unsigned int count; +{ + asect->orelocation = location; + asect->reloc_count = count; +} /* FUNCTION @@ -387,16 +611,15 @@ SYNOPSIS boolean bfd_set_file_flags(bfd *abfd, flagword flags); DESCRIPTION - This function attempts to set the flag word in the referenced - BFD structure to the value supplied. + Set the flag word in the BFD @var{abfd} to the value @var{flags}. Possible errors are: - o wrong_format - The target bfd was not of object format. - o invalid_operation - The target bfd was open for reading. - o invalid_operation - + o <> - The target bfd was not of object format. + o <> - The target bfd was open for reading. + o <> - The flag word contained a bit which was not applicable to the - type of file. eg, an attempt was made to set the D_PAGED bit - on a bfd format which does not support demand paging + type of file. E.g., an attempt was made to set the <> bit + on a BFD format which does not support demand paging. */ @@ -406,55 +629,30 @@ bfd_set_file_flags (abfd, flags) flagword flags; { if (abfd->format != bfd_object) { - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); return false; } if (bfd_read_p (abfd)) { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return false; } + bfd_get_file_flags (abfd) = flags; if ((flags & bfd_applicable_file_flags (abfd)) != flags) { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return false; } - bfd_get_file_flags (abfd) = flags; return true; } -/* -FUNCTION - bfd_set_reloc - -SYNOPSIS - void bfd_set_reloc - (bfd *abfd, asection *sec, arelent **rel, unsigned int count) - -DESCRIPTION - This function sets the relocation pointer and count within a - section to the supplied values. - -*/ - -void -bfd_set_reloc (ignore_abfd, asect, location, count) - bfd *ignore_abfd; - sec_ptr asect; - arelent **location; - unsigned int count; -{ - asect->orelocation = location; - asect->reloc_count = count; -} - void -bfd_assert(file, line) -char *file; -int line; +bfd_assert (file, line) + const char *file; + int line; { - printf("bfd assertion fail %s:%d\n",file,line); + (*_bfd_error_handler) ("bfd assertion fail %s:%d", file, line); } @@ -462,14 +660,14 @@ int line; FUNCTION bfd_set_start_address +SYNOPSIS + boolean bfd_set_start_address(bfd *abfd, bfd_vma vma); + DESCRIPTION - Marks the entry point of an output BFD. + Make @var{vma} the entry point of output BFD @var{abfd}. RETURNS Returns <> on success, <> otherwise. - -SYNOPSIS - boolean bfd_set_start_address(bfd *, bfd_vma); */ boolean @@ -484,14 +682,14 @@ bfd_vma vma; /* FUNCTION - The bfd_get_mtime function + bfd_get_mtime SYNOPSIS - long bfd_get_mtime(bfd *); + long bfd_get_mtime(bfd *abfd); DESCRIPTION - Return file modification time (as read from file system, or - from archive header for archive members). + Return the file modification time (as read from the file system, or + from the archive header for archive members). */ @@ -513,12 +711,286 @@ bfd_get_mtime (abfd) return buf.st_mtime; } +/* +FUNCTION + bfd_get_size + +SYNOPSIS + long 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 <> 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 quesion, "is the + size reasonable?". +*/ + +long +bfd_get_size (abfd) + bfd *abfd; +{ + FILE *fp; + struct stat buf; + + if ((abfd->flags & BFD_IN_MEMORY) != 0) + return ((struct bfd_in_memory *) abfd->iostream)->size; + + fp = bfd_cache_lookup (abfd); + if (0 != fstat (fileno (fp), &buf)) + return 0; + + return buf.st_size; +} + +/* +FUNCTION + bfd_get_gp_size + +SYNOPSIS + int bfd_get_gp_size(bfd *abfd); + +DESCRIPTION + Return the maximum size of objects to be optimized using the GP + register under MIPS ECOFF. This is typically set by the <<-G>> + argument to the compiler, assembler or linker. +*/ + +int +bfd_get_gp_size (abfd) + bfd *abfd; +{ + if (abfd->format == bfd_object) + { + if (abfd->xvec->flavour == bfd_target_ecoff_flavour) + return ecoff_data (abfd)->gp_size; + else if (abfd->xvec->flavour == bfd_target_elf_flavour) + return elf_gp_size (abfd); + } + return 0; +} + +/* +FUNCTION + bfd_set_gp_size + +SYNOPSIS + void bfd_set_gp_size(bfd *abfd, int i); + +DESCRIPTION + Set the maximum size of objects to be optimized using the GP + register under ECOFF or MIPS ELF. This is typically set by + the <<-G>> argument to the compiler, assembler or linker. +*/ + +void +bfd_set_gp_size (abfd, i) + bfd *abfd; + int i; +{ + /* Don't try to set GP size on an archive or core file! */ + if (abfd->format != bfd_object) + return; + if (abfd->xvec->flavour == bfd_target_ecoff_flavour) + ecoff_data (abfd)->gp_size = i; + else if (abfd->xvec->flavour == bfd_target_elf_flavour) + elf_gp_size (abfd) = i; +} + +/* Get the GP value. This is an internal function used by some of the + relocation special_function routines on targets which support a GP + register. */ + +bfd_vma +_bfd_get_gp_value (abfd) + bfd *abfd; +{ + if (abfd->format == bfd_object) + { + if (abfd->xvec->flavour == bfd_target_ecoff_flavour) + return ecoff_data (abfd)->gp; + else if (abfd->xvec->flavour == bfd_target_elf_flavour) + return elf_gp (abfd); + } + return 0; +} + +/* Set the GP value. */ + +void +_bfd_set_gp_value (abfd, v) + bfd *abfd; + bfd_vma v; +{ + if (abfd->format != bfd_object) + return; + if (abfd->xvec->flavour == bfd_target_ecoff_flavour) + ecoff_data (abfd)->gp = v; + else if (abfd->xvec->flavour == bfd_target_elf_flavour) + elf_gp (abfd) = v; +} + +/* +FUNCTION + bfd_scan_vma + +SYNOPSIS + bfd_vma bfd_scan_vma(CONST char *string, CONST char **end, int base); + +DESCRIPTION + Convert, like <>, a numerical expression + @var{string} into a <> integer, and return that integer. + (Though without as many bells and whistles as <>.) + The expression is assumed to be unsigned (i.e., positive). + If given a @var{base}, it is used as the base for conversion. + A base of 0 causes the function to interpret the string + in hex if a leading "0x" or "0X" is found, otherwise + in octal if a leading zero is found, otherwise in decimal. + + Overflow is not detected. +*/ + +bfd_vma +bfd_scan_vma (string, end, base) + CONST char *string; + CONST char **end; + int base; +{ + bfd_vma value; + int digit; + + /* Let the host do it if possible. */ + if (sizeof(bfd_vma) <= sizeof(unsigned long)) + return (bfd_vma) strtoul (string, (char **) end, base); + + /* A negative base makes no sense, and we only need to go as high as hex. */ + if ((base < 0) || (base > 16)) + return (bfd_vma) 0; + + if (base == 0) + { + if (string[0] == '0') + { + if ((string[1] == 'x') || (string[1] == 'X')) + base = 16; + /* XXX should we also allow "0b" or "0B" to set base to 2? */ + else + base = 8; + } + else + base = 10; + } + if ((base == 16) && + (string[0] == '0') && ((string[1] == 'x') || (string[1] == 'X'))) + string += 2; + /* XXX should we also skip over "0b" or "0B" if base is 2? */ + +/* Speed could be improved with a table like hex_value[] in gas. */ +#define HEX_VALUE(c) \ + (isxdigit(c) ? \ + (isdigit(c) ? \ + (c - '0') : \ + (10 + c - (islower(c) ? 'a' : 'A'))) : \ + 42) + + for (value = 0; (digit = HEX_VALUE(*string)) < base; string++) + { + value = value * base + digit; + } + + if (end) + *end = string; + + return value; +} + +/* +FUNCTION + bfd_copy_private_bfd_data + +SYNOPSIS + boolean bfd_copy_private_bfd_data(bfd *ibfd, bfd *obfd); + +DESCRIPTION + Copy private BFD information from the BFD @var{ibfd} to the + the BFD @var{obfd}. Return <> on success, <> on error. + Possible error returns are: + + o <> - + Not enough memory exists to create private data for @var{obfd}. + +.#define bfd_copy_private_bfd_data(ibfd, obfd) \ +. BFD_SEND (ibfd, _bfd_copy_private_bfd_data, \ +. (ibfd, obfd)) + +*/ + +/* +FUNCTION + bfd_merge_private_bfd_data + +SYNOPSIS + boolean bfd_merge_private_bfd_data(bfd *ibfd, bfd *obfd); + +DESCRIPTION + Merge private BFD information from the BFD @var{ibfd} to the + the output file BFD @var{obfd} when linking. Return <> + on success, <> on error. Possible error returns are: + + o <> - + Not enough memory exists to create private data for @var{obfd}. + +.#define bfd_merge_private_bfd_data(ibfd, obfd) \ +. BFD_SEND (ibfd, _bfd_merge_private_bfd_data, \ +. (ibfd, obfd)) + +*/ + +/* +FUNCTION + bfd_set_private_flags + +SYNOPSIS + boolean bfd_set_private_flags(bfd *abfd, flagword flags); + +DESCRIPTION + Set private BFD flag information in the BFD @var{abfd}. + Return <> on success, <> on error. Possible error + returns are: + + o <> - + Not enough memory exists to create private data for @var{obfd}. + +.#define bfd_set_private_flags(abfd, flags) \ +. BFD_SEND (abfd, _bfd_set_private_flags, \ +. (abfd, flags)) + +*/ + /* FUNCTION stuff DESCRIPTION - stuff which should be documented + Stuff which should be documented: .#define bfd_sizeof_headers(abfd, reloc) \ . BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc)) @@ -526,6 +998,7 @@ DESCRIPTION .#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \ . BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, sec, syms, off, file, func, line)) . +. {* Do these three do anything useful at all, for any back end? *} .#define bfd_debug_info_start(abfd) \ . BFD_SEND (abfd, _bfd_debug_info_start, (abfd)) . @@ -535,48 +1008,125 @@ DESCRIPTION .#define bfd_debug_info_accumulate(abfd, section) \ . BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section)) . +. .#define bfd_stat_arch_elt(abfd, stat) \ . BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat)) . -.#define bfd_coff_swap_aux_in(a,e,t,c,i) \ -. BFD_SEND (a, _bfd_coff_swap_aux_in, (a,e,t,c,i)) -. -.#define bfd_coff_swap_sym_in(a,e,i) \ -. BFD_SEND (a, _bfd_coff_swap_sym_in, (a,e,i)) -. -.#define bfd_coff_swap_lineno_in(a,e,i) \ -. BFD_SEND ( a, _bfd_coff_swap_lineno_in, (a,e,i)) +.#define bfd_update_armap_timestamp(abfd) \ +. BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd)) . .#define bfd_set_arch_mach(abfd, arch, mach)\ . BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach)) . -.#define bfd_coff_swap_reloc_out(abfd, i, o) \ -. BFD_SEND (abfd, _bfd_coff_swap_reloc_out, (abfd, i, o)) +.#define bfd_relax_section(abfd, section, link_info, again) \ +. BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again)) +. +.#define bfd_link_hash_table_create(abfd) \ +. BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd)) +. +.#define bfd_link_add_symbols(abfd, info) \ +. BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info)) +. +.#define bfd_final_link(abfd, info) \ +. BFD_SEND (abfd, _bfd_final_link, (abfd, info)) +. +.#define bfd_free_cached_info(abfd) \ +. BFD_SEND (abfd, _bfd_free_cached_info, (abfd)) . -.#define bfd_coff_swap_lineno_out(abfd, i, o) \ -. BFD_SEND (abfd, _bfd_coff_swap_lineno_out, (abfd, i, o)) +.#define bfd_get_dynamic_symtab_upper_bound(abfd) \ +. BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd)) . -.#define bfd_coff_swap_aux_out(abfd, i, t,c,o) \ -. BFD_SEND (abfd, _bfd_coff_swap_aux_out, (abfd, i,t,c, o)) +.#define bfd_print_private_bfd_data(abfd, file)\ +. BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file)) . -.#define bfd_coff_swap_sym_out(abfd, i,o) \ -. BFD_SEND (abfd, _bfd_coff_swap_sym_out, (abfd, i, o)) +.#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \ +. BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols)) . -.#define bfd_coff_swap_scnhdr_out(abfd, i,o) \ -. BFD_SEND (abfd, _bfd_coff_swap_scnhdr_out, (abfd, i, o)) +.#define bfd_get_dynamic_reloc_upper_bound(abfd) \ +. BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd)) . -.#define bfd_coff_swap_filehdr_out(abfd, i,o) \ -. BFD_SEND (abfd, _bfd_coff_swap_filehdr_out, (abfd, i, o)) +.#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \ +. BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms)) . -.#define bfd_coff_swap_aouthdr_out(abfd, i,o) \ -. BFD_SEND (abfd, _bfd_coff_swap_aouthdr_out, (abfd, i, o)) +.extern bfd_byte *bfd_get_relocated_section_contents +. PARAMS ((bfd *, struct bfd_link_info *, +. struct bfd_link_order *, bfd_byte *, +. boolean, asymbol **)); . -.#define bfd_get_relocated_section_contents(abfd, seclet) \ -. BFD_SEND (abfd, _bfd_get_relocated_section_contents, (abfd, seclet)) + */ +bfd_byte * +bfd_get_relocated_section_contents (abfd, link_info, link_order, data, + relocateable, symbols) + bfd *abfd; + struct bfd_link_info *link_info; + struct bfd_link_order *link_order; + bfd_byte *data; + boolean relocateable; + asymbol **symbols; +{ + bfd *abfd2; + bfd_byte *(*fn) PARAMS ((bfd *, struct bfd_link_info *, + struct bfd_link_order *, bfd_byte *, boolean, + asymbol **)); + + if (link_order->type == bfd_indirect_link_order) + { + abfd2 = link_order->u.indirect.section->owner; + if (abfd2 == 0) + abfd2 = abfd; + } + else + abfd2 = abfd; + fn = abfd2->xvec->_bfd_get_relocated_section_contents; + + return (*fn) (abfd, link_info, link_order, data, relocateable, symbols); +} + +/* Record information about an ELF program header. */ +boolean +bfd_record_phdr (abfd, type, flags_valid, flags, at_valid, at, + includes_filehdr, includes_phdrs, count, secs) + bfd *abfd; + unsigned long type; + boolean flags_valid; + flagword flags; + boolean at_valid; + bfd_vma at; + boolean includes_filehdr; + boolean includes_phdrs; + unsigned int count; + asection **secs; +{ + struct elf_segment_map *m, **pm; + if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) + return true; + m = ((struct elf_segment_map *) + bfd_alloc (abfd, + (sizeof (struct elf_segment_map) + + (count - 1) * sizeof (asection *)))); + if (m == NULL) + return false; + m->next = NULL; + m->p_type = type; + m->p_flags = flags; + m->p_paddr = at; + m->p_flags_valid = flags_valid; + m->p_paddr_valid = at_valid; + m->includes_filehdr = includes_filehdr; + m->includes_phdrs = includes_phdrs; + m->count = count; + if (count > 0) + memcpy (m->sections, secs, count * sizeof (asection *)); + + for (pm = &elf_tdata (abfd)->segment_map; *pm != NULL; pm = &(*pm)->next) + ; + *pm = m; + return true; +}