* bfd.c (enum bfd_error): Define bfd_error_no_armap.
(bfd_errmsgs): Add string for bfd_error_no_armap. * bfd-in2.h: Rebuild. * ecoff.c (ecoff_link_add_archive_symbols): If an archive has no armap, set bfd_error_no_armap rather than bfd_error_no_symbols. * elfcode.h (elf_link_add_archive_symbols): Likewise. * linker.c (_bfd_generic_link_add_archive_symbols): Likewise.
This commit is contained in:
parent
d07445c310
commit
9675c281af
|
@ -1919,6 +1919,7 @@ typedef enum bfd_error
|
|||
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,
|
||||
|
@ -2120,7 +2121,8 @@ enum bfd_flavour {
|
|||
bfd_target_srec_flavour,
|
||||
bfd_target_som_flavour,
|
||||
bfd_target_os9k_flavour,
|
||||
bfd_target_versados_flavour
|
||||
bfd_target_versados_flavour,
|
||||
bfd_target_msdos_flavour
|
||||
};
|
||||
|
||||
/* Forward declaration. */
|
||||
|
|
223
bfd/bfd.c
223
bfd/bfd.c
|
@ -169,6 +169,7 @@ CODE_FRAGMENT
|
|||
. 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;
|
||||
. PTR any;
|
||||
. } tdata;
|
||||
.
|
||||
|
@ -183,6 +184,13 @@ CODE_FRAGMENT
|
|||
|
||||
#include "bfd.h"
|
||||
#include "sysdep.h"
|
||||
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "bfdlink.h"
|
||||
#include "libbfd.h"
|
||||
#include "coff/internal.h"
|
||||
|
@ -192,6 +200,16 @@ CODE_FRAGMENT
|
|||
#undef obj_symbols
|
||||
#include "libelf.h"
|
||||
|
||||
|
||||
/* 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 */
|
||||
|
||||
enum bfd_link_subsystem NT_subsystem;
|
||||
|
||||
bfd_link_stack_heap NT_stack_heap;
|
||||
|
||||
/*
|
||||
SECTION
|
||||
|
@ -224,6 +242,7 @@ CODE_FRAGMENT
|
|||
. 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,
|
||||
|
@ -233,6 +252,7 @@ CODE_FRAGMENT
|
|||
. 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;
|
||||
.
|
||||
|
@ -251,6 +271,7 @@ CONST char *CONST bfd_errmsgs[] = {
|
|||
"Invalid operation",
|
||||
"Memory exhausted",
|
||||
"No symbols",
|
||||
"Archive has no index; run ranlib to add one",
|
||||
"No more archived files",
|
||||
"Malformed archive",
|
||||
"File format not recognized",
|
||||
|
@ -260,6 +281,7 @@ CONST char *CONST bfd_errmsgs[] = {
|
|||
"Symbol needs debug section which does not exist",
|
||||
"Bad value",
|
||||
"File truncated",
|
||||
"File too big",
|
||||
"#<Invalid error code>"
|
||||
};
|
||||
|
||||
|
@ -356,6 +378,126 @@ bfd_perror (message)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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
|
||||
|
@ -696,7 +838,7 @@ bfd_scan_vma (string, end, base)
|
|||
|
||||
/* Let the host do it if possible. */
|
||||
if (sizeof(bfd_vma) <= sizeof(unsigned long))
|
||||
return (bfd_vma) strtoul (string, end, base);
|
||||
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))
|
||||
|
@ -760,6 +902,48 @@ DESCRIPTION
|
|||
|
||||
*/
|
||||
|
||||
/*
|
||||
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 <<true>>
|
||||
on success, <<false>> on error. Possible error returns are:
|
||||
|
||||
o <<bfd_error_no_memory>> -
|
||||
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 <<true>> on success, <<false>> on error. Possible error
|
||||
returns are:
|
||||
|
||||
o <<bfd_error_no_memory>> -
|
||||
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
|
||||
|
@ -793,10 +977,6 @@ DESCRIPTION
|
|||
.#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, link_info, link_order, data, relocateable, symbols) \
|
||||
. BFD_SEND (abfd, _bfd_get_relocated_section_contents, \
|
||||
. (abfd, link_info, link_order, data, relocateable, symbols))
|
||||
.
|
||||
.#define bfd_relax_section(abfd, section, link_info, again) \
|
||||
. BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again))
|
||||
.
|
||||
|
@ -824,5 +1004,38 @@ DESCRIPTION
|
|||
.#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \
|
||||
. BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms))
|
||||
.
|
||||
.extern bfd_byte *bfd_get_relocated_section_contents
|
||||
. PARAMS ((bfd *, struct bfd_link_info *,
|
||||
. struct bfd_link_order *, bfd_byte *,
|
||||
. boolean, asymbol **));
|
||||
.
|
||||
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
758
bfd/ecoff.c
758
bfd/ecoff.c
|
@ -123,6 +123,8 @@ _bfd_ecoff_mkobject_hook (abfd, filehdr, aouthdr)
|
|||
ecoff->fprmask = internal_a->fprmask;
|
||||
if (internal_a->magic == ECOFF_AOUT_ZMAGIC)
|
||||
abfd->flags |= D_PAGED;
|
||||
else
|
||||
abfd->flags &=~ D_PAGED;
|
||||
}
|
||||
|
||||
/* It turns out that no special action is required by the MIPS or
|
||||
|
@ -408,201 +410,6 @@ _bfd_ecoff_styp_to_sec_flags (abfd, hdr, name)
|
|||
return sec_flags;
|
||||
}
|
||||
|
||||
/* Routines to swap auxiliary information in and out. I am assuming
|
||||
that the auxiliary information format is always going to be target
|
||||
independent. */
|
||||
|
||||
/* Swap in a type information record.
|
||||
BIGEND says whether AUX symbols are big-endian or little-endian; this
|
||||
info comes from the file header record (fh-fBigendian). */
|
||||
|
||||
void
|
||||
_bfd_ecoff_swap_tir_in (bigend, ext_copy, intern)
|
||||
int bigend;
|
||||
const struct tir_ext *ext_copy;
|
||||
TIR *intern;
|
||||
{
|
||||
struct tir_ext ext[1];
|
||||
|
||||
*ext = *ext_copy; /* Make it reasonable to do in-place. */
|
||||
|
||||
/* now the fun stuff... */
|
||||
if (bigend) {
|
||||
intern->fBitfield = 0 != (ext->t_bits1[0] & TIR_BITS1_FBITFIELD_BIG);
|
||||
intern->continued = 0 != (ext->t_bits1[0] & TIR_BITS1_CONTINUED_BIG);
|
||||
intern->bt = (ext->t_bits1[0] & TIR_BITS1_BT_BIG)
|
||||
>> TIR_BITS1_BT_SH_BIG;
|
||||
intern->tq4 = (ext->t_tq45[0] & TIR_BITS_TQ4_BIG)
|
||||
>> TIR_BITS_TQ4_SH_BIG;
|
||||
intern->tq5 = (ext->t_tq45[0] & TIR_BITS_TQ5_BIG)
|
||||
>> TIR_BITS_TQ5_SH_BIG;
|
||||
intern->tq0 = (ext->t_tq01[0] & TIR_BITS_TQ0_BIG)
|
||||
>> TIR_BITS_TQ0_SH_BIG;
|
||||
intern->tq1 = (ext->t_tq01[0] & TIR_BITS_TQ1_BIG)
|
||||
>> TIR_BITS_TQ1_SH_BIG;
|
||||
intern->tq2 = (ext->t_tq23[0] & TIR_BITS_TQ2_BIG)
|
||||
>> TIR_BITS_TQ2_SH_BIG;
|
||||
intern->tq3 = (ext->t_tq23[0] & TIR_BITS_TQ3_BIG)
|
||||
>> TIR_BITS_TQ3_SH_BIG;
|
||||
} else {
|
||||
intern->fBitfield = 0 != (ext->t_bits1[0] & TIR_BITS1_FBITFIELD_LITTLE);
|
||||
intern->continued = 0 != (ext->t_bits1[0] & TIR_BITS1_CONTINUED_LITTLE);
|
||||
intern->bt = (ext->t_bits1[0] & TIR_BITS1_BT_LITTLE)
|
||||
>> TIR_BITS1_BT_SH_LITTLE;
|
||||
intern->tq4 = (ext->t_tq45[0] & TIR_BITS_TQ4_LITTLE)
|
||||
>> TIR_BITS_TQ4_SH_LITTLE;
|
||||
intern->tq5 = (ext->t_tq45[0] & TIR_BITS_TQ5_LITTLE)
|
||||
>> TIR_BITS_TQ5_SH_LITTLE;
|
||||
intern->tq0 = (ext->t_tq01[0] & TIR_BITS_TQ0_LITTLE)
|
||||
>> TIR_BITS_TQ0_SH_LITTLE;
|
||||
intern->tq1 = (ext->t_tq01[0] & TIR_BITS_TQ1_LITTLE)
|
||||
>> TIR_BITS_TQ1_SH_LITTLE;
|
||||
intern->tq2 = (ext->t_tq23[0] & TIR_BITS_TQ2_LITTLE)
|
||||
>> TIR_BITS_TQ2_SH_LITTLE;
|
||||
intern->tq3 = (ext->t_tq23[0] & TIR_BITS_TQ3_LITTLE)
|
||||
>> TIR_BITS_TQ3_SH_LITTLE;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Swap out a type information record.
|
||||
BIGEND says whether AUX symbols are big-endian or little-endian; this
|
||||
info comes from the file header record (fh-fBigendian). */
|
||||
|
||||
void
|
||||
_bfd_ecoff_swap_tir_out (bigend, intern_copy, ext)
|
||||
int bigend;
|
||||
const TIR *intern_copy;
|
||||
struct tir_ext *ext;
|
||||
{
|
||||
TIR intern[1];
|
||||
|
||||
*intern = *intern_copy; /* Make it reasonable to do in-place. */
|
||||
|
||||
/* now the fun stuff... */
|
||||
if (bigend) {
|
||||
ext->t_bits1[0] = ((intern->fBitfield ? TIR_BITS1_FBITFIELD_BIG : 0)
|
||||
| (intern->continued ? TIR_BITS1_CONTINUED_BIG : 0)
|
||||
| ((intern->bt << TIR_BITS1_BT_SH_BIG)
|
||||
& TIR_BITS1_BT_BIG));
|
||||
ext->t_tq45[0] = (((intern->tq4 << TIR_BITS_TQ4_SH_BIG)
|
||||
& TIR_BITS_TQ4_BIG)
|
||||
| ((intern->tq5 << TIR_BITS_TQ5_SH_BIG)
|
||||
& TIR_BITS_TQ5_BIG));
|
||||
ext->t_tq01[0] = (((intern->tq0 << TIR_BITS_TQ0_SH_BIG)
|
||||
& TIR_BITS_TQ0_BIG)
|
||||
| ((intern->tq1 << TIR_BITS_TQ1_SH_BIG)
|
||||
& TIR_BITS_TQ1_BIG));
|
||||
ext->t_tq23[0] = (((intern->tq2 << TIR_BITS_TQ2_SH_BIG)
|
||||
& TIR_BITS_TQ2_BIG)
|
||||
| ((intern->tq3 << TIR_BITS_TQ3_SH_BIG)
|
||||
& TIR_BITS_TQ3_BIG));
|
||||
} else {
|
||||
ext->t_bits1[0] = ((intern->fBitfield ? TIR_BITS1_FBITFIELD_LITTLE : 0)
|
||||
| (intern->continued ? TIR_BITS1_CONTINUED_LITTLE : 0)
|
||||
| ((intern->bt << TIR_BITS1_BT_SH_LITTLE)
|
||||
& TIR_BITS1_BT_LITTLE));
|
||||
ext->t_tq45[0] = (((intern->tq4 << TIR_BITS_TQ4_SH_LITTLE)
|
||||
& TIR_BITS_TQ4_LITTLE)
|
||||
| ((intern->tq5 << TIR_BITS_TQ5_SH_LITTLE)
|
||||
& TIR_BITS_TQ5_LITTLE));
|
||||
ext->t_tq01[0] = (((intern->tq0 << TIR_BITS_TQ0_SH_LITTLE)
|
||||
& TIR_BITS_TQ0_LITTLE)
|
||||
| ((intern->tq1 << TIR_BITS_TQ1_SH_LITTLE)
|
||||
& TIR_BITS_TQ1_LITTLE));
|
||||
ext->t_tq23[0] = (((intern->tq2 << TIR_BITS_TQ2_SH_LITTLE)
|
||||
& TIR_BITS_TQ2_LITTLE)
|
||||
| ((intern->tq3 << TIR_BITS_TQ3_SH_LITTLE)
|
||||
& TIR_BITS_TQ3_LITTLE));
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Swap in a relative symbol record. BIGEND says whether it is in
|
||||
big-endian or little-endian format.*/
|
||||
|
||||
void
|
||||
_bfd_ecoff_swap_rndx_in (bigend, ext_copy, intern)
|
||||
int bigend;
|
||||
const struct rndx_ext *ext_copy;
|
||||
RNDXR *intern;
|
||||
{
|
||||
struct rndx_ext ext[1];
|
||||
|
||||
*ext = *ext_copy; /* Make it reasonable to do in-place. */
|
||||
|
||||
/* now the fun stuff... */
|
||||
if (bigend) {
|
||||
intern->rfd = (ext->r_bits[0] << RNDX_BITS0_RFD_SH_LEFT_BIG)
|
||||
| ((ext->r_bits[1] & RNDX_BITS1_RFD_BIG)
|
||||
>> RNDX_BITS1_RFD_SH_BIG);
|
||||
intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_BIG)
|
||||
<< RNDX_BITS1_INDEX_SH_LEFT_BIG)
|
||||
| (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_BIG)
|
||||
| (ext->r_bits[3] << RNDX_BITS3_INDEX_SH_LEFT_BIG);
|
||||
} else {
|
||||
intern->rfd = (ext->r_bits[0] << RNDX_BITS0_RFD_SH_LEFT_LITTLE)
|
||||
| ((ext->r_bits[1] & RNDX_BITS1_RFD_LITTLE)
|
||||
<< RNDX_BITS1_RFD_SH_LEFT_LITTLE);
|
||||
intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_LITTLE)
|
||||
>> RNDX_BITS1_INDEX_SH_LITTLE)
|
||||
| (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_LITTLE)
|
||||
| ((unsigned int) ext->r_bits[3]
|
||||
<< RNDX_BITS3_INDEX_SH_LEFT_LITTLE);
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Swap out a relative symbol record. BIGEND says whether it is in
|
||||
big-endian or little-endian format.*/
|
||||
|
||||
void
|
||||
_bfd_ecoff_swap_rndx_out (bigend, intern_copy, ext)
|
||||
int bigend;
|
||||
const RNDXR *intern_copy;
|
||||
struct rndx_ext *ext;
|
||||
{
|
||||
RNDXR intern[1];
|
||||
|
||||
*intern = *intern_copy; /* Make it reasonable to do in-place. */
|
||||
|
||||
/* now the fun stuff... */
|
||||
if (bigend) {
|
||||
ext->r_bits[0] = intern->rfd >> RNDX_BITS0_RFD_SH_LEFT_BIG;
|
||||
ext->r_bits[1] = (((intern->rfd << RNDX_BITS1_RFD_SH_BIG)
|
||||
& RNDX_BITS1_RFD_BIG)
|
||||
| ((intern->index >> RNDX_BITS1_INDEX_SH_LEFT_BIG)
|
||||
& RNDX_BITS1_INDEX_BIG));
|
||||
ext->r_bits[2] = intern->index >> RNDX_BITS2_INDEX_SH_LEFT_BIG;
|
||||
ext->r_bits[3] = intern->index >> RNDX_BITS3_INDEX_SH_LEFT_BIG;
|
||||
} else {
|
||||
ext->r_bits[0] = intern->rfd >> RNDX_BITS0_RFD_SH_LEFT_LITTLE;
|
||||
ext->r_bits[1] = (((intern->rfd >> RNDX_BITS1_RFD_SH_LEFT_LITTLE)
|
||||
& RNDX_BITS1_RFD_LITTLE)
|
||||
| ((intern->index << RNDX_BITS1_INDEX_SH_LITTLE)
|
||||
& RNDX_BITS1_INDEX_LITTLE));
|
||||
ext->r_bits[2] = intern->index >> RNDX_BITS2_INDEX_SH_LEFT_LITTLE;
|
||||
ext->r_bits[3] = intern->index >> RNDX_BITS3_INDEX_SH_LEFT_LITTLE;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Read in the symbolic header for an ECOFF object file. */
|
||||
|
||||
static boolean
|
||||
|
@ -2002,164 +1809,6 @@ _bfd_ecoff_canonicalize_reloc (abfd, section, relptr, symbols)
|
|||
return section->reloc_count;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cmp_fdrtab_entry (leftp, rightp)
|
||||
const void *leftp, *rightp;
|
||||
{
|
||||
const struct ecoff_fdrtab_entry *lp = leftp;
|
||||
const struct ecoff_fdrtab_entry *rp = rightp;
|
||||
|
||||
if (lp->base_addr < rp->base_addr)
|
||||
return -1;
|
||||
if (lp->base_addr > rp->base_addr)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Each file descriptor (FDR) has a memory address, to simplify
|
||||
looking up an FDR by address, we build a table covering all FDRs
|
||||
that have a least one procedure descriptor in them. The final
|
||||
table will be sorted by address so we can look it up via binary
|
||||
search. */
|
||||
static boolean
|
||||
mk_fdrtab (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info;
|
||||
const struct ecoff_debug_swap * const debug_swap
|
||||
= &ecoff_backend (abfd)->debug_swap;
|
||||
struct ecoff_fdrtab_entry *tab;
|
||||
FDR *fdr_ptr;
|
||||
FDR *fdr_start;
|
||||
FDR *fdr_end;
|
||||
boolean stabs;
|
||||
long len;
|
||||
|
||||
/* Make sure we have the FDR's. */
|
||||
if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, debug_info)
|
||||
|| bfd_get_symcount (abfd) == 0)
|
||||
return false;
|
||||
|
||||
fdr_start = debug_info->fdr;
|
||||
fdr_end = fdr_start + debug_info->symbolic_header.ifdMax;
|
||||
|
||||
/* First, let's see how long the table needs to be: */
|
||||
for (len = 0, fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++)
|
||||
{
|
||||
if (fdr_ptr->cpd == 0) /* skip FDRs that have no PDRs */
|
||||
continue;
|
||||
++len;
|
||||
}
|
||||
|
||||
/* Now, create and fill in the table: */
|
||||
|
||||
ecoff_data (abfd)->fdrtab = (struct ecoff_fdrtab_entry*)
|
||||
bfd_zalloc (abfd,len * sizeof (struct ecoff_fdrtab_entry));
|
||||
if (ecoff_data (abfd)->fdrtab == NULL)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
return false;
|
||||
}
|
||||
ecoff_data (abfd)->fdrtab_len = len;
|
||||
|
||||
tab = ecoff_data (abfd)->fdrtab;
|
||||
for (fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++)
|
||||
{
|
||||
if (fdr_ptr->cpd == 0)
|
||||
continue;
|
||||
|
||||
/* Check whether this file has stabs debugging information. In
|
||||
a file with stabs debugging information, the second local
|
||||
symbol is named @stabs. */
|
||||
stabs = false;
|
||||
if (fdr_ptr->csym >= 2)
|
||||
{
|
||||
char *sym_ptr;
|
||||
SYMR sym;
|
||||
|
||||
sym_ptr = ((char *) debug_info->external_sym
|
||||
+ (fdr_ptr->isymBase + 1)*debug_swap->external_sym_size);
|
||||
(*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym);
|
||||
if (strcmp (debug_info->ss + fdr_ptr->issBase + sym.iss,
|
||||
STABS_SYMBOL) == 0)
|
||||
stabs = true;
|
||||
}
|
||||
|
||||
if (!stabs)
|
||||
{
|
||||
bfd_size_type external_pdr_size;
|
||||
char *pdr_ptr;
|
||||
PDR pdr;
|
||||
|
||||
external_pdr_size = debug_swap->external_pdr_size;
|
||||
|
||||
pdr_ptr = ((char *) debug_info->external_pdr
|
||||
+ fdr_ptr->ipdFirst * external_pdr_size);
|
||||
(*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
|
||||
/* The address of the first PDR is the offset of that
|
||||
procedure relative to the beginning of file FDR. */
|
||||
tab->base_addr = fdr_ptr->adr - pdr.adr;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXX I don't know about stabs, so this is a guess
|
||||
(davidm@cs.arizona.edu): */
|
||||
tab->base_addr = fdr_ptr->adr;
|
||||
}
|
||||
tab->fdr = fdr_ptr;
|
||||
++tab;
|
||||
}
|
||||
/* Finally, the table is sorted in increasing memory-address order.
|
||||
The table is mostly sorted already, but there are cases (e.g.,
|
||||
static functions in include files), where this does not hold.
|
||||
Use "odump -PFv" to verify... */
|
||||
qsort((char*) ecoff_data (abfd)->fdrtab, len,
|
||||
sizeof(struct ecoff_fdrtab_entry), cmp_fdrtab_entry);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Return index of first FDR that covers to OFFSET. */
|
||||
static long
|
||||
lookup (abfd, offset)
|
||||
bfd *abfd;
|
||||
bfd_vma offset;
|
||||
{
|
||||
long low, high, len;
|
||||
long mid = -1;
|
||||
struct ecoff_fdrtab_entry *tab;
|
||||
|
||||
len = ecoff_data(abfd)->fdrtab_len;
|
||||
if (!len)
|
||||
return -1;
|
||||
|
||||
tab = ecoff_data(abfd)->fdrtab;
|
||||
for (low = 0, high = len - 1 ; low != high ;)
|
||||
{
|
||||
mid = (high + low) / 2;
|
||||
if (offset >= tab[mid].base_addr && offset < tab[mid + 1].base_addr)
|
||||
goto find_min;
|
||||
|
||||
if (tab[mid].base_addr > offset)
|
||||
high = mid;
|
||||
else
|
||||
low = mid + 1;
|
||||
}
|
||||
++mid;
|
||||
|
||||
/* last entry is catch-all for all higher addresses: */
|
||||
if (offset < tab[mid].base_addr)
|
||||
return -1;
|
||||
|
||||
find_min:
|
||||
|
||||
while (mid > 0 && tab[mid - 1].base_addr == tab[mid].base_addr)
|
||||
--mid;
|
||||
|
||||
return mid;
|
||||
}
|
||||
|
||||
/* Provided a BFD, a section and an offset into the section, calculate
|
||||
and return the name of the source file and the line nearest to the
|
||||
wanted location. */
|
||||
|
@ -2179,395 +1828,37 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
|
|||
const struct ecoff_debug_swap * const debug_swap
|
||||
= &ecoff_backend (abfd)->debug_swap;
|
||||
struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info;
|
||||
struct ecoff_fdrtab_entry *tab;
|
||||
boolean stabs;
|
||||
FDR *fdr_ptr;
|
||||
int i;
|
||||
struct ecoff_find_line *line_info;
|
||||
|
||||
offset += section->vma;
|
||||
/* If we're not in the .text section, we don't have any line
|
||||
numbers. */
|
||||
if (strcmp (section->name, _TEXT) != 0
|
||||
|| offset < ecoff_data (abfd)->text_start
|
||||
|| offset >= ecoff_data (abfd)->text_end)
|
||||
return false;
|
||||
/* Build FDR table (sorted by object file's base-address) if we
|
||||
don't have it already. */
|
||||
if (!ecoff_data (abfd)->fdrtab && !mk_fdrtab (abfd))
|
||||
|
||||
/* Make sure we have the FDR's. */
|
||||
if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, debug_info)
|
||||
|| bfd_get_symcount (abfd) == 0)
|
||||
return false;
|
||||
tab = ecoff_data (abfd)->fdrtab;
|
||||
|
||||
i = lookup(abfd, offset); /* find first FDR for address OFFSET */
|
||||
if (i < 0)
|
||||
return false; /* no FDR, no fun... */
|
||||
fdr_ptr = tab[i].fdr;
|
||||
|
||||
/* Check whether this file has stabs debugging information. In a
|
||||
file with stabs debugging information, the second local symbol is
|
||||
named @stabs. */
|
||||
stabs = false;
|
||||
if (fdr_ptr->csym >= 2)
|
||||
if (ecoff_data (abfd)->find_line_info == NULL)
|
||||
{
|
||||
char *sym_ptr;
|
||||
SYMR sym;
|
||||
|
||||
sym_ptr = ((char *) debug_info->external_sym
|
||||
+ (fdr_ptr->isymBase + 1) * debug_swap->external_sym_size);
|
||||
(*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym);
|
||||
if (strcmp (debug_info->ss + fdr_ptr->issBase + sym.iss,
|
||||
STABS_SYMBOL) == 0)
|
||||
stabs = true;
|
||||
}
|
||||
|
||||
if (!stabs)
|
||||
{
|
||||
bfd_size_type external_pdr_size;
|
||||
char *pdr_ptr;
|
||||
char *best_pdr = NULL;
|
||||
FDR *best_fdr;
|
||||
bfd_vma best_dist = ~0;
|
||||
PDR pdr;
|
||||
unsigned char *line_ptr;
|
||||
unsigned char *line_end;
|
||||
int lineno;
|
||||
/* This file uses ECOFF debugging information. Each FDR has a
|
||||
list of procedure descriptors (PDR). The address in the FDR
|
||||
is the absolute address of the first procedure. The address
|
||||
in the first PDR gives the offset of that procedure relative
|
||||
to the object file's base-address. The addresses in
|
||||
subsequent PDRs specify each procedure's address relative to
|
||||
the object file's base-address. To make things more juicy,
|
||||
whenever the PROF bit in the PDR is set, the real entry point
|
||||
of the procedure may be 16 bytes below what would normally be
|
||||
the procedure's entry point. Instead, DEC came up with a
|
||||
wicked scheme to create profiled libraries "on the fly":
|
||||
instead of shipping a regular and a profiled version of each
|
||||
library, they insert 16 bytes of unused space in front of
|
||||
each procedure and set the "prof" bit in the PDR to indicate
|
||||
that there is a gap there (this is done automagically by "as"
|
||||
when option "-pg" is specified). Thus, normally, you link
|
||||
against such a library and, except for lots of 16 byte gaps
|
||||
between functions, things will behave as usual. However,
|
||||
when invoking "ld" with option "-pg", it will fill those gaps
|
||||
with code that calls mcount(). It then moves the function's
|
||||
entry point down by 16 bytes, and out pops a binary that has
|
||||
all functions profiled.
|
||||
|
||||
NOTE: Neither FDRs nor PDRs are strictly sorted in memory
|
||||
order. For example, when including header-files that
|
||||
define functions, the FDRs follow behind the including
|
||||
file, even though their code may have been generated at
|
||||
a lower address. File coff-alpha.c from libbfd
|
||||
illustrates this (use "odump -PFv" to look at a file's
|
||||
FDR/PDR). Similarly, PDRs are sometimes out of order
|
||||
as well. An example of this is OSF/1 v3.0 libc's
|
||||
malloc.c. I'm not sure why this happens, but it could
|
||||
be due to optimizations that reorder a function's
|
||||
position within an object-file.
|
||||
|
||||
Strategy:
|
||||
|
||||
On the first call to this function, we build a table of FDRs
|
||||
that is sorted by the base-address of the object-file the FDR
|
||||
is referring to. Notice that each object-file may contain
|
||||
code from multiple source files (e.g., due to code defined in
|
||||
include files). Thus, for any given base-address, there may
|
||||
be multiple FDRs (but this case is, fortunately, uncommon).
|
||||
lookup(addr) guarantees to return the first FDR that applies
|
||||
to address ADDR. Thus, after invoking lookup(), we have a
|
||||
list of FDRs that may contain the PDR for ADDR. Next, we
|
||||
walk through the PDRs of these FDRs and locate the one that
|
||||
is closest to ADDR (i.e., for which the difference between
|
||||
ADDR and the PDR's entry point is positive and minimal).
|
||||
Once, the right FDR and PDR are located, we simply walk
|
||||
through the line-number table to lookup the line-number that
|
||||
best matches ADDR. Obviously, things could be sped up by
|
||||
keeping a sorted list of PDRs instead of a sorted list of
|
||||
FDRs. However, this would increase space requirements
|
||||
considerably, which is undesirable. */
|
||||
external_pdr_size = debug_swap->external_pdr_size;
|
||||
|
||||
/* Make offset relative to object file's start-address: */
|
||||
offset -= tab[i].base_addr;
|
||||
/* Search FDR list starting at tab[i] for the PDR that best matches
|
||||
OFFSET. Normally, the FDR list is only one entry long. */
|
||||
best_fdr = NULL;
|
||||
do
|
||||
ecoff_data (abfd)->find_line_info =
|
||||
((struct ecoff_find_line *)
|
||||
bfd_alloc (abfd, sizeof (struct ecoff_find_line)));
|
||||
if (ecoff_data (abfd)->find_line_info == NULL)
|
||||
{
|
||||
bfd_vma dist, min_dist = 0;
|
||||
char *pdr_hold;
|
||||
char *pdr_end;
|
||||
|
||||
fdr_ptr = tab[i].fdr;
|
||||
|
||||
pdr_ptr = ((char *) debug_info->external_pdr
|
||||
+ fdr_ptr->ipdFirst * external_pdr_size);
|
||||
pdr_end = pdr_ptr + fdr_ptr->cpd * external_pdr_size;
|
||||
(*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
|
||||
/* Find PDR that is closest to OFFSET. If pdr.prof is set,
|
||||
the procedure entry-point *may* be 0x10 below pdr.adr. We
|
||||
simply pretend that pdr.prof *implies* a lower entry-point.
|
||||
This is safe because it just means that may identify 4 NOPs
|
||||
in front of the function as belonging to the function. */
|
||||
for (pdr_hold = NULL;
|
||||
pdr_ptr < pdr_end;
|
||||
(pdr_ptr += external_pdr_size,
|
||||
(*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr)))
|
||||
{
|
||||
if (offset >= (pdr.adr - 0x10 * pdr.prof))
|
||||
{
|
||||
dist = offset - (pdr.adr - 0x10 * pdr.prof);
|
||||
if (!pdr_hold || dist < min_dist)
|
||||
{
|
||||
min_dist = dist;
|
||||
pdr_hold = pdr_ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!best_pdr || min_dist < best_dist)
|
||||
{
|
||||
best_dist = min_dist;
|
||||
best_fdr = fdr_ptr;
|
||||
best_pdr = pdr_hold;
|
||||
}
|
||||
/* continue looping until base_addr of next entry is different: */
|
||||
}
|
||||
while (++i < ecoff_data (abfd)->fdrtab_len
|
||||
&& tab[i].base_addr == tab[i - 1].base_addr);
|
||||
|
||||
if (!best_fdr || !best_pdr)
|
||||
return false; /* shouldn't happen... */
|
||||
|
||||
/* phew, finally we got something that we can hold onto: */
|
||||
fdr_ptr = best_fdr;
|
||||
pdr_ptr = best_pdr;
|
||||
(*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
|
||||
/* Now we can look for the actual line number. The line numbers
|
||||
are stored in a very funky format, which I won't try to
|
||||
describe. The search is bounded by the end of the FDRs line
|
||||
number entries. */
|
||||
line_end = debug_info->line + fdr_ptr->cbLineOffset + fdr_ptr->cbLine;
|
||||
|
||||
/* Make offset relative to procedure entry: */
|
||||
offset -= pdr.adr - 0x10 * pdr.prof;
|
||||
lineno = pdr.lnLow;
|
||||
line_ptr = debug_info->line + fdr_ptr->cbLineOffset + pdr.cbLineOffset;
|
||||
while (line_ptr < line_end)
|
||||
{
|
||||
int delta;
|
||||
int count;
|
||||
|
||||
delta = *line_ptr >> 4;
|
||||
if (delta >= 0x8)
|
||||
delta -= 0x10;
|
||||
count = (*line_ptr & 0xf) + 1;
|
||||
++line_ptr;
|
||||
if (delta == -8)
|
||||
{
|
||||
delta = (((line_ptr[0]) & 0xff) << 8) + ((line_ptr[1]) & 0xff);
|
||||
if (delta >= 0x8000)
|
||||
delta -= 0x10000;
|
||||
line_ptr += 2;
|
||||
}
|
||||
lineno += delta;
|
||||
if (offset < count * 4)
|
||||
break;
|
||||
offset -= count * 4;
|
||||
}
|
||||
|
||||
/* If fdr_ptr->rss is -1, then this file does not have full
|
||||
symbols, at least according to gdb/mipsread.c. */
|
||||
if (fdr_ptr->rss == -1)
|
||||
{
|
||||
*filename_ptr = NULL;
|
||||
if (pdr.isym == -1)
|
||||
*functionname_ptr = NULL;
|
||||
else
|
||||
{
|
||||
EXTR proc_ext;
|
||||
|
||||
(*debug_swap->swap_ext_in)
|
||||
(abfd,
|
||||
((char *) debug_info->external_ext
|
||||
+ pdr.isym * debug_swap->external_ext_size),
|
||||
&proc_ext);
|
||||
*functionname_ptr = debug_info->ssext + proc_ext.asym.iss;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SYMR proc_sym;
|
||||
|
||||
*filename_ptr = debug_info->ss + fdr_ptr->issBase + fdr_ptr->rss;
|
||||
(*debug_swap->swap_sym_in)
|
||||
(abfd,
|
||||
((char *) debug_info->external_sym
|
||||
+ (fdr_ptr->isymBase + pdr.isym) * debug_swap->external_sym_size),
|
||||
&proc_sym);
|
||||
*functionname_ptr = debug_info->ss + fdr_ptr->issBase + proc_sym.iss;
|
||||
}
|
||||
if (lineno == ilineNil)
|
||||
lineno = 0;
|
||||
*retline_ptr = lineno;
|
||||
}
|
||||
else
|
||||
{
|
||||
bfd_size_type external_sym_size;
|
||||
const char *directory_name;
|
||||
const char *main_file_name;
|
||||
const char *current_file_name;
|
||||
const char *function_name;
|
||||
const char *line_file_name;
|
||||
bfd_vma low_func_vma;
|
||||
bfd_vma low_line_vma;
|
||||
char *sym_ptr, *sym_ptr_end;
|
||||
size_t len, funclen;
|
||||
char *buffer = NULL;
|
||||
|
||||
/* This file uses stabs debugging information. */
|
||||
|
||||
*filename_ptr = NULL;
|
||||
*functionname_ptr = NULL;
|
||||
*retline_ptr = 0;
|
||||
|
||||
directory_name = NULL;
|
||||
main_file_name = NULL;
|
||||
current_file_name = NULL;
|
||||
function_name = NULL;
|
||||
line_file_name = NULL;
|
||||
low_func_vma = 0;
|
||||
low_line_vma = 0;
|
||||
|
||||
external_sym_size = debug_swap->external_sym_size;
|
||||
|
||||
sym_ptr = ((char *) debug_info->external_sym
|
||||
+ (fdr_ptr->isymBase + 2) * external_sym_size);
|
||||
sym_ptr_end = sym_ptr + fdr_ptr->csym * external_sym_size;
|
||||
for (; sym_ptr < sym_ptr_end; sym_ptr += external_sym_size)
|
||||
{
|
||||
SYMR sym;
|
||||
|
||||
(*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym);
|
||||
|
||||
if (ECOFF_IS_STAB (&sym))
|
||||
{
|
||||
switch (ECOFF_UNMARK_STAB (sym.index))
|
||||
{
|
||||
case N_SO:
|
||||
main_file_name = current_file_name =
|
||||
debug_info->ss + fdr_ptr->issBase + sym.iss;
|
||||
|
||||
/* Check the next symbol to see if it is also an
|
||||
N_SO symbol. */
|
||||
if (sym_ptr + external_sym_size < sym_ptr_end)
|
||||
{
|
||||
SYMR nextsym;
|
||||
|
||||
(*debug_swap->swap_sym_in) (abfd,
|
||||
sym_ptr + external_sym_size,
|
||||
&nextsym);
|
||||
if (ECOFF_IS_STAB (&nextsym)
|
||||
&& ECOFF_UNMARK_STAB (nextsym.index) == N_SO)
|
||||
{
|
||||
directory_name = current_file_name;
|
||||
main_file_name = current_file_name =
|
||||
debug_info->ss + fdr_ptr->issBase + sym.iss;
|
||||
sym_ptr += external_sym_size;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case N_SOL:
|
||||
current_file_name =
|
||||
debug_info->ss + fdr_ptr->issBase + sym.iss;
|
||||
break;
|
||||
|
||||
case N_FUN:
|
||||
if (sym.value >= low_func_vma
|
||||
&& sym.value <= offset + section->vma)
|
||||
{
|
||||
low_func_vma = sym.value;
|
||||
function_name =
|
||||
debug_info->ss + fdr_ptr->issBase + sym.iss;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (sym.st == stLabel && sym.index != indexNil)
|
||||
{
|
||||
if (sym.value > offset + section->vma)
|
||||
{
|
||||
/* We have passed the location in the file we are
|
||||
looking for, so we can get out of the loop. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (sym.value >= low_line_vma)
|
||||
{
|
||||
low_line_vma = sym.value;
|
||||
line_file_name = current_file_name;
|
||||
*retline_ptr = sym.index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*retline_ptr != 0)
|
||||
main_file_name = line_file_name;
|
||||
|
||||
/* We need to remove the stuff after the colon in the function
|
||||
name. We also need to put the directory name and the file
|
||||
name together. */
|
||||
if (function_name == NULL)
|
||||
len = funclen = 0;
|
||||
else
|
||||
len = funclen = strlen (function_name) + 1;
|
||||
|
||||
if (main_file_name != NULL
|
||||
&& directory_name != NULL
|
||||
&& main_file_name[0] != '/')
|
||||
len += strlen (directory_name) + strlen (main_file_name) + 1;
|
||||
|
||||
if (len != 0)
|
||||
{
|
||||
if (ecoff_data (abfd)->find_buffer != NULL)
|
||||
free (ecoff_data (abfd)->find_buffer);
|
||||
buffer = (char *) malloc (len);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
return false;
|
||||
}
|
||||
ecoff_data (abfd)->find_buffer = buffer;
|
||||
}
|
||||
|
||||
if (function_name != NULL)
|
||||
{
|
||||
char *colon;
|
||||
|
||||
strcpy (buffer, function_name);
|
||||
colon = strchr (buffer, ':');
|
||||
if (colon != NULL)
|
||||
*colon = '\0';
|
||||
*functionname_ptr = buffer;
|
||||
}
|
||||
|
||||
if (main_file_name != NULL)
|
||||
{
|
||||
if (directory_name == NULL || main_file_name[0] == '/')
|
||||
*filename_ptr = main_file_name;
|
||||
else
|
||||
{
|
||||
sprintf (buffer + funclen, "%s%s", directory_name,
|
||||
main_file_name);
|
||||
*filename_ptr = buffer + funclen;
|
||||
}
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
line_info = ecoff_data (abfd)->find_line_info;
|
||||
|
||||
return true;
|
||||
return _bfd_ecoff_locate_line (abfd, section, offset, debug_info,
|
||||
debug_swap, line_info, filename_ptr,
|
||||
functionname_ptr, retline_ptr);
|
||||
}
|
||||
|
||||
|
||||
/* Copy private BFD data. This is called by objcopy and strip. We
|
||||
use it to copy the ECOFF debugging information from one BFD to the
|
||||
|
@ -3194,8 +2485,8 @@ _bfd_ecoff_write_object_contents (abfd)
|
|||
section.s_flags = ecoff_sec_to_styp_flags (current->name,
|
||||
current->flags);
|
||||
|
||||
bfd_coff_swap_scnhdr_out (abfd, (PTR) §ion, buff);
|
||||
if (bfd_write (buff, 1, scnhsz, abfd) != scnhsz)
|
||||
if (bfd_coff_swap_scnhdr_out (abfd, (PTR) §ion, buff) == 0
|
||||
|| bfd_write (buff, 1, scnhsz, abfd) != scnhsz)
|
||||
goto error_return;
|
||||
|
||||
if ((section.s_flags & STYP_TEXT) != 0
|
||||
|
@ -4087,7 +3378,7 @@ ecoff_link_add_archive_symbols (abfd, info)
|
|||
/* An empty archive is a special case. */
|
||||
if (bfd_openr_next_archived_file (abfd, (bfd *) NULL) == NULL)
|
||||
return true;
|
||||
bfd_set_error (bfd_error_no_symbols);
|
||||
bfd_set_error (bfd_error_no_armap);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -4605,10 +3896,11 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
|
|||
on Ultrix 4.2 to handle the symbol cred in -lckrb. */
|
||||
if (h->small
|
||||
&& h->root.type == bfd_link_hash_common
|
||||
&& strcmp (h->root.u.c.section->name, SCOMMON) != 0)
|
||||
&& strcmp (h->root.u.c.p->section->name, SCOMMON) != 0)
|
||||
{
|
||||
h->root.u.c.section = bfd_make_section_old_way (abfd, SCOMMON);
|
||||
h->root.u.c.section->flags = SEC_ALLOC;
|
||||
h->root.u.c.p->section = bfd_make_section_old_way (abfd,
|
||||
SCOMMON);
|
||||
h->root.u.c.p->section->flags = SEC_ALLOC;
|
||||
if (h->esym.asym.sc == scCommon)
|
||||
h->esym.asym.sc = scSCommon;
|
||||
}
|
||||
|
|
|
@ -4035,7 +4035,7 @@ elf_link_add_archive_symbols (abfd, info)
|
|||
/* An empty archive is a special case. */
|
||||
if (bfd_openr_next_archived_file (abfd, (bfd *) NULL) == NULL)
|
||||
return true;
|
||||
bfd_set_error (bfd_error_no_symbols);
|
||||
bfd_set_error (bfd_error_no_armap);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -867,7 +867,7 @@ _bfd_generic_link_add_archive_symbols (abfd, info, checkfn)
|
|||
/* An empty archive is a special case. */
|
||||
if (bfd_openr_next_archived_file (abfd, (bfd *) NULL) == NULL)
|
||||
return true;
|
||||
bfd_set_error (bfd_error_no_symbols);
|
||||
bfd_set_error (bfd_error_no_armap);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue