/* Routines to link ECOFF debugging information.
- Copyright 1993, 1994, 1995, 1996, 1997, 2000, 2001, 2002
- Free Software Foundation, Inc.
+ Copyright 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003,
+ 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>.
-This file is part of BFD, the Binary File Descriptor library.
+ This file is part of BFD, the Binary File Descriptor library.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "bfdlink.h"
#include "libbfd.h"
#include "objalloc.h"
#include "libcoff.h"
#include "libecoff.h"
\f
-static boolean ecoff_add_bytes PARAMS ((char **buf, char **bufend,
- size_t need));
+static bfd_boolean ecoff_add_bytes
+ PARAMS ((char **buf, char **bufend, size_t need));
static struct bfd_hash_entry *string_hash_newfunc
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
const char *));
-static void ecoff_align_debug PARAMS ((bfd *abfd,
- struct ecoff_debug_info *debug,
- const struct ecoff_debug_swap *swap));
-static boolean ecoff_write_symhdr PARAMS ((bfd *, struct ecoff_debug_info *,
- const struct ecoff_debug_swap *,
- file_ptr where));
-static int cmp_fdrtab_entry PARAMS ((const PTR, const PTR));
-static boolean mk_fdrtab PARAMS ((bfd *,
- struct ecoff_debug_info * const,
- const struct ecoff_debug_swap * const,
- struct ecoff_find_line *));
-static long fdrtab_lookup PARAMS ((struct ecoff_find_line *, bfd_vma));
-static boolean lookup_line
+static void ecoff_align_debug
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap));
+static bfd_boolean ecoff_write_symhdr
+ PARAMS ((bfd *, struct ecoff_debug_info *, const struct ecoff_debug_swap *,
+ file_ptr where));
+static int cmp_fdrtab_entry
+ PARAMS ((const PTR, const PTR));
+static bfd_boolean mk_fdrtab
+ PARAMS ((bfd *, struct ecoff_debug_info * const,
+ const struct ecoff_debug_swap * const, struct ecoff_find_line *));
+static long fdrtab_lookup
+ PARAMS ((struct ecoff_find_line *, bfd_vma));
+static bfd_boolean lookup_line
PARAMS ((bfd *, struct ecoff_debug_info * const,
const struct ecoff_debug_swap * const, struct ecoff_find_line *));
\f
/* Add bytes to a buffer. Return success. */
-static boolean
+static bfd_boolean
ecoff_add_bytes (buf, bufend, need)
char **buf;
char **bufend;
}
newbuf = (char *) bfd_realloc (*buf, (bfd_size_type) have + want);
if (newbuf == NULL)
- return false;
+ return FALSE;
*buf = newbuf;
*bufend = *buf + have + want;
- return true;
+ return TRUE;
}
/* We keep a hash table which maps strings to numbers. We use it to
/* The length of the information. */
unsigned long size;
/* Whether this information comes from a file or not. */
- boolean filep;
+ bfd_boolean filep;
union
{
struct
/* Add a file entry to a shuffle list. */
-static boolean add_file_shuffle PARAMS ((struct accumulate *,
- struct shuffle **,
- struct shuffle **, bfd *, file_ptr,
- unsigned long));
+static bfd_boolean add_file_shuffle
+ PARAMS ((struct accumulate *, struct shuffle **, struct shuffle **,
+ bfd *, file_ptr, unsigned long));
-static boolean
+static bfd_boolean
add_file_shuffle (ainfo, head, tail, input_bfd, offset, size)
struct accumulate *ainfo;
struct shuffle **head;
(*tail)->size += size;
if ((*tail)->size > ainfo->largest_file_shuffle)
ainfo->largest_file_shuffle = (*tail)->size;
- return true;
+ return TRUE;
}
n = (struct shuffle *) objalloc_alloc (ainfo->memory,
if (!n)
{
bfd_set_error (bfd_error_no_memory);
- return false;
+ return FALSE;
}
n->next = NULL;
n->size = size;
- n->filep = true;
+ n->filep = TRUE;
n->u.file.input_bfd = input_bfd;
n->u.file.offset = offset;
if (*head == (struct shuffle *) NULL)
*tail = n;
if (size > ainfo->largest_file_shuffle)
ainfo->largest_file_shuffle = size;
- return true;
+ return TRUE;
}
/* Add a memory entry to a shuffle list. */
-static boolean add_memory_shuffle PARAMS ((struct accumulate *,
- struct shuffle **head,
- struct shuffle **tail,
- bfd_byte *data, unsigned long size));
+static bfd_boolean add_memory_shuffle
+ PARAMS ((struct accumulate *, struct shuffle **head, struct shuffle **tail,
+ bfd_byte *data, unsigned long size));
-static boolean
+static bfd_boolean
add_memory_shuffle (ainfo, head, tail, data, size)
struct accumulate *ainfo;
struct shuffle **head;
if (!n)
{
bfd_set_error (bfd_error_no_memory);
- return false;
+ return FALSE;
}
n->next = NULL;
n->size = size;
- n->filep = false;
+ n->filep = FALSE;
n->u.memory = (PTR) data;
if (*head == (struct shuffle *) NULL)
*head = n;
if (*tail != (struct shuffle *) NULL)
(*tail)->next = n;
*tail = n;
- return true;
+ return TRUE;
}
/* Initialize the FDR hash table. This returns a handle which is then
ainfo = (struct accumulate *) bfd_malloc (amt);
if (!ainfo)
return NULL;
- if (! bfd_hash_table_init_n (&ainfo->fdr_hash.table, string_hash_newfunc,
- 1021))
+ if (!bfd_hash_table_init_n (&ainfo->fdr_hash.table, string_hash_newfunc,
+ sizeof (struct string_hash_entry), 1021))
return NULL;
ainfo->line = NULL;
ainfo->largest_file_shuffle = 0;
- if (! info->relocateable)
+ if (! info->relocatable)
{
- if (! bfd_hash_table_init (&ainfo->str_hash.table, string_hash_newfunc))
+ if (!bfd_hash_table_init (&ainfo->str_hash.table, string_hash_newfunc,
+ sizeof (struct string_hash_entry)))
return NULL;
/* The first entry in the string table is the empty string. */
bfd_hash_table_free (&ainfo->fdr_hash.table);
- if (! info->relocateable)
+ if (! info->relocatable)
bfd_hash_table_free (&ainfo->str_hash.table);
objalloc_free (ainfo->memory);
linker information structure. HANDLE is returned by
bfd_ecoff_debug_init. */
-boolean
+bfd_boolean
bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
input_bfd, input_debug, input_swap,
info)
if (!input_debug->ifdmap || !rfd_out)
{
bfd_set_error (bfd_error_no_memory);
- return false;
+ return FALSE;
}
if (!add_memory_shuffle (ainfo, &ainfo->rfd, &ainfo->rfd_end, rfd_out, sz))
- return false;
+ return FALSE;
copied = 0;
lookup = (char *) bfd_malloc ((bfd_size_type) strlen (name) + 20);
if (lookup == NULL)
- return false;
+ return FALSE;
sprintf (lookup, "%s %lx %lx", name, fdr.csym, fdr.caux);
- fh = string_hash_lookup (&ainfo->fdr_hash, lookup, true, true);
+ fh = string_hash_lookup (&ainfo->fdr_hash, lookup, TRUE, TRUE);
free (lookup);
if (fh == (struct string_hash_entry *) NULL)
- return false;
+ return FALSE;
if (fh->val != -1)
{
if (!fdr_out)
{
bfd_set_error (bfd_error_no_memory);
- return false;
+ return FALSE;
}
if (!add_memory_shuffle (ainfo, &ainfo->fdr, &ainfo->fdr_end, fdr_out, sz))
- return false;
+ return FALSE;
for (fdr_ptr = fdr_start, i = 0;
fdr_ptr < fdr_end;
fdr_ptr += fdr_add, i++)
{
FDR fdr;
- bfd_vma fdr_adr;
bfd_byte *sym_out;
bfd_byte *lraw_src;
bfd_byte *lraw_end;
- boolean fgotfilename;
+ bfd_boolean fgotfilename;
if (input_debug->ifdmap[i] < output_symhdr->ifdMax)
{
else
(*input_swap->swap_fdr_in) (input_bfd, (PTR) fdr_ptr, &fdr);
- fdr_adr = fdr.adr;
-
- /* Adjust the FDR address for any changes that may have been
- made by relaxing. */
- if (input_debug->adjust != (struct ecoff_value_adjust *) NULL)
- {
- struct ecoff_value_adjust *adjust;
-
- for (adjust = input_debug->adjust;
- adjust != (struct ecoff_value_adjust *) NULL;
- adjust = adjust->next)
- if (fdr_adr >= adjust->start
- && fdr_adr < adjust->end)
- fdr.adr += adjust->adjust;
- }
-
/* FIXME: It is conceivable that this FDR points to the .init or
.fini section, in which case this will not do the right
thing. */
/* Swap in the local symbols, adjust their values, and swap them
out again. */
- fgotfilename = false;
+ fgotfilename = FALSE;
sz = fdr.csym * external_sym_size;
sym_out = (bfd_byte *) objalloc_alloc (ainfo->memory, sz);
if (!sym_out)
{
bfd_set_error (bfd_error_no_memory);
- return false;
+ return FALSE;
}
if (!add_memory_shuffle (ainfo, &ainfo->sym, &ainfo->sym_end, sym_out,
sz))
- return false;
+ return FALSE;
lraw_src = ((bfd_byte *) input_debug->external_sym
+ fdr.isymBase * input_swap->external_sym_size);
lraw_end = lraw_src + fdr.csym * input_swap->external_sym_size;
case stLabel:
case stProc:
case stStaticProc:
- if (input_debug->adjust != (struct ecoff_value_adjust *) NULL)
- {
- bfd_vma value;
- struct ecoff_value_adjust *adjust;
-
- value = internal_sym.value;
- for (adjust = input_debug->adjust;
- adjust != (struct ecoff_value_adjust *) NULL;
- adjust = adjust->next)
- if (value >= adjust->start
- && value < adjust->end)
- internal_sym.value += adjust->adjust;
- }
internal_sym.value += section_adjust[internal_sym.sc];
break;
/* If we are doing a final link, we hash all the strings in
the local symbol table together. This reduces the amount
of space required by debugging information. We don't do
- this when performing a relocateable link because it would
+ this when performing a relocatable link because it would
prevent us from easily merging different FDR's. */
- if (! info->relocateable)
+ if (! info->relocatable)
{
- boolean ffilename;
+ bfd_boolean ffilename;
const char *name;
if (! fgotfilename && internal_sym.iss == fdr.rss)
- ffilename = true;
+ ffilename = TRUE;
else
- ffilename = false;
+ ffilename = FALSE;
/* Hash the name into the string table. */
name = input_debug->ss + fdr.issBase + internal_sym.iss;
{
struct string_hash_entry *sh;
- sh = string_hash_lookup (&ainfo->str_hash, name, true, true);
+ sh = string_hash_lookup (&ainfo->str_hash, name, TRUE, TRUE);
if (sh == (struct string_hash_entry *) NULL)
- return false;
+ return FALSE;
if (sh->val == -1)
{
sh->val = output_symhdr->issMax;
if (ffilename)
{
fdr.rss = internal_sym.iss;
- fgotfilename = true;
+ fgotfilename = TRUE;
}
}
file_ptr pos = input_symhdr->cbLineOffset + fdr.cbLineOffset;
if (!add_file_shuffle (ainfo, &ainfo->line, &ainfo->line_end,
input_bfd, pos, (unsigned long) fdr.cbLine))
- return false;
+ return FALSE;
fdr.ilineBase = output_symhdr->ilineMax;
fdr.cbLineOffset = output_symhdr->cbLine;
output_symhdr->ilineMax += fdr.cline;
if (!add_file_shuffle (ainfo, &ainfo->aux, &ainfo->aux_end,
input_bfd, pos,
fdr.caux * sizeof (union aux_ext)))
- return false;
+ return FALSE;
fdr.iauxBase = output_symhdr->iauxMax;
output_symhdr->iauxMax += fdr.caux;
}
- if (! info->relocateable)
+ if (! info->relocatable)
{
/* When are are hashing strings, we lie about the number of
file_ptr pos = input_symhdr->cbSsOffset + fdr.issBase;
if (!add_file_shuffle (ainfo, &ainfo->ss, &ainfo->ss_end,
input_bfd, pos, (unsigned long) fdr.cbSs))
- return false;
+ return FALSE;
fdr.issBase = output_symhdr->issMax;
output_symhdr->issMax += fdr.cbSs;
}
- if ((output_bfd->xvec->header_byteorder
- == input_bfd->xvec->header_byteorder)
- && input_debug->adjust == (struct ecoff_value_adjust *) NULL)
+ if (output_bfd->xvec->header_byteorder
+ == input_bfd->xvec->header_byteorder)
{
/* The two BFD's have the same endianness, and we don't have
to adjust the PDR addresses, so simply copying the
unsigned long size = fdr.cpd * external_pdr_size;
if (!add_file_shuffle (ainfo, &ainfo->pdr, &ainfo->pdr_end,
input_bfd, pos, size))
- return false;
+ return FALSE;
}
BFD_ASSERT (external_opt_size == input_swap->external_opt_size);
if (fdr.copt > 0)
unsigned long size = fdr.copt * external_opt_size;
if (!add_file_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end,
input_bfd, pos, size))
- return false;
+ return FALSE;
}
}
else
if (!out)
{
bfd_set_error (bfd_error_no_memory);
- return false;
+ return FALSE;
}
if (!add_memory_shuffle (ainfo, &ainfo->pdr, &ainfo->pdr_end, out,
sz))
- return false;
+ return FALSE;
for (; in < end; in += insz, out += outsz)
{
PDR pdr;
(*input_swap->swap_pdr_in) (input_bfd, (PTR) in, &pdr);
-
- /* If we have been relaxing, we may have to adjust the
- address. */
- if (input_debug->adjust != (struct ecoff_value_adjust *) NULL)
- {
- bfd_vma adr;
- struct ecoff_value_adjust *adjust;
-
- adr = fdr_adr + pdr.adr;
- for (adjust = input_debug->adjust;
- adjust != (struct ecoff_value_adjust *) NULL;
- adjust = adjust->next)
- if (adr >= adjust->start
- && adr < adjust->end)
- pdr.adr += adjust->adjust;
- }
-
(*output_swap->swap_pdr_out) (output_bfd, &pdr, (PTR) out);
}
if (!out)
{
bfd_set_error (bfd_error_no_memory);
- return false;
+ return FALSE;
}
if (!add_memory_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end, out,
sz))
- return false;
+ return FALSE;
for (; in < end; in += insz, out += outsz)
{
OPTR opt;
++output_symhdr->ifdMax;
}
- return true;
+ return TRUE;
}
/* Add a string to the debugging information we are accumulating.
Return the offset from the fdr string base. */
-static long ecoff_add_string PARAMS ((struct accumulate *,
- struct bfd_link_info *,
- struct ecoff_debug_info *,
- FDR *fdr, const char *string));
+static long ecoff_add_string
+ PARAMS ((struct accumulate *, struct bfd_link_info *,
+ struct ecoff_debug_info *, FDR *fdr, const char *string));
static long
ecoff_add_string (ainfo, info, debug, fdr, string)
symhdr = &debug->symbolic_header;
len = strlen (string);
- if (info->relocateable)
+ if (info->relocatable)
{
if (!add_memory_shuffle (ainfo, &ainfo->ss, &ainfo->ss_end, (PTR) string,
len + 1))
{
struct string_hash_entry *sh;
- sh = string_hash_lookup (&ainfo->str_hash, string, true, true);
+ sh = string_hash_lookup (&ainfo->str_hash, string, TRUE, TRUE);
if (sh == (struct string_hash_entry *) NULL)
return -1;
if (sh->val == -1)
/* Add debugging information from a non-ECOFF file. */
-boolean
+bfd_boolean
bfd_ecoff_debug_accumulate_other (handle, output_bfd, output_debug,
output_swap, input_bfd, info)
PTR handle;
fdr.issBase = output_symhdr->issMax;
fdr.cbSs = 0;
fdr.rss = ecoff_add_string (ainfo, info, output_debug, &fdr,
- bfd_archive_filename (input_bfd));
+ input_bfd->filename);
if (fdr.rss == -1)
- return false;
+ return FALSE;
fdr.isymBase = output_symhdr->isymMax;
/* Get the local symbols from the input BFD. */
symsize = bfd_get_symtab_upper_bound (input_bfd);
if (symsize < 0)
- return false;
+ return FALSE;
symbols = (asymbol **) bfd_alloc (output_bfd, (bfd_size_type) symsize);
if (symbols == (asymbol **) NULL)
- return false;
+ return FALSE;
symcount = bfd_canonicalize_symtab (input_bfd, symbols);
if (symcount < 0)
- return false;
+ return FALSE;
sym_end = symbols + symcount;
/* Handle the local symbols. Any external symbols are handled
(*sym_ptr)->name);
if (internal_sym.iss == -1)
- return false;
+ return FALSE;
if (bfd_is_com_section ((*sym_ptr)->section)
|| bfd_is_und_section ((*sym_ptr)->section))
internal_sym.value = (*sym_ptr)->value;
if (!external_sym)
{
bfd_set_error (bfd_error_no_memory);
- return false;
+ return FALSE;
}
(*swap_sym_out) (output_bfd, &internal_sym, external_sym);
add_memory_shuffle (ainfo, &ainfo->sym, &ainfo->sym_end,
if (!external_fdr)
{
bfd_set_error (bfd_error_no_memory);
- return false;
+ return FALSE;
}
(*output_swap->swap_fdr_out) (output_bfd, &fdr, external_fdr);
add_memory_shuffle (ainfo, &ainfo->fdr, &ainfo->fdr_end,
++output_symhdr->ifdMax;
- return true;
+ return TRUE;
}
/* Set up ECOFF debugging information for the external symbols.
probably be changed to use a shuffle structure. The assembler uses
this interface, so that must be changed to do something else. */
-boolean
-bfd_ecoff_debug_externals (abfd, debug, swap, relocateable, get_extr,
+bfd_boolean
+bfd_ecoff_debug_externals (abfd, debug, swap, relocatable, get_extr,
set_index)
bfd *abfd;
struct ecoff_debug_info *debug;
const struct ecoff_debug_swap *swap;
- boolean relocateable;
- boolean (*get_extr) PARAMS ((asymbol *, EXTR *));
+ bfd_boolean relocatable;
+ bfd_boolean (*get_extr) PARAMS ((asymbol *, EXTR *));
void (*set_index) PARAMS ((asymbol *, bfd_size_type));
{
HDRR * const symhdr = &debug->symbolic_header;
sym_ptr_ptr = bfd_get_outsymbols (abfd);
if (sym_ptr_ptr == NULL)
- return true;
+ return TRUE;
for (c = bfd_get_symcount (abfd); c > 0; c--, sym_ptr_ptr++)
{
/* If we're producing an executable, move common symbols into
bss. */
- if (! relocateable)
+ if (! relocatable)
{
if (esym.asym.sc == scCommon)
esym.asym.sc = scBss;
if (! bfd_ecoff_debug_one_external (abfd, debug, swap,
sym_ptr->name, &esym))
- return false;
+ return FALSE;
}
- return true;
+ return TRUE;
}
/* Add a single external symbol to the debugging information. */
-boolean
+bfd_boolean
bfd_ecoff_debug_one_external (abfd, debug, swap, name, esym)
bfd *abfd;
struct ecoff_debug_info *debug;
if (! ecoff_add_bytes ((char **) &debug->ssext,
(char **) &debug->ssext_end,
symhdr->issExtMax + namelen + 1))
- return false;
+ return FALSE;
}
if ((size_t) ((char *) debug->external_ext_end
- (char *) debug->external_ext)
< (symhdr->iextMax + 1) * external_ext_size)
{
- if (! ecoff_add_bytes ((char **) &debug->external_ext,
- (char **) &debug->external_ext_end,
+ char *external_ext = debug->external_ext;
+ char *external_ext_end = debug->external_ext_end;
+ if (! ecoff_add_bytes ((char **) &external_ext,
+ (char **) &external_ext_end,
(symhdr->iextMax + 1) * (size_t) external_ext_size))
- return false;
+ return FALSE;
+ debug->external_ext = external_ext;
+ debug->external_ext_end = external_ext_end;
}
esym->asym.iss = symhdr->issExtMax;
strcpy (debug->ssext + symhdr->issExtMax, name);
symhdr->issExtMax += namelen + 1;
- return true;
+ return TRUE;
}
/* Align the ECOFF debugging information. */
going to be placed at. This assumes that the counts are set
correctly. */
-static boolean
+static bfd_boolean
ecoff_write_symhdr (abfd, debug, swap, where)
bfd *abfd;
struct ecoff_debug_info *debug;
/* Go to the right location in the file. */
if (bfd_seek (abfd, where, SEEK_SET) != 0)
- return false;
+ return FALSE;
where += swap->external_hdr_size;
if (buff != NULL)
free (buff);
- return true;
+ return TRUE;
error_return:
if (buff != NULL)
free (buff);
- return false;
+ return FALSE;
}
/* Write out the ECOFF debugging information. This function assumes
information to. This function fills in the file offsets in the
symbolic header. */
-boolean
+bfd_boolean
bfd_ecoff_write_debug (abfd, debug, swap, where)
bfd *abfd;
struct ecoff_debug_info *debug;
HDRR * const symhdr = &debug->symbolic_header;
if (! ecoff_write_symhdr (abfd, debug, swap, where))
- return false;
+ return FALSE;
#define WRITE(ptr, count, size, offset) \
BFD_ASSERT (symhdr->offset == 0 \
|| (bfd_vma) bfd_tell (abfd) == symhdr->offset); \
if (bfd_bwrite ((PTR) debug->ptr, (bfd_size_type) size * symhdr->count, abfd)\
!= size * symhdr->count) \
- return false;
+ return FALSE;
WRITE (line, cbLine, sizeof (unsigned char), cbLineOffset);
WRITE (external_dnr, idnMax, swap->external_dnr_size, cbDnOffset);
WRITE (external_ext, iextMax, swap->external_ext_size, cbExtOffset);
#undef WRITE
- return true;
+ return TRUE;
}
/* Write out a shuffle list. */
-static boolean ecoff_write_shuffle PARAMS ((bfd *,
- const struct ecoff_debug_swap *,
- struct shuffle *, PTR space));
+static bfd_boolean ecoff_write_shuffle
+ PARAMS ((bfd *, const struct ecoff_debug_swap *, struct shuffle *,
+ PTR space));
-static boolean
+static bfd_boolean
ecoff_write_shuffle (abfd, swap, shuffle, space)
bfd *abfd;
const struct ecoff_debug_swap *swap;
{
if (bfd_bwrite (l->u.memory, (bfd_size_type) l->size, abfd)
!= l->size)
- return false;
+ return FALSE;
}
else
{
|| bfd_bread (space, (bfd_size_type) l->size,
l->u.file.input_bfd) != l->size
|| bfd_bwrite (space, (bfd_size_type) l->size, abfd) != l->size)
- return false;
+ return FALSE;
}
total += l->size;
}
i = swap->debug_align - (total & (swap->debug_align - 1));
s = (bfd_byte *) bfd_zmalloc ((bfd_size_type) i);
if (s == NULL && i != 0)
- return false;
+ return FALSE;
if (bfd_bwrite ((PTR) s, (bfd_size_type) i, abfd) != i)
{
free (s);
- return false;
+ return FALSE;
}
free (s);
}
- return true;
+ return TRUE;
}
/* Write out debugging information using accumulated linker
information. */
-boolean
+bfd_boolean
bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
PTR handle;
bfd *abfd;
/* The string table is written out from the hash table if this is a
final link. */
- if (info->relocateable)
+ if (info->relocatable)
{
BFD_ASSERT (ainfo->ss_hash == (struct string_hash_entry *) NULL);
if (! ecoff_write_shuffle (abfd, swap, ainfo->ss, space))
if (space != NULL)
free (space);
- return true;
+ return TRUE;
error_return:
if (space != NULL)
free (space);
- return false;
+ return FALSE;
}
\f
/* Handle the find_nearest_line function for both ECOFF and MIPS ELF
table will be sorted by address so we can look it up via binary
search. */
-static boolean
+static bfd_boolean
mk_fdrtab (abfd, debug_info, debug_swap, line_info)
bfd *abfd;
struct ecoff_debug_info * const debug_info;
FDR *fdr_ptr;
FDR *fdr_start;
FDR *fdr_end;
- boolean stabs;
+ bfd_boolean stabs;
long len;
bfd_size_type amt;
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: */
+ /* 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 */
+ if (fdr_ptr->cpd == 0) /* Skip FDRs that have no PDRs. */
continue;
++len;
}
- /* Now, create and fill in the table: */
-
+ /* Now, create and fill in the table. */
amt = (bfd_size_type) len * sizeof (struct ecoff_fdrtab_entry);
line_info->fdrtab = (struct ecoff_fdrtab_entry*) bfd_zalloc (abfd, amt);
if (line_info->fdrtab == NULL)
- return false;
+ return FALSE;
line_info->fdrtab_len = len;
tab = line_info->fdrtab;
/* Check whether this file has stabs debugging information. In
a file with stabs debugging information, the second local
symbol is named @stabs. */
- stabs = false;
+ 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);
+ + (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;
+ 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);
+ /* eraxxon: There are at least two problems with this computation:
+ 1) PDRs do *not* contain offsets but full vma's; and typically the
+ address of the first PDR is the address of the FDR, which will
+ make (most) of the results of the original computation 0!
+ 2) Once in a wacky while, the Compaq compiler generated PDR
+ addresses do not equal the FDR vma, but they (the PDR address)
+ are still vma's and not offsets. Cf. comments in
+ 'lookup_line'. */
/* 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;
+ tab->base_addr = fdr_ptr->adr;
}
else
{
/* XXX I don't know about stabs, so this is a guess
- (davidm@cs.arizona.edu): */
+ (davidm@cs.arizona.edu). */
tab->base_addr = fdr_ptr->adr;
}
tab->fdr = fdr_ptr;
qsort ((PTR) line_info->fdrtab, (size_t) len,
sizeof (struct ecoff_fdrtab_entry), cmp_fdrtab_entry);
- return true;
+ return TRUE;
}
/* Return index of first FDR that covers to OFFSET. */
else
low = mid + 1;
}
+
+ /* eraxxon: at this point 'offset' is either lower than the lowest entry or
+ higher than the highest entry. In the former case high = low = mid = 0;
+ we want to return -1. In the latter case, low = high and mid = low - 1;
+ we want to return the index of the highest entry. Only in former case
+ will the following 'catch-all' test be true. */
++mid;
- /* last entry is catch-all for all higher addresses: */
+ /* Last entry is catch-all for all higher addresses. */
if (offset < tab[mid].base_addr)
return -1;
find_min:
+ /* eraxxon: There may be multiple FDRs in the table with the
+ same base_addr; make sure that we are at the first one. */
while (mid > 0 && tab[mid - 1].base_addr == tab[mid].base_addr)
--mid;
/* Look up a line given an address, storing the information in
LINE_INFO->cache. */
-static boolean
+static bfd_boolean
lookup_line (abfd, debug_info, debug_swap, line_info)
bfd *abfd;
struct ecoff_debug_info * const debug_info;
{
struct ecoff_fdrtab_entry *tab;
bfd_vma offset;
- boolean stabs;
+ bfd_boolean stabs;
FDR *fdr_ptr;
int i;
+ /* eraxxon: note that 'offset' is the full vma, not a section offset. */
offset = line_info->cache.start;
/* Build FDR table (sorted by object file's base-address) if we
don't have it already. */
if (line_info->fdrtab == NULL
&& !mk_fdrtab (abfd, debug_info, debug_swap, line_info))
- return false;
+ return FALSE;
tab = line_info->fdrtab;
- /* find first FDR for address OFFSET */
+ /* Find first FDR for address OFFSET. */
i = fdrtab_lookup (line_info, offset);
if (i < 0)
- return false; /* no FDR, no fun... */
+ return FALSE; /* no FDR, no fun... */
+
+ /* eraxxon: 'fdrtab_lookup' doesn't give what we want, at least for Compaq's
+ C++ compiler 6.2. Consider three FDRs with starting addresses of x, y,
+ and z, respectively, such that x < y < z. Assume further that
+ y < 'offset' < z. It is possible at times that the PDR for 'offset' is
+ associated with FDR x and *not* with FDR y. Erg!!
+
+ From a binary dump of my C++ test case 'moo' using Compaq's coffobjanl
+ (output format has been edited for our purposes):
+
+ FDR [2]: (main.C): First instruction: 0x12000207c <x>
+ PDR [5] for File [2]: LoopTest__Xv <0x1200020a0> (a)
+ PDR [7] for File [2]: foo__Xv <0x120002168>
+ FDR [1]: (-1): First instruction: 0x1200020e8 <y>
+ PDR [3] for File [1]: <0x120001ad0> (b)
+ FDR [6]: (-1): First instruction: 0x1200026f0 <z>
+
+ (a) In the case of PDR5, the vma is such that the first few instructions
+ of the procedure can be found. But since the size of this procedure is
+ 160b, the vma will soon cross into the 'address space' of FDR1 and no
+ debugging info will be found. How repugnant!
+
+ (b) It is also possible for a PDR to have a *lower* vma than its associated
+ FDR; see FDR1 and PDR3. Gross!
+
+ Since the FDRs that are causing so much havok (in this case) 1) do not
+ describe actual files (fdr.rss == -1), and 2) contain only compiler
+ generated routines, I thought a simple fix would be to exclude them from
+ the FDR table in 'mk_fdrtab'. But, besides not knowing for certain
+ whether this would be correct, it creates an additional problem. If we
+ happen to ask for source file info on a compiler generated (procedure)
+ symbol -- which is still in the symbol table -- the result can be
+ information from a real procedure! This is because compiler generated
+ procedures with vma's higher than the last FDR in the fdr table will be
+ associated with a PDR from this FDR, specifically the PDR with the
+ highest vma. This wasn't a problem before, because each procedure had a
+ PDR. (Yes, this problem could be eliminated if we kept the size of the
+ last PDR around, but things are already getting ugly).
+
+ Probably, a better solution would be to have a sorted PDR table. Each
+ PDR would have a pointer to its FDR so file information could still be
+ obtained. A FDR table could still be constructed if necessary -- since
+ it only contains pointers, not much extra memory would be used -- but
+ the PDR table would be searched to locate debugging info.
+
+ There is still at least one remaining issue. Sometimes a FDR can have a
+ bogus name, but contain PDRs that should belong to another FDR with a
+ real name. E.g:
+
+ FDR [3]: 0000000120001b50 (/home/.../Array.H~alt~deccxx_5E5A62AD)
+ PDR [a] for File [3]: 0000000120001b50
+ PDR [b] for File [3]: 0000000120001cf0
+ PDR [c] for File [3]: 0000000120001dc8
+ PDR [d] for File [3]: 0000000120001e40
+ PDR [e] for File [3]: 0000000120001eb8
+ PDR [f] for File [3]: 0000000120001f4c
+ FDR [4]: 0000000120001b50 (/home/.../Array.H)
+
+ Here, FDR4 has the correct name, but should (seemingly) contain PDRa-f.
+ The symbol table for PDR4 does contain symbols for PDRa-f, but so does
+ the symbol table for FDR3. However the former is different; perhaps this
+ can be detected easily. (I'm not sure at this point.) This problem only
+ seems to be associated with files with templates. I am assuming the idea
+ is that there is a 'fake' FDR (with PDRs) for each differently typed set
+ of templates that must be generated. Currently, FDR4 is completely
+ excluded from the FDR table in 'mk_fdrtab' because it contains no PDRs.
+
+ Since I don't have time to prepare a real fix for this right now, be
+ prepared for 'A Horrible Hack' to force the inspection of all non-stabs
+ FDRs. It's coming... */
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;
+ stabs = FALSE;
if (fdr_ptr->csym >= 2)
{
char *sym_ptr;
(*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym);
if (strcmp (debug_info->ss + fdr_ptr->issBase + sym.iss,
STABS_SYMBOL) == 0)
- stabs = true;
+ stabs = TRUE;
}
if (!stabs)
char *pdr_ptr;
char *best_pdr = NULL;
FDR *best_fdr;
- bfd_vma best_dist = ~(bfd_vma) 0;
+ bfd_signed_vma best_dist = -1;
PDR pdr;
unsigned char *line_ptr;
unsigned char *line_end;
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;
+ /* eraxxon: The Horrible Hack: Because of the problems above, set 'i'
+ to 0 so we look through all FDRs.
+
+ Because FDR's without any symbols are assumed to be non-stabs,
+ searching through all FDRs may cause the following code to try to
+ read stabs FDRs as ECOFF ones. However, I don't think this will
+ harm anything. */
+ i = 0;
+
/* 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
{
- bfd_vma dist, min_dist = 0;
+ /* eraxxon: 'dist' and 'min_dist' can be negative now
+ because we iterate over every FDR rather than just ones
+ with a base address less than or equal to 'offset'. */
+ bfd_signed_vma dist = -1, min_dist = -1;
char *pdr_hold;
char *pdr_end;
if (offset >= (pdr.adr - 0x10 * pdr.prof))
{
dist = offset - (pdr.adr - 0x10 * pdr.prof);
- if (!pdr_hold || dist < min_dist)
+
+ /* eraxxon: 'dist' can be negative now. Note that
+ 'min_dist' can be negative if 'pdr_hold' below is NULL. */
+ if (!pdr_hold || (dist >= 0 && dist < min_dist))
{
min_dist = dist;
pdr_hold = pdr_ptr;
}
}
- if (!best_pdr || min_dist < best_dist)
+ if (!best_pdr || (min_dist >= 0 && min_dist < best_dist))
{
- best_dist = min_dist;
+ best_dist = (bfd_vma) min_dist;
best_fdr = fdr_ptr;
best_pdr = pdr_hold;
}
- /* continue looping until base_addr of next entry is different: */
+ /* Continue looping until base_addr of next entry is different. */
}
- while (++i < line_info->fdrtab_len
- && tab[i].base_addr == tab[i - 1].base_addr);
+ /* eraxxon: We want to iterate over all FDRs.
+ See previous comment about 'fdrtab_lookup'. */
+ while (++i < line_info->fdrtab_len);
if (!best_fdr || !best_pdr)
- return false; /* shouldn't happen... */
+ return FALSE; /* Shouldn't happen... */
- /* phew, finally we got something that we can hold onto: */
+ /* 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);
number entries. */
line_end = debug_info->line + fdr_ptr->cbLineOffset + fdr_ptr->cbLine;
- /* Make offset relative to procedure entry: */
+ /* 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;
const char *line_file_name;
bfd_vma low_func_vma;
bfd_vma low_line_vma;
- boolean past_line;
- boolean past_fn;
+ bfd_boolean past_line;
+ bfd_boolean past_fn;
char *sym_ptr, *sym_ptr_end;
size_t len, funclen;
char *buffer = NULL;
line_file_name = NULL;
low_func_vma = 0;
low_line_vma = 0;
- past_line = false;
- past_fn = false;
+ past_line = FALSE;
+ past_fn = FALSE;
external_sym_size = debug_swap->external_sym_size;
case N_FUN:
if (sym.value > offset)
- past_fn = true;
+ past_fn = TRUE;
else if (sym.value >= low_func_vma)
{
low_func_vma = sym.value;
else if (sym.st == stLabel && sym.index != indexNil)
{
if (sym.value > offset)
- past_line = true;
+ past_line = TRUE;
else if (sym.value >= low_line_vma)
{
low_line_vma = sym.value;
free (line_info->find_buffer);
buffer = (char *) bfd_malloc ((bfd_size_type) len);
if (buffer == NULL)
- return false;
+ return FALSE;
line_info->find_buffer = buffer;
}
}
}
- return true;
+ return TRUE;
}
/* Do the work of find_nearest_line. */
-boolean
+bfd_boolean
_bfd_ecoff_locate_line (abfd, section, offset, debug_info, debug_swap,
line_info, filename_ptr, functionname_ptr, retline_ptr)
bfd *abfd;
if (! lookup_line (abfd, debug_info, debug_swap, line_info))
{
line_info->cache.sect = NULL;
- return false;
+ return FALSE;
}
}
*functionname_ptr = line_info->cache.functionname;
*retline_ptr = line_info->cache.line_num;
- return true;
+ return TRUE;
}
\f
/* These routines copy symbolic information into a memory buffer.
/* Collect a shuffle into a memory buffer. */
-static boolean ecoff_collect_shuffle PARAMS ((struct shuffle *, bfd_byte *));
+static bfd_boolean ecoff_collect_shuffle
+ PARAMS ((struct shuffle *, bfd_byte *));
-static boolean
+static bfd_boolean
ecoff_collect_shuffle (l, buff)
struct shuffle *l;
bfd_byte *buff;
if (bfd_seek (l->u.file.input_bfd, l->u.file.offset, SEEK_SET) != 0
|| (bfd_bread (buff, (bfd_size_type) l->size, l->u.file.input_bfd)
!= l->size))
- return false;
+ return FALSE;
}
total += l->size;
buff += l->size;
}
- return true;
+ return TRUE;
}
/* Copy PDR information into a memory buffer. */
-boolean
+bfd_boolean
_bfd_ecoff_get_accumulated_pdr (handle, buff)
PTR handle;
bfd_byte *buff;
/* Copy symbol information into a memory buffer. */
-boolean
+bfd_boolean
_bfd_ecoff_get_accumulated_sym (handle, buff)
PTR handle;
bfd_byte *buff;
/* Copy the string table into a memory buffer. */
-boolean
+bfd_boolean
_bfd_ecoff_get_accumulated_ss (handle, buff)
PTR handle;
bfd_byte *buff;
buff += len + 1;
}
- return true;
+ return TRUE;
}