/* Generic BFD library interface and support routines.
- Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
SECTION
<<typedef bfd>>
- A BFD is has type <<bfd>>; objects of this type are the
- cornerstone of any application using <<libbfd>>. References
- though the BFD and to data in the BFD give the entire BFD
- functionality.
+ A BFD has type <<bfd>>; objects of this type are the
+ cornerstone of any application using <<libbfd>>. Using BFD
+ consists of making references though the BFD and to data in the BFD.
- Here is the struct used to define the type <<bfd>>. This
- contains the major data about the file, and contains pointers
+ Here is the structure that defines the type <<bfd>>. It
+ contains the major data about the file and pointers
to the rest of the data.
CODE_FRAGMENT
. is the result of an fopen on the filename. *}
. char *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;
.
. 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;
.
.
. int ifd;
.
-. {* The format which belongs to the BFD.*}
+. {* The format which belongs to the BFD. (object, core, etc.) *}
.
. bfd_format format;
.
. 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*}
. {* 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*}
.
. {* 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;
.
. {* Used by the back end to hold private data. *}
. struct _oasys_data *oasys_obj_data;
. struct _oasys_ar_data *oasys_ar_data;
. struct coff_tdata *coff_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 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 hppa_data_struct *hppa_data;
+. struct som_data_struct *som_data;
+. struct hpux_core_struct *hpux_core_data;
+. struct sgi_core_struct *sgi_core_data;
+. struct lynx_core_struct *lynx_core_data;
+. struct osf_core_struct *osf_core_data;
. PTR any;
. } tdata;
.
#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
+#include "coff/internal.h"
+#include "coff/sym.h"
+#include "libcoff.h"
+#include "libecoff.h"
+#undef obj_symbols
+#include "libelf.h"
#undef strerror
extern char *strerror();
-
-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.) */
-\f
/** Error handling
o - Most functions return nonzero on success (check doc for
precise semantics); 0 or NULL on error.
bfd_ec bfd_error = no_error;
-CONST char *CONST bfd_errmsgs[] = { "No error",
+CONST char *CONST bfd_errmsgs[] = {
+ "No error",
"System call error",
"Invalid target",
"File in wrong format",
"Nonrepresentable section on output",
"Symbol needs debug section which does not exist",
"Bad value",
+ "File truncated",
"#<Invalid error code>"
};
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);
+ fprintf(stderr,
+ "bfd error writing file %s, format %s can't represent section %s\n",
+ abfd->filename,
+ abfd->xvec->name,
+ name);
exit(1);
}
CONST struct bfd_seclet *seclet)
{
asymbol *symbol = *(relent->sym_ptr_ptr);
- printf("bfd error relocating, symbol %s is undefined\n",
- symbol->name);
+ fprintf(stderr, "bfd error relocating, symbol %s is undefined\n",
+ symbol->name);
exit(1);
}
/*ARGSUSED*/
CONST arelent *relent AND
struct bfd_seclet *seclet)
{
- printf("bfd error relocating, value truncated\n");
+ fprintf(stderr, "bfd error relocating, value truncated\n");
exit(1);
}
/*ARGSUSED*/
CONST arelent *relent AND
CONST struct bfd_seclet *seclet)
{
- printf("bfd error relocating, dangerous\n");
+ fprintf(stderr, "bfd error relocating, dangerous\n");
exit(1);
}
return bfd_errmsgs [(int)error_tag];
}
-
-void bfd_default_error_trap(error_tag)
-bfd_ec error_tag;
+void
+DEFUN (bfd_default_error_trap, (error_tag),
+ bfd_ec error_tag)
{
- printf("bfd assert fail (%s)\n", bfd_errmsg(error_tag));
+ fprintf(stderr, "bfd assert fail (%s)\n", bfd_errmsg(error_tag));
}
-void (*bfd_error_trap)() = bfd_default_error_trap;
-void (*bfd_error_nonrepresentabltrap)() = bfd_default_error_trap;
+void (*bfd_error_trap) PARAMS ((bfd_ec)) = bfd_default_error_trap;
+void (*bfd_error_nonrepresentabltrap) PARAMS ((bfd_ec)) = bfd_default_error_trap;
void
DEFUN(bfd_perror,(message),
unsigned int 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 <<sect>>
- attached to bfd <<abfd>>
+ Return the number of bytes required to store the
+ relocation information associated with section @var{sect}
+ attached to bfd @var{abfd}.
*/
asymbol **syms);
DESCRIPTION
- This function calls the back end associated with the open
- <<abfd>> and translates the external form of the relocation
- information attached to <<sec>> into the internal canonical
- form. The table is placed into memory at <<loc>>, 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
<<bfd_get_reloc_upper_bound>>.
- The <<syms>> table is also needed for horrible internal magic
+ The @var{syms} table is also needed for horrible internal magic
reasons.
arelent **location AND
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_error = invalid_operation;
+ return 0;
}
+ 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
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 -
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 D_PAGED bit
+ on a bfd format which does not support demand paging.
*/
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.
-
-*/
-/*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;
-}
-
void
bfd_assert(file, line)
char *file;
int line;
{
- printf("bfd assertion fail %s:%d\n",file,line);
+ fprintf(stderr, "bfd assertion fail %s:%d\n",file,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 <<true>> on success, <<false>> otherwise.
-
-SYNOPSIS
- boolean bfd_set_start_address(bfd *, bfd_vma);
*/
boolean
/*
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).
*/
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 <<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 quesion, "is the
+ size reasonable?".
+*/
+
+long
+bfd_get_size (abfd)
+ bfd *abfd;
+{
+ FILE *fp;
+ struct stat buf;
+
+ 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->xvec->flavour == bfd_target_ecoff_flavour)
+ return ecoff_data (abfd)->gp_size;
+ 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;
+{
+ 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;
+}
+
+/*
+FUNCTION
+ bfd_scan_vma
+
+SYNOPSIS
+ bfd_vma bfd_scan_vma(CONST char *string, CONST char **end, int base);
+
+DESCRIPTION
+ Convert, like <<strtoul>>, a numerical expression
+ @var{string} into a bfd_vma integer, and returns that integer.
+ (Though without as many bells and whistles as <<strtoul>>.)
+ 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
+DEFUN(bfd_scan_vma,(string, end, base),
+ CONST char *string AND
+ CONST char **end AND
+ 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, 0, 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
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))
.#define bfd_set_arch_mach(abfd, arch, mach)\
. BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
.
-.#define bfd_get_relocated_section_contents(abfd, seclet, data) \
-. BFD_SEND (abfd, _bfd_get_relocated_section_contents, (abfd, seclet, data))
+.#define bfd_get_relocated_section_contents(abfd, seclet, data, relocateable) \
+. BFD_SEND (abfd, _bfd_get_relocated_section_contents, (abfd, seclet, data, relocateable))
.
.#define bfd_relax_section(abfd, section, symbols) \
. BFD_SEND (abfd, _bfd_relax_section, (abfd, section, symbols))
+.
+.#define bfd_seclet_link(abfd, data, relocateable) \
+. BFD_SEND (abfd, _bfd_seclet_link, (abfd, data, relocateable))
*/
-
-
-
-
-
-