|
|
|
@ -1,5 +1,5 @@ |
|
|
|
/* Generic BFD library interface and support routines.
|
|
|
|
Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc. |
|
|
|
Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. |
|
|
|
Written by Cygnus Support. |
|
|
|
|
|
|
|
This file is part of BFD, the Binary File Descriptor library. |
|
|
|
@ -191,18 +191,56 @@ CODE_FRAGMENT |
|
|
|
#undef obj_symbols |
|
|
|
#include "libelf.h" |
|
|
|
|
|
|
|
#undef strerror |
|
|
|
extern char *strerror(); |
|
|
|
|
|
|
|
/*
|
|
|
|
SECTION |
|
|
|
Error reporting |
|
|
|
|
|
|
|
Most BFD functions return nonzero on success (check their |
|
|
|
individual documentation for precise semantics). On an error, |
|
|
|
they call <<bfd_set_error>> to set an error condition that callers |
|
|
|
can check by calling <<bfd_get_error>>. |
|
|
|
If that returns <<bfd_error_system_call>>, then check |
|
|
|
<<errno>>. |
|
|
|
|
|
|
|
/** 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. |
|
|
|
The easiest way to report a BFD error to the user is to |
|
|
|
use <<bfd_perror>>. |
|
|
|
|
|
|
|
SUBSECTION |
|
|
|
Type <<bfd_error_type>> |
|
|
|
|
|
|
|
The values returned by <<bfd_get_error>> are defined by the |
|
|
|
enumerated type <<bfd_error_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_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_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; |
|
|
|
|
|
|
|
CONST char *CONST bfd_errmsgs[] = { |
|
|
|
"No error", |
|
|
|
@ -224,40 +262,104 @@ CONST char *CONST bfd_errmsgs[] = { |
|
|
|
"#<Invalid error code>" |
|
|
|
}; |
|
|
|
|
|
|
|
/*
|
|
|
|
FUNCTION |
|
|
|
bfd_get_error |
|
|
|
|
|
|
|
SYNOPSIS |
|
|
|
bfd_error_type bfd_get_error (void); |
|
|
|
|
|
|
|
DESCRIPTION |
|
|
|
Return the current BFD error condition. |
|
|
|
*/ |
|
|
|
|
|
|
|
bfd_error_type |
|
|
|
bfd_get_error () |
|
|
|
{ |
|
|
|
return bfd_error; |
|
|
|
} |
|
|
|
|
|
|
|
/*
|
|
|
|
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; |
|
|
|
{ |
|
|
|
bfd_error = error_tag; |
|
|
|
} |
|
|
|
|
|
|
|
/*
|
|
|
|
FUNCTION |
|
|
|
bfd_errmsg |
|
|
|
|
|
|
|
SYNOPSIS |
|
|
|
CONST char *bfd_errmsg (bfd_error_type error_tag); |
|
|
|
|
|
|
|
DESCRIPTION |
|
|
|
Return a string describing the error @var{error_tag}, or |
|
|
|
the system error if @var{error_tag} is <<bfd_error_system_call>>. |
|
|
|
*/ |
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
SYNOPSIS |
|
|
|
void bfd_perror (CONST char *message); |
|
|
|
|
|
|
|
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 */ |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
SECTION |
|
|
|
Symbols |
|
|
|
*/ |
|
|
|
|
|
|
|
/*
|
|
|
|
FUNCTION |
|
|
|
@ -275,12 +377,12 @@ DESCRIPTION |
|
|
|
|
|
|
|
|
|
|
|
unsigned int |
|
|
|
DEFUN(bfd_get_reloc_upper_bound,(abfd, asect), |
|
|
|
bfd *abfd AND |
|
|
|
sec_ptr asect) |
|
|
|
bfd_get_reloc_upper_bound (abfd, asect) |
|
|
|
bfd *abfd; |
|
|
|
sec_ptr asect; |
|
|
|
{ |
|
|
|
if (abfd->format != bfd_object) { |
|
|
|
bfd_error = invalid_operation; |
|
|
|
bfd_set_error (bfd_error_invalid_operation); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
@ -312,14 +414,14 @@ DESCRIPTION |
|
|
|
|
|
|
|
*/ |
|
|
|
unsigned int |
|
|
|
DEFUN(bfd_canonicalize_reloc,(abfd, asect, location, symbols), |
|
|
|
bfd *abfd AND |
|
|
|
sec_ptr asect AND |
|
|
|
arelent **location AND |
|
|
|
asymbol **symbols) |
|
|
|
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; |
|
|
|
bfd_set_error (bfd_error_invalid_operation); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
return BFD_SEND (abfd, _bfd_canonicalize_reloc, |
|
|
|
@ -363,9 +465,9 @@ DESCRIPTION |
|
|
|
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 <<bfd_error_wrong_format>> - The target bfd was not of object format. |
|
|
|
o <<bfd_error_invalid_operation>> - The target bfd was open for reading. |
|
|
|
o <<bfd_error_invalid_operation>> - |
|
|
|
The flag word contained a bit which was not applicable to the |
|
|
|
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. |
|
|
|
@ -378,18 +480,18 @@ 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; |
|
|
|
} |
|
|
|
|
|
|
|
@ -524,10 +626,13 @@ int |
|
|
|
bfd_get_gp_size (abfd) |
|
|
|
bfd *abfd; |
|
|
|
{ |
|
|
|
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); |
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
|
@ -549,6 +654,9 @@ 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) |
|
|
|
@ -576,10 +684,10 @@ DESCRIPTION |
|
|
|
*/ |
|
|
|
|
|
|
|
bfd_vma |
|
|
|
DEFUN(bfd_scan_vma,(string, end, base), |
|
|
|
CONST char *string AND |
|
|
|
CONST char **end AND |
|
|
|
int base) |
|
|
|
bfd_scan_vma (string, end, base) |
|
|
|
CONST char *string; |
|
|
|
CONST char **end; |
|
|
|
int base; |
|
|
|
{ |
|
|
|
bfd_vma value; |
|
|
|
int digit; |
|
|
|
|