/* Support for the generic parts of COFF, for BFD.
- Copyright 1990, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001
+ Free Software Foundation, Inc.
Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
#include "coff/internal.h"
#include "libcoff.h"
-static boolean coff_write_symbol PARAMS ((bfd *, asymbol *,
- combined_entry_type *,
- unsigned int *));
-static boolean coff_write_alien_symbol PARAMS ((bfd *, asymbol *,
- unsigned int *));
-static boolean coff_write_native_symbol PARAMS ((bfd *, coff_symbol_type *,
- unsigned int *));
+static void coff_fix_symbol_name
+ PARAMS ((bfd *, asymbol *, combined_entry_type *, bfd_size_type *,
+ asection **, bfd_size_type *));
+static boolean coff_write_symbol
+ PARAMS ((bfd *, asymbol *, combined_entry_type *, bfd_vma *,
+ bfd_size_type *, asection **, bfd_size_type *));
+static boolean coff_write_alien_symbol
+ PARAMS ((bfd *, asymbol *, bfd_vma *, bfd_size_type *,
+ asection **, bfd_size_type *));
+static boolean coff_write_native_symbol
+ PARAMS ((bfd *, coff_symbol_type *, bfd_vma *, bfd_size_type *,
+ asection **, bfd_size_type *));
+static void coff_pointerize_aux
+ PARAMS ((bfd *, combined_entry_type *, combined_entry_type *,
+ unsigned int, combined_entry_type *));
+static boolean make_a_section_from_file
+ PARAMS ((bfd *, struct internal_scnhdr *, unsigned int));
+static const bfd_target *coff_real_object_p
+ PARAMS ((bfd *, unsigned, struct internal_filehdr *,
+ struct internal_aouthdr *));
+static void fixup_symbol_value
+ PARAMS ((bfd *, coff_symbol_type *, struct internal_syment *));
+static char *build_debug_section
+ PARAMS ((bfd *));
+static char *copy_name
+ PARAMS ((bfd *, char *, int));
#define STRING_SIZE_SIZE (4)
asection *return_section;
char *name;
- /* Assorted wastage to null-terminate the name, thanks AT&T! */
- name = bfd_alloc (abfd, sizeof (hdr->s_name) + 1);
- if (name == NULL)
+ name = NULL;
+
+ /* Handle long section names as in PE. */
+ if (bfd_coff_long_section_names (abfd)
+ && hdr->s_name[0] == '/')
{
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- strncpy (name, (char *) &hdr->s_name[0], sizeof (hdr->s_name));
- name[sizeof (hdr->s_name)] = 0;
+ char buf[SCNNMLEN];
+ long strindex;
+ char *p;
+ const char *strings;
- return_section = bfd_make_section (abfd, name);
- if (return_section == NULL)
- return_section = bfd_coff_make_section_hook (abfd, name);
+ memcpy (buf, hdr->s_name + 1, SCNNMLEN - 1);
+ buf[SCNNMLEN - 1] = '\0';
+ strindex = strtol (buf, &p, 10);
+ if (*p == '\0' && strindex >= 0)
+ {
+ strings = _bfd_coff_read_string_table (abfd);
+ if (strings == NULL)
+ return false;
+ /* FIXME: For extra safety, we should make sure that
+ strindex does not run us past the end, but right now we
+ don't know the length of the string table. */
+ strings += strindex;
+ name = bfd_alloc (abfd, strlen (strings) + 1);
+ if (name == NULL)
+ return false;
+ strcpy (name, strings);
+ }
+ }
- /* Handle several sections of the same name. For example, if an executable
- has two .bss sections, GDB better be able to find both of them
- (PR 3562). */
- if (return_section == NULL)
- return_section = bfd_make_section_anyway (abfd, name);
+ if (name == NULL)
+ {
+ /* Assorted wastage to null-terminate the name, thanks AT&T! */
+ name = bfd_alloc (abfd, sizeof (hdr->s_name) + 1);
+ if (name == NULL)
+ return false;
+ strncpy (name, (char *) &hdr->s_name[0], sizeof (hdr->s_name));
+ name[sizeof (hdr->s_name)] = 0;
+ }
+ return_section = bfd_make_section_anyway (abfd, name);
if (return_section == NULL)
return false;
- /* s_paddr is presumed to be = to s_vaddr */
-
return_section->vma = hdr->s_vaddr;
- return_section->lma = return_section->vma;
+ return_section->lma = hdr->s_paddr;
return_section->_raw_size = hdr->s_size;
return_section->filepos = hdr->s_scnptr;
return_section->rel_filepos = hdr->s_relptr;
return_section->lineno_count = hdr->s_nlnno;
return_section->userdata = NULL;
return_section->next = (asection *) NULL;
- return_section->flags = bfd_coff_styp_to_sec_flags_hook (abfd, hdr, name);
-
return_section->target_index = target_index;
+ return_section->flags = bfd_coff_styp_to_sec_flags_hook (abfd, hdr, name,
+ return_section);
/* At least on i386-coff, the line number count for a shared library
section must be ignored. */
readsize = nscns * scnhsz;
external_sections = (char *) bfd_alloc (abfd, readsize);
if (!external_sections)
- {
- bfd_set_error (bfd_error_no_memory);
- goto fail;
- }
+ goto fail;
if (bfd_read ((PTR) external_sections, 1, readsize, abfd) != readsize)
goto fail;
+ /* Set the arch/mach *before* swapping in sections; section header swapping
+ may depend on arch/mach info. */
+ if (bfd_coff_set_arch_mach_hook (abfd, (PTR) internal_f) == false)
+ goto fail;
+
/* Now copy data as required; construct all asections etc */
if (nscns != 0)
{
bfd_coff_swap_scnhdr_in (abfd,
(PTR) (external_sections + i * scnhsz),
(PTR) & tmp);
- make_a_section_from_file (abfd, &tmp, i + 1);
+ if (! make_a_section_from_file (abfd, &tmp, i + 1))
+ goto fail;
}
}
/* make_abs_section (abfd); */
- if (bfd_coff_set_arch_mach_hook (abfd, (PTR) internal_f) == false)
- goto fail;
-
return abfd->xvec;
fail:
opthdr = bfd_alloc (abfd, aoutsz);
if (opthdr == NULL)
return 0;;
- if (bfd_read (opthdr, 1, aoutsz, abfd) != aoutsz)
+ if (bfd_read (opthdr, 1, internal_f.f_opthdr, abfd)
+ != internal_f.f_opthdr)
{
return 0;
}
- bfd_coff_swap_aouthdr_in (abfd, opthdr, (PTR) & internal_a);
+ bfd_coff_swap_aouthdr_in (abfd, opthdr, (PTR) &internal_a);
}
- /* Seek past the opt hdr stuff */
- if (bfd_seek (abfd, (file_ptr) (internal_f.f_opthdr + filhsz), SEEK_SET)
- != 0)
- return NULL;
-
return coff_real_object_p (abfd, nscns, &internal_f,
(internal_f.f_opthdr != 0
? &internal_a
return (bfd_get_symcount (abfd) + 1) * (sizeof (coff_symbol_type *));
}
-
/* Canonicalize a COFF symbol table. */
long
return bfd_get_symcount (abfd);
}
+/* Get the name of a symbol. The caller must pass in a buffer of size
+ >= SYMNMLEN + 1. */
+
+const char *
+_bfd_coff_internal_syment_name (abfd, sym, buf)
+ bfd *abfd;
+ const struct internal_syment *sym;
+ char *buf;
+{
+ /* FIXME: It's not clear this will work correctly if sizeof
+ (_n_zeroes) != 4. */
+ if (sym->_n._n_n._n_zeroes != 0
+ || sym->_n._n_n._n_offset == 0)
+ {
+ memcpy (buf, sym->_n._n_name, SYMNMLEN);
+ buf[SYMNMLEN] = '\0';
+ return buf;
+ }
+ else
+ {
+ const char *strings;
+
+ BFD_ASSERT (sym->_n._n_n._n_offset >= STRING_SIZE_SIZE);
+ strings = obj_coff_strings (abfd);
+ if (strings == NULL)
+ {
+ strings = _bfd_coff_read_string_table (abfd);
+ if (strings == NULL)
+ return NULL;
+ }
+ return strings + sym->_n._n_n._n_offset;
+ }
+}
+
+/* Read in and swap the relocs. This returns a buffer holding the
+ relocs for section SEC in file ABFD. If CACHE is true and
+ INTERNAL_RELOCS is NULL, the relocs read in will be saved in case
+ the function is called again. If EXTERNAL_RELOCS is not NULL, it
+ is a buffer large enough to hold the unswapped relocs. If
+ INTERNAL_RELOCS is not NULL, it is a buffer large enough to hold
+ the swapped relocs. If REQUIRE_INTERNAL is true, then the return
+ value must be INTERNAL_RELOCS. The function returns NULL on error. */
+
+struct internal_reloc *
+_bfd_coff_read_internal_relocs (abfd, sec, cache, external_relocs,
+ require_internal, internal_relocs)
+ bfd *abfd;
+ asection *sec;
+ boolean cache;
+ bfd_byte *external_relocs;
+ boolean require_internal;
+ struct internal_reloc *internal_relocs;
+{
+ bfd_size_type relsz;
+ bfd_byte *free_external = NULL;
+ struct internal_reloc *free_internal = NULL;
+ bfd_byte *erel;
+ bfd_byte *erel_end;
+ struct internal_reloc *irel;
+
+ if (coff_section_data (abfd, sec) != NULL
+ && coff_section_data (abfd, sec)->relocs != NULL)
+ {
+ if (! require_internal)
+ return coff_section_data (abfd, sec)->relocs;
+ memcpy (internal_relocs, coff_section_data (abfd, sec)->relocs,
+ sec->reloc_count * sizeof (struct internal_reloc));
+ return internal_relocs;
+ }
+
+ relsz = bfd_coff_relsz (abfd);
+
+ if (external_relocs == NULL)
+ {
+ free_external = (bfd_byte *) bfd_malloc (sec->reloc_count * relsz);
+ if (free_external == NULL && sec->reloc_count > 0)
+ goto error_return;
+ external_relocs = free_external;
+ }
+
+ if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
+ || (bfd_read (external_relocs, relsz, sec->reloc_count, abfd)
+ != relsz * sec->reloc_count))
+ goto error_return;
+
+ if (internal_relocs == NULL)
+ {
+ free_internal = ((struct internal_reloc *)
+ bfd_malloc (sec->reloc_count
+ * sizeof (struct internal_reloc)));
+ if (free_internal == NULL && sec->reloc_count > 0)
+ goto error_return;
+ internal_relocs = free_internal;
+ }
+
+ /* Swap in the relocs. */
+ erel = external_relocs;
+ erel_end = erel + relsz * sec->reloc_count;
+ irel = internal_relocs;
+ for (; erel < erel_end; erel += relsz, irel++)
+ bfd_coff_swap_reloc_in (abfd, (PTR) erel, (PTR) irel);
+
+ if (free_external != NULL)
+ {
+ free (free_external);
+ free_external = NULL;
+ }
+
+ if (cache && free_internal != NULL)
+ {
+ if (coff_section_data (abfd, sec) == NULL)
+ {
+ sec->used_by_bfd =
+ (PTR) bfd_zalloc (abfd,
+ sizeof (struct coff_section_tdata));
+ if (sec->used_by_bfd == NULL)
+ goto error_return;
+ coff_section_data (abfd, sec)->contents = NULL;
+ }
+ coff_section_data (abfd, sec)->relocs = free_internal;
+ }
+
+ return internal_relocs;
+
+ error_return:
+ if (free_external != NULL)
+ free (free_external);
+ if (free_internal != NULL)
+ free (free_internal);
+ return NULL;
+}
+
/* Set lineno_count for the output sections of a COFF file. */
int
{
asymbol *q_maybe = *p;
- if (bfd_asymbol_flavour (q_maybe) == bfd_target_coff_flavour)
+ if (bfd_family_coff (bfd_asymbol_bfd (q_maybe)))
{
coff_symbol_type *q = coffsymbol (q_maybe);
- if (q->lineno != NULL)
+ /* The AIX 4.1 compiler can sometimes generate line numbers
+ attached to debugging symbols. We try to simply ignore
+ those here. */
+ if (q->lineno != NULL
+ && q->symbol.section->owner != NULL)
{
/* This symbol has line numbers. Increment the owning
section's linenumber count. */
/* Takes a bfd and a symbol, returns a pointer to the coff specific
area of the symbol if there is one. */
-/*ARGSUSED*/
coff_symbol_type *
coff_symbol_from (ignore_abfd, symbol)
- bfd *ignore_abfd;
+ bfd *ignore_abfd ATTRIBUTE_UNUSED;
asymbol *symbol;
{
- if (bfd_asymbol_flavour (symbol) != bfd_target_coff_flavour)
+ if (!bfd_family_coff (bfd_asymbol_bfd (symbol)))
return (coff_symbol_type *) NULL;
if (bfd_asymbol_bfd (symbol)->tdata.coff_obj_data == (coff_data_type *) NULL)
}
static void
-fixup_symbol_value (coff_symbol_ptr, syment)
+fixup_symbol_value (abfd, coff_symbol_ptr, syment)
+ bfd *abfd;
coff_symbol_type *coff_symbol_ptr;
struct internal_syment *syment;
{
syment->n_scnum = N_UNDEF;
syment->n_value = coff_symbol_ptr->symbol.value;
}
- else if (coff_symbol_ptr->symbol.flags & BSF_DEBUGGING)
+ else if ((coff_symbol_ptr->symbol.flags & BSF_DEBUGGING) != 0
+ && (coff_symbol_ptr->symbol.flags & BSF_DEBUGGING_RELOC) == 0)
{
syment->n_value = coff_symbol_ptr->symbol.value;
}
syment->n_scnum = N_UNDEF;
syment->n_value = 0;
}
+ /* FIXME: Do we need to handle the absolute section here? */
else
{
if (coff_symbol_ptr->symbol.section)
syment->n_scnum =
coff_symbol_ptr->symbol.section->output_section->target_index;
- syment->n_value =
- coff_symbol_ptr->symbol.value +
- coff_symbol_ptr->symbol.section->output_offset +
- coff_symbol_ptr->symbol.section->output_section->vma;
+ syment->n_value = (coff_symbol_ptr->symbol.value
+ + coff_symbol_ptr->symbol.section->output_offset);
+ if (! obj_pe (abfd))
+ {
+ syment->n_value += (syment->n_sclass == C_STATLAB)
+ ? coff_symbol_ptr->symbol.section->output_section->lma
+ : coff_symbol_ptr->symbol.section->output_section->vma;
+ }
}
else
{
asymbol **newsyms;
unsigned int i;
- newsyms = (asymbol **) bfd_alloc_by_size_t (bfd_ptr,
- sizeof (asymbol *)
- * (symbol_count + 1));
+ newsyms = (asymbol **) bfd_alloc (bfd_ptr,
+ sizeof (asymbol *) * (symbol_count + 1));
if (!newsyms)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
bfd_ptr->outsymbols = newsyms;
for (i = 0; i < symbol_count; i++)
- if (!bfd_is_und_section (symbol_ptr_ptr[i]->section)
- && ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL
- | BSF_NOT_AT_END
- | BSF_FUNCTION))
- != BSF_GLOBAL))
+ if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) != 0
+ || (!bfd_is_und_section (symbol_ptr_ptr[i]->section)
+ && !bfd_is_com_section (symbol_ptr_ptr[i]->section)
+ && ((symbol_ptr_ptr[i]->flags & BSF_FUNCTION) != 0
+ || ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL | BSF_WEAK))
+ == 0))))
*newsyms++ = symbol_ptr_ptr[i];
for (i = 0; i < symbol_count; i++)
- if (!bfd_is_und_section (symbol_ptr_ptr[i]->section)
- && ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL
- | BSF_NOT_AT_END
- | BSF_FUNCTION))
- == BSF_GLOBAL))
+ if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) == 0
+ && !bfd_is_und_section (symbol_ptr_ptr[i]->section)
+ && (bfd_is_com_section (symbol_ptr_ptr[i]->section)
+ || ((symbol_ptr_ptr[i]->flags & BSF_FUNCTION) == 0
+ && ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL | BSF_WEAK))
+ != 0))))
*newsyms++ = symbol_ptr_ptr[i];
*first_undef = newsyms - bfd_ptr->outsymbols;
for (i = 0; i < symbol_count; i++)
- if (bfd_is_und_section (symbol_ptr_ptr[i]->section))
+ if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) == 0
+ && bfd_is_und_section (symbol_ptr_ptr[i]->section))
*newsyms++ = symbol_ptr_ptr[i];
*newsyms = (asymbol *) NULL;
symbol_ptr_ptr = bfd_ptr->outsymbols;
for (symbol_index = 0; symbol_index < symbol_count; symbol_index++)
{
coff_symbol_type *coff_symbol_ptr = coff_symbol_from (bfd_ptr, symbol_ptr_ptr[symbol_index]);
- symbol_ptr_ptr[symbol_index]->udata.i = symbol_index;
+ symbol_ptr_ptr[symbol_index]->udata.i = symbol_index;
if (coff_symbol_ptr && coff_symbol_ptr->native)
{
combined_entry_type *s = coff_symbol_ptr->native;
/* Modify the symbol values according to their section and
type */
- fixup_symbol_value (coff_symbol_ptr, &(s->u.syment));
+ fixup_symbol_value (bfd_ptr, coff_symbol_ptr, &(s->u.syment));
}
for (i = 0; i < s->u.syment.n_numaux + 1; i++)
s[i].offset = native_index++;
if (s->fix_value)
{
/* FIXME: We should use a union here. */
- s->u.syment.n_value =
- ((combined_entry_type *) s->u.syment.n_value)->offset;
+ s->u.syment.n_value =
+ (bfd_vma)((combined_entry_type *)
+ ((unsigned long) s->u.syment.n_value))->offset;
s->fix_value = 0;
}
+ if (s->fix_line)
+ {
+ /* The value is the offset into the line number entries
+ for the symbol's section. On output, the symbol's
+ section should be N_DEBUG. */
+ s->u.syment.n_value =
+ (coff_symbol_ptr->symbol.section->output_section->line_filepos
+ + s->u.syment.n_value * bfd_coff_linesz (bfd_ptr));
+ coff_symbol_ptr->symbol.section =
+ coff_section_from_bfd_index (bfd_ptr, N_DEBUG);
+ BFD_ASSERT (coff_symbol_ptr->symbol.flags & BSF_DEBUGGING);
+ }
for (i = 0; i < s->u.syment.n_numaux; i++)
{
combined_entry_type *a = s + i + 1;
}
}
-static bfd_size_type string_size;
-static bfd_size_type debug_string_size;
-static asection *debug_string_section;
-
static void
-coff_fix_symbol_name (abfd, symbol, native)
+coff_fix_symbol_name (abfd, symbol, native, string_size_p,
+ debug_string_section_p, debug_string_size_p)
bfd *abfd;
asymbol *symbol;
combined_entry_type *native;
+ bfd_size_type *string_size_p;
+ asection **debug_string_section_p;
+ bfd_size_type *debug_string_size_p;
{
unsigned int name_length;
union internal_auxent *auxent;
}
name_length = strlen (name);
- if (native->u.syment.n_sclass == C_FILE)
+ if (native->u.syment.n_sclass == C_FILE
+ && native->u.syment.n_numaux > 0)
{
- strncpy (native->u.syment._n._n_name, ".file", SYMNMLEN);
+ unsigned int filnmlen;
+
+ if (bfd_coff_force_symnames_in_strings (abfd))
+ {
+ native->u.syment._n._n_n._n_offset =
+ (*string_size_p + STRING_SIZE_SIZE);
+ native->u.syment._n._n_n._n_zeroes = 0;
+ *string_size_p += 6; /* strlen(".file") + 1 */
+ }
+ else
+ strncpy (native->u.syment._n._n_name, ".file", SYMNMLEN);
+
auxent = &(native + 1)->u.auxent;
+ filnmlen = bfd_coff_filnmlen (abfd);
+
if (bfd_coff_long_filenames (abfd))
{
- if (name_length <= FILNMLEN)
+ if (name_length <= filnmlen)
{
- strncpy (auxent->x_file.x_fname, name, FILNMLEN);
+ strncpy (auxent->x_file.x_fname, name, filnmlen);
}
else
{
- auxent->x_file.x_n.x_offset = string_size + STRING_SIZE_SIZE;
+ auxent->x_file.x_n.x_offset = *string_size_p + STRING_SIZE_SIZE;
auxent->x_file.x_n.x_zeroes = 0;
- string_size += name_length + 1;
+ *string_size_p += name_length + 1;
}
}
else
{
- strncpy (auxent->x_file.x_fname, name, FILNMLEN);
- if (name_length > FILNMLEN)
- {
- name[FILNMLEN] = '\0';
- }
+ strncpy (auxent->x_file.x_fname, name, filnmlen);
+ if (name_length > filnmlen)
+ name[filnmlen] = '\0';
}
}
else
- { /* NOT A C_FILE SYMBOL */
- if (name_length <= SYMNMLEN)
+ {
+ if (name_length <= SYMNMLEN && !bfd_coff_force_symnames_in_strings (abfd))
{
/* This name will fit into the symbol neatly */
strncpy (native->u.syment._n._n_name, symbol->name, SYMNMLEN);
}
else if (!bfd_coff_symname_in_debug (abfd, &native->u.syment))
{
- native->u.syment._n._n_n._n_offset = string_size + STRING_SIZE_SIZE;
+ native->u.syment._n._n_n._n_offset = (*string_size_p
+ + STRING_SIZE_SIZE);
native->u.syment._n._n_n._n_zeroes = 0;
- string_size += name_length + 1;
+ *string_size_p += name_length + 1;
}
else
{
long filepos;
- bfd_byte buf[2];
+ bfd_byte buf[4];
+ int prefix_len = bfd_coff_debug_string_prefix_length (abfd);
/* This name should be written into the .debug section. For
some reason each name is preceded by a two byte length
and also followed by a null byte. FIXME: We assume that
the .debug section has already been created, and that it
is large enough. */
- if (debug_string_section == (asection *) NULL)
- debug_string_section = bfd_get_section_by_name (abfd, ".debug");
+ if (*debug_string_section_p == (asection *) NULL)
+ *debug_string_section_p = bfd_get_section_by_name (abfd, ".debug");
filepos = bfd_tell (abfd);
- bfd_put_16 (abfd, name_length + 1, buf);
+ if (prefix_len == 4)
+ bfd_put_32 (abfd, name_length + 1, buf);
+ else
+ bfd_put_16 (abfd, name_length + 1, buf);
+
if (!bfd_set_section_contents (abfd,
- debug_string_section,
+ *debug_string_section_p,
(PTR) buf,
- (file_ptr) debug_string_size,
- (bfd_size_type) 2)
+ (file_ptr) *debug_string_size_p,
+ (bfd_size_type) prefix_len)
|| !bfd_set_section_contents (abfd,
- debug_string_section,
+ *debug_string_section_p,
(PTR) symbol->name,
- (file_ptr) debug_string_size + 2,
+ ((file_ptr) *debug_string_size_p
+ + prefix_len),
(bfd_size_type) name_length + 1))
abort ();
if (bfd_seek (abfd, filepos, SEEK_SET) != 0)
abort ();
- native->u.syment._n._n_n._n_offset = debug_string_size + 2;
+ native->u.syment._n._n_n._n_offset =
+ *debug_string_size_p + prefix_len;
native->u.syment._n._n_n._n_zeroes = 0;
- debug_string_size += name_length + 3;
+ *debug_string_size_p += name_length + 1 + prefix_len;
}
}
}
/* Write a symbol out to a COFF file. */
static boolean
-coff_write_symbol (abfd, symbol, native, written)
+coff_write_symbol (abfd, symbol, native, written, string_size_p,
+ debug_string_section_p, debug_string_size_p)
bfd *abfd;
asymbol *symbol;
combined_entry_type *native;
- unsigned int *written;
+ bfd_vma *written;
+ bfd_size_type *string_size_p;
+ asection **debug_string_section_p;
+ bfd_size_type *debug_string_size_p;
{
unsigned int numaux = native->u.syment.n_numaux;
int type = native->u.syment.n_type;
if (native->u.syment.n_sclass == C_FILE)
symbol->flags |= BSF_DEBUGGING;
- if (symbol->flags & BSF_DEBUGGING)
+ if (symbol->flags & BSF_DEBUGGING
+ && bfd_is_abs_section (symbol->section))
{
native->u.syment.n_scnum = N_DEBUG;
}
symbol->section->output_section->target_index;
}
- coff_fix_symbol_name (abfd, symbol, native);
+ coff_fix_symbol_name (abfd, symbol, native, string_size_p,
+ debug_string_section_p, debug_string_size_p);
symesz = bfd_coff_symesz (abfd);
buf = bfd_alloc (abfd, symesz);
if (!buf)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
bfd_coff_swap_sym_out (abfd, &native->u.syment, buf);
if (bfd_write (buf, 1, symesz, abfd) != symesz)
return false;
auxesz = bfd_coff_auxesz (abfd);
buf = bfd_alloc (abfd, auxesz);
if (!buf)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
for (j = 0; j < native->u.syment.n_numaux; j++)
{
bfd_coff_swap_aux_out (abfd,
or we may be linking a non COFF file to a COFF file. */
static boolean
-coff_write_alien_symbol (abfd, symbol, written)
+coff_write_alien_symbol (abfd, symbol, written, string_size_p,
+ debug_string_section_p, debug_string_size_p)
bfd *abfd;
asymbol *symbol;
- unsigned int *written;
+ bfd_vma *written;
+ bfd_size_type *string_size_p;
+ asection **debug_string_section_p;
+ bfd_size_type *debug_string_size_p;
{
combined_entry_type *native;
combined_entry_type dummy;
native->u.syment.n_scnum =
symbol->section->output_section->target_index;
native->u.syment.n_value = (symbol->value
- + symbol->section->output_section->vma
+ symbol->section->output_offset);
+ if (! obj_pe (abfd))
+ native->u.syment.n_value += symbol->section->output_section->vma;
/* Copy the any flags from the the file header into the symbol.
FIXME: Why? */
native->u.syment.n_type = 0;
if (symbol->flags & BSF_LOCAL)
native->u.syment.n_sclass = C_STAT;
+ else if (symbol->flags & BSF_WEAK)
+ native->u.syment.n_sclass = obj_pe (abfd) ? C_NT_WEAK : C_WEAKEXT;
else
native->u.syment.n_sclass = C_EXT;
native->u.syment.n_numaux = 0;
- return coff_write_symbol (abfd, symbol, native, written);
+ return coff_write_symbol (abfd, symbol, native, written, string_size_p,
+ debug_string_section_p, debug_string_size_p);
}
/* Write a native symbol to a COFF file. */
static boolean
-coff_write_native_symbol (abfd, symbol, written)
+coff_write_native_symbol (abfd, symbol, written, string_size_p,
+ debug_string_section_p, debug_string_size_p)
bfd *abfd;
coff_symbol_type *symbol;
- unsigned int *written;
+ bfd_vma *written;
+ bfd_size_type *string_size_p;
+ asection **debug_string_section_p;
+ bfd_size_type *debug_string_size_p;
{
combined_entry_type *native = symbol->native;
alent *lineno = symbol->lineno;
/* If this symbol has an associated line number, we must store the
symbol index in the line number field. We also tag the auxent to
point to the right place in the lineno table. */
- if (lineno && !symbol->done_lineno)
+ if (lineno && !symbol->done_lineno && symbol->symbol.section->owner != NULL)
{
unsigned int count = 0;
lineno[count].u.offset = *written;
while (lineno[count].line_number != 0)
{
#if 0
- /* 13 april 92. sac
+ /* 13 april 92. sac
I've been told this, but still need proof:
> The second bug is also in `bfd/coffcode.h'. This bug
> causes the linker to screw up the pc-relocations for
count * bfd_coff_linesz (abfd);
}
- return coff_write_symbol (abfd, &(symbol->symbol), native, written);
+ return coff_write_symbol (abfd, &(symbol->symbol), native, written,
+ string_size_p, debug_string_section_p,
+ debug_string_size_p);
}
/* Write out the COFF symbols. */
coff_write_symbols (abfd)
bfd *abfd;
{
+ bfd_size_type string_size;
+ asection *debug_string_section;
+ bfd_size_type debug_string_size;
unsigned int i;
unsigned int limit = bfd_get_symcount (abfd);
- unsigned int written = 0;
+ bfd_signed_vma written = 0;
asymbol **p;
string_size = 0;
+ debug_string_section = NULL;
debug_string_size = 0;
+ /* If this target supports long section names, they must be put into
+ the string table. This is supported by PE. This code must
+ handle section names just as they are handled in
+ coff_write_object_contents. */
+ if (bfd_coff_long_section_names (abfd))
+ {
+ asection *o;
+
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ size_t len;
+
+ len = strlen (o->name);
+ if (len > SCNNMLEN)
+ string_size += len + 1;
+ }
+ }
+
/* Seek to the right place */
if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0)
return false;
if (c_symbol == (coff_symbol_type *) NULL
|| c_symbol->native == (combined_entry_type *) NULL)
{
- if (!coff_write_alien_symbol (abfd, symbol, &written))
+ if (!coff_write_alien_symbol (abfd, symbol, &written, &string_size,
+ &debug_string_section,
+ &debug_string_size))
return false;
}
else
{
- if (!coff_write_native_symbol (abfd, c_symbol, &written))
+ if (!coff_write_native_symbol (abfd, c_symbol, &written,
+ &string_size, &debug_string_section,
+ &debug_string_size))
return false;
}
}
#endif
if (bfd_write ((PTR) buffer, 1, sizeof (buffer), abfd) != sizeof (buffer))
return false;
+
+ /* Handle long section names. This code must handle section
+ names just as they are handled in coff_write_object_contents. */
+ if (bfd_coff_long_section_names (abfd))
+ {
+ asection *o;
+
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ size_t len;
+
+ len = strlen (o->name);
+ if (len > SCNNMLEN)
+ {
+ if (bfd_write (o->name, 1, len + 1, abfd) != len + 1)
+ return false;
+ }
+ }
+ }
+
for (p = abfd->outsymbols, i = 0;
i < limit;
i++, p++)
{
/* This is not a COFF symbol, so it certainly is not a
file name, nor does it go in the .debug section. */
- maxlen = SYMNMLEN;
+ maxlen = bfd_coff_force_symnames_in_strings (abfd) ? 0 : SYMNMLEN;
}
else if (bfd_coff_symname_in_debug (abfd,
&c_symbol->native->u.syment))
Don't write it into the string table. */
maxlen = name_length;
}
- else if (c_symbol->native->u.syment.n_sclass == C_FILE)
- maxlen = FILNMLEN;
+ else if (c_symbol->native->u.syment.n_sclass == C_FILE
+ && c_symbol->native->u.syment.n_numaux > 0)
+ {
+ if (bfd_coff_force_symnames_in_strings (abfd))
+ bfd_write (".file", 1, 6, abfd);
+ maxlen = bfd_coff_filnmlen (abfd);
+ }
else
- maxlen = SYMNMLEN;
+ maxlen = bfd_coff_force_symnames_in_strings (abfd) ? 0 : SYMNMLEN;
if (name_length > maxlen)
{
linesz = bfd_coff_linesz (abfd);
buff = bfd_alloc (abfd, linesz);
if (!buff)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
for (s = abfd->sections; s != (asection *) NULL; s = s->next)
{
if (s->lineno_count)
return true;
}
-/*ARGSUSED */
alent *
coff_get_lineno (ignore_abfd, symbol)
- bfd *ignore_abfd;
+ bfd *ignore_abfd ATTRIBUTE_UNUSED;
asymbol *symbol;
{
return coffsymbol (symbol)->lineno;
}
+#if 0
+
+/* This is only called from coff_add_missing_symbols, which has been
+ disabled. */
+
asymbol *
coff_section_symbol (abfd, name)
bfd *abfd;
combined_entry_type e[10];
};
struct foo *f;
- f = (struct foo *) bfd_alloc_by_size_t (abfd, sizeof (*f));
+ f = (struct foo *) bfd_alloc (abfd, sizeof (*f));
if (!f)
{
bfd_set_error (bfd_error_no_error);
return sym;
}
+#endif /* 0 */
+
/* This function transforms the offsets into the symbol table into
pointers to syments. */
static void
-coff_pointerize_aux (abfd, table_base, type, class, auxent)
+coff_pointerize_aux (abfd, table_base, symbol, indaux, auxent)
bfd *abfd;
combined_entry_type *table_base;
- unsigned int type;
- unsigned int class;
+ combined_entry_type *symbol;
+ unsigned int indaux;
combined_entry_type *auxent;
{
+ unsigned int type = symbol->u.syment.n_type;
+ unsigned int class = symbol->u.syment.n_sclass;
+
+ if (coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook)
+ {
+ if ((*coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook)
+ (abfd, table_base, symbol, indaux, auxent))
+ return;
+ }
+
/* Don't bother if this is a file or a section */
if (class == C_STAT && type == T_NULL)
return;
/* Otherwise patch up */
#define N_TMASK coff_data (abfd)->local_n_tmask
#define N_BTSHFT coff_data (abfd)->local_n_btshft
- if ((ISFCN (type) || ISTAG (class) || class == C_BLOCK)
+ if ((ISFCN (type) || ISTAG (class) || class == C_BLOCK || class == C_FCN)
&& auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l > 0)
{
auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p =
- (table_base
- + auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l);
+ table_base + auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l;
auxent->fix_end = 1;
}
/* A negative tagndx is meaningless, but the SCO 3.2v4 cc can
/* Allocate space for the ".debug" section, and read it.
We did not read the debug section until now, because
- we didn't want to go to the trouble until someone needed it. */
+ we didn't want to go to the trouble until someone needed it. */
static char *
build_debug_section (abfd)
debug_section = (PTR) bfd_alloc (abfd,
bfd_get_section_size_before_reloc (sect));
if (debug_section == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
+ return NULL;
- /* Seek to the beginning of the `.debug' section and read it.
+ /* Seek to the beginning of the `.debug' section and read it.
Save the current position first; it is needed by our caller.
Then read debug section and reset the file pointer. */
return debug_section;
}
-
/* Return a pointer to a malloc'd copy of 'name'. 'name' may not be
\0-terminated, but will not exceed 'maxlen' characters. The copy *will*
be \0-terminated. */
}
if ((newname = (PTR) bfd_alloc (abfd, len + 1)) == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return (NULL);
- }
+ return (NULL);
strncpy (newname, name, len);
newname[len] = '\0';
return newname;
size = obj_raw_syment_count (abfd) * symesz;
- syms = malloc (size);
+ syms = (PTR) bfd_malloc (size);
if (syms == NULL && size != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
|| bfd_read (syms, size, 1, abfd) != size)
if (obj_coff_strings (abfd) != NULL)
return obj_coff_strings (abfd);
+ if (obj_sym_filepos (abfd) == 0)
+ {
+ bfd_set_error (bfd_error_no_symbols);
+ return NULL;
+ }
+
if (bfd_seek (abfd,
(obj_sym_filepos (abfd)
+ obj_raw_syment_count (abfd) * bfd_coff_symesz (abfd)),
SEEK_SET) != 0)
return NULL;
-
+
if (bfd_read (extstrsize, sizeof extstrsize, 1, abfd) != sizeof extstrsize)
{
if (bfd_get_error () != bfd_error_file_truncated)
#endif
}
- strings = malloc (strsize);
- if (strings == NULL)
+ if (strsize < STRING_SIZE_SIZE)
{
- bfd_set_error (bfd_error_no_memory);
+ (*_bfd_error_handler)
+ (_("%s: bad string table size %lu"), bfd_get_filename (abfd),
+ (unsigned long) strsize);
+ bfd_set_error (bfd_error_bad_value);
return NULL;
}
+ strings = (char *) bfd_malloc (strsize);
+ if (strings == NULL)
+ return NULL;
+
if (bfd_read (strings + STRING_SIZE_SIZE,
strsize - STRING_SIZE_SIZE, 1, abfd)
!= strsize - STRING_SIZE_SIZE)
return obj_raw_syments (abfd);
size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type);
- internal = (combined_entry_type *) bfd_alloc (abfd, size);
+ internal = (combined_entry_type *) bfd_zalloc (abfd, size);
if (internal == NULL && size != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
+ return NULL;
internal_end = internal + obj_raw_syment_count (abfd);
if (! _bfd_coff_get_external_symbols (abfd))
unsigned int i;
bfd_coff_swap_sym_in (abfd, (PTR) raw_src,
(PTR) & internal_ptr->u.syment);
- internal_ptr->fix_value = 0;
- internal_ptr->fix_tag = 0;
- internal_ptr->fix_end = 0;
- internal_ptr->fix_scnlen = 0;
symbol_ptr = internal_ptr;
for (i = 0;
{
internal_ptr++;
raw_src += symesz;
-
- internal_ptr->fix_value = 0;
- internal_ptr->fix_tag = 0;
- internal_ptr->fix_end = 0;
- internal_ptr->fix_scnlen = 0;
bfd_coff_swap_aux_in (abfd, (PTR) raw_src,
symbol_ptr->u.syment.n_type,
symbol_ptr->u.syment.n_sclass,
i, symbol_ptr->u.syment.n_numaux,
&(internal_ptr->u.auxent));
- /* Remember that bal entries arn't pointerized */
- if (i != 1 || symbol_ptr->u.syment.n_sclass != C_LEAFPROC)
- {
-
- coff_pointerize_aux (abfd,
- internal,
- symbol_ptr->u.syment.n_type,
- symbol_ptr->u.syment.n_sclass,
- internal_ptr);
- }
-
+ coff_pointerize_aux (abfd, internal, symbol_ptr, i,
+ internal_ptr);
}
}
}
else
{
- /* ordinary short filename, put into memory anyway */
- internal_ptr->u.syment._n._n_n._n_offset = (long)
- copy_name (abfd, (internal_ptr + 1)->u.auxent.x_file.x_fname,
- FILNMLEN);
+ /* Ordinary short filename, put into memory anyway. The
+ Microsoft PE tools sometimes store a filename in
+ multiple AUX entries. */
+ if (internal_ptr->u.syment.n_numaux > 1
+ && coff_data (abfd)->pe)
+ {
+ internal_ptr->u.syment._n._n_n._n_offset =
+ ((long)
+ copy_name (abfd,
+ (internal_ptr + 1)->u.auxent.x_file.x_fname,
+ internal_ptr->u.syment.n_numaux * symesz));
+ }
+ else
+ {
+ internal_ptr->u.syment._n._n_n._n_offset =
+ ((long)
+ copy_name (abfd,
+ (internal_ptr + 1)->u.auxent.x_file.x_fname,
+ bfd_coff_filnmlen (abfd)));
+ }
}
}
else
{
break;
} /* if end of string */
- } /* possible lengths of this string. */
+ } /* possible lengths of this string. */
if ((newstring = (PTR) bfd_alloc (abfd, ++i)) == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return (NULL);
- } /* on error */
+ return (NULL);
memset (newstring, 0, i);
strncpy (newstring, internal_ptr->u.syment._n._n_name, i - 1);
internal_ptr->u.syment._n._n_n._n_offset = (long int) newstring;
{
coff_symbol_type *new = (coff_symbol_type *) bfd_alloc (abfd, sizeof (coff_symbol_type));
if (new == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return (NULL);
- } /* on error */
+ return (NULL);
memset (new, 0, sizeof *new);
new->symbol.section = 0;
new->native = 0;
asymbol *
coff_bfd_make_debug_symbol (abfd, ptr, sz)
bfd *abfd;
- PTR ptr;
- unsigned long sz;
+ PTR ptr ATTRIBUTE_UNUSED;
+ unsigned long sz ATTRIBUTE_UNUSED;
{
coff_symbol_type *new = (coff_symbol_type *) bfd_alloc (abfd, sizeof (coff_symbol_type));
if (new == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return (NULL);
- } /* on error */
- /* @@ This shouldn't be using a constant multiplier. */
+ return (NULL);
+ /* @@ The 10 is a guess at a plausible maximum number of aux entries
+ (but shouldn't be a constant). */
new->native = (combined_entry_type *) bfd_zalloc (abfd, sizeof (combined_entry_type) * 10);
if (!new->native)
- {
- bfd_set_error (bfd_error_no_memory);
- return (NULL);
- } /* on error */
+ return (NULL);
new->symbol.section = bfd_abs_section_ptr;
new->symbol.flags = BSF_DEBUGGING;
new->lineno = (alent *) NULL;
return &new->symbol;
}
-/*ARGSUSED */
void
coff_get_symbol_info (abfd, symbol, ret)
bfd *abfd;
symbol_info *ret;
{
bfd_symbol_info (symbol, ret);
+ if (coffsymbol (symbol)->native != NULL
+ && coffsymbol (symbol)->native->fix_value)
+ {
+ ret->value = coffsymbol (symbol)->native->u.syment.n_value -
+ (unsigned long) obj_raw_syments (abfd);
+ }
+}
+
+/* Return the COFF syment for a symbol. */
+
+boolean
+bfd_coff_get_syment (abfd, symbol, psyment)
+ bfd *abfd;
+ asymbol *symbol;
+ struct internal_syment *psyment;
+{
+ coff_symbol_type *csym;
+
+ csym = coff_symbol_from (abfd, symbol);
+ if (csym == NULL || csym->native == NULL)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+
+ *psyment = csym->native->u.syment;
+
+ if (csym->native->fix_value)
+ psyment->n_value = psyment->n_value -
+ (unsigned long) obj_raw_syments (abfd);
+
+ /* FIXME: We should handle fix_line here. */
+
+ return true;
+}
+
+/* Return the COFF auxent for a symbol. */
+
+boolean
+bfd_coff_get_auxent (abfd, symbol, indx, pauxent)
+ bfd *abfd;
+ asymbol *symbol;
+ int indx;
+ union internal_auxent *pauxent;
+{
+ coff_symbol_type *csym;
+ combined_entry_type *ent;
+
+ csym = coff_symbol_from (abfd, symbol);
+
+ if (csym == NULL
+ || csym->native == NULL
+ || indx >= csym->native->u.syment.n_numaux)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+
+ ent = csym->native + indx + 1;
+
+ *pauxent = ent->u.auxent;
+
+ if (ent->fix_tag)
+ pauxent->x_sym.x_tagndx.l =
+ ((combined_entry_type *) pauxent->x_sym.x_tagndx.p
+ - obj_raw_syments (abfd));
+
+ if (ent->fix_end)
+ pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l =
+ ((combined_entry_type *) pauxent->x_sym.x_fcnary.x_fcn.x_endndx.p
+ - obj_raw_syments (abfd));
+
+ if (ent->fix_scnlen)
+ pauxent->x_csect.x_scnlen.l =
+ ((combined_entry_type *) pauxent->x_csect.x_scnlen.p
+ - obj_raw_syments (abfd));
+
+ return true;
}
/* Print out information about COFF symbol. */
case bfd_print_symbol_all:
if (coffsymbol (symbol)->native)
{
+ bfd_vma val;
unsigned int aux;
combined_entry_type *combined = coffsymbol (symbol)->native;
combined_entry_type *root = obj_raw_syments (abfd);
fprintf (file, "[%3ld]", (long) (combined - root));
+ if (! combined->fix_value)
+ val = (bfd_vma) combined->u.syment.n_value;
+ else
+ val = combined->u.syment.n_value - (unsigned long) root;
+
+#ifndef XCOFF64
fprintf (file,
"(sec %2d)(fl 0x%02x)(ty %3x)(scl %3d) (nx %d) 0x%08lx %s",
combined->u.syment.n_scnum,
combined->u.syment.n_type,
combined->u.syment.n_sclass,
combined->u.syment.n_numaux,
- (unsigned long) combined->u.syment.n_value,
+ (unsigned long) val,
symbol->name);
+#else
+ /* Print out the wide, 64 bit, symbol value */
+ fprintf (file,
+ "(sec %2d)(fl 0x%02x)(ty %3x)(scl %3d) (nx %d) 0x%016llx %s",
+ combined->u.syment.n_scnum,
+ combined->u.syment.n_flags,
+ combined->u.syment.n_type,
+ combined->u.syment.n_sclass,
+ combined->u.syment.n_numaux,
+ val,
+ symbol->name);
+#endif
for (aux = 0; aux < combined->u.syment.n_numaux; aux++)
{
tagndx = auxp->u.auxent.x_sym.x_tagndx.l;
fprintf (file, "\n");
+
+ if (bfd_coff_print_aux (abfd, file, root, combined, auxp, aux))
+ continue;
+
switch (combined->u.syment.n_sclass)
{
case C_FILE:
(long) auxp->u.auxent.x_scn.x_scnlen,
auxp->u.auxent.x_scn.x_nreloc,
auxp->u.auxent.x_scn.x_nlinno);
+ if (auxp->u.auxent.x_scn.x_checksum != 0
+ || auxp->u.auxent.x_scn.x_associated != 0
+ || auxp->u.auxent.x_scn.x_comdat != 0)
+ fprintf (file, " checksum 0x%lx assoc %d comdat %d",
+ auxp->u.auxent.x_scn.x_checksum,
+ auxp->u.auxent.x_scn.x_associated,
+ auxp->u.auxent.x_scn.x_comdat);
+ break;
+ }
+ /* else fall through */
+ case C_EXT:
+ if (ISFCN (combined->u.syment.n_type))
+ {
+ fprintf (file,
+ _("AUX tagndx %ld ttlsiz 0x%lx lnnos %ld next %ld"),
+ tagndx,
+ auxp->u.auxent.x_sym.x_misc.x_fsize,
+ auxp->u.auxent.x_sym.x_fcnary.x_fcn.x_lnnoptr,
+ (auxp->fix_end
+ ? ((long)
+ (auxp->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p
+ - root))
+ : auxp->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l));
break;
}
/* else fall through */
-
default:
fprintf (file, "AUX lnno %d size 0x%x tagndx %ld",
auxp->u.auxent.x_sym.x_misc.x_lnsz.x_lnno,
}
}
-/* 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. */
+/* Return whether a symbol name implies a local symbol. In COFF,
+ local symbols generally start with ``.L''. Most targets use this
+ function for the is_local_label_name entry point, but some may
+ override it. */
-/*ARGSUSED*/
boolean
-coff_find_nearest_line (abfd, section, ignore_symbols, offset, filename_ptr,
+_bfd_coff_is_local_label_name (abfd, name)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ const char *name;
+{
+ return name[0] == '.' && name[1] == 'L';
+}
+
+/* Provided a BFD, a section and an offset (in bytes, not octets) into the
+ section, calculate and return the name of the source file and the line
+ nearest to the wanted location. */
+
+boolean
+coff_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
functionname_ptr, line_ptr)
bfd *abfd;
asection *section;
- asymbol **ignore_symbols;
+ asymbol **symbols;
bfd_vma offset;
CONST char **filename_ptr;
CONST char **functionname_ptr;
unsigned int *line_ptr;
{
+ boolean found;
unsigned int i;
unsigned int line_base;
coff_data_type *cof = coff_data (abfd);
alent *l;
struct coff_section_tdata *sec_data;
+ /* Before looking through the symbol table, try to use a .stab
+ section to find the information. */
+ if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
+ &found, filename_ptr,
+ functionname_ptr, line_ptr,
+ &coff_data(abfd)->line_info))
+ return false;
+
+ if (found)
+ return true;
+
+ /* Also try examining DWARF2 debugging information. */
+ if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
+ filename_ptr, functionname_ptr,
+ line_ptr, 0,
+ &coff_data(abfd)->dwarf2_find_line_info))
+ return true;
+
*filename_ptr = 0;
*functionname_ptr = 0;
*line_ptr = 0;
/* Don't try and find line numbers in a non coff file */
- if (abfd->xvec->flavour != bfd_target_coff_flavour)
+ if (!bfd_family_coff (abfd))
return false;
if (cof == NULL)
/* Find the first C_FILE symbol. */
p = cof->raw_syments;
+ if (!p)
+ return false;
+
pend = p + cof->raw_syment_count;
while (p < pend)
{
if (p < pend)
{
+ bfd_vma sec_vma;
bfd_vma maxdiff;
/* Look through the C_FILE symbols to find the best one. */
+ sec_vma = bfd_get_section_vma (abfd, section);
*filename_ptr = (char *) p->u.syment._n._n_n._n_offset;
maxdiff = (bfd_vma) 0 - (bfd_vma) 1;
while (1)
}
}
+ /* We use <= MAXDIFF here so that if we get a zero length
+ file, we actually use the next file entry. */
if (p2 < pend
- && offset >= (bfd_vma) p2->u.syment.n_value
- && offset - (bfd_vma) p2->u.syment.n_value < maxdiff)
+ && offset + sec_vma >= (bfd_vma) p2->u.syment.n_value
+ && offset + sec_vma - (bfd_vma) p2->u.syment.n_value <= maxdiff)
{
*filename_ptr = (char *) p->u.syment._n._n_n._n_offset;
- maxdiff = offset - p2->u.syment.n_value;
+ maxdiff = offset + sec_vma - p2->u.syment.n_value;
}
/* Avoid endless loops on erroneous files by ensuring that
line_base = 0;
}
- l = §ion->lineno[i];
-
- for (; i < section->lineno_count; i++)
+ if (section->lineno != NULL)
{
- if (l->line_number == 0)
+ bfd_vma last_value = 0;
+
+ l = §ion->lineno[i];
+
+ for (; i < section->lineno_count; i++)
{
- /* Get the symbol this line number points at */
- coff_symbol_type *coff = (coff_symbol_type *) (l->u.sym);
- if (coff->symbol.value > offset)
- break;
- *functionname_ptr = coff->symbol.name;
- if (coff->native)
+ if (l->line_number == 0)
{
- combined_entry_type *s = coff->native;
- s = s + 1 + s->u.syment.n_numaux;
-
- /* In XCOFF a debugging symbol can follow the function
- symbol. */
- if (s->u.syment.n_scnum == N_DEBUG)
- s = s + 1 + s->u.syment.n_numaux;
-
- /*
- S should now point to the .bf of the function
- */
- if (s->u.syment.n_numaux)
+ /* Get the symbol this line number points at */
+ coff_symbol_type *coff = (coff_symbol_type *) (l->u.sym);
+ if (coff->symbol.value > offset)
+ break;
+ *functionname_ptr = coff->symbol.name;
+ last_value = coff->symbol.value;
+ if (coff->native)
{
- /*
- The linenumber is stored in the auxent
- */
- union internal_auxent *a = &((s + 1)->u.auxent);
- line_base = a->x_sym.x_misc.x_lnsz.x_lnno;
- *line_ptr = line_base;
+ combined_entry_type *s = coff->native;
+ s = s + 1 + s->u.syment.n_numaux;
+
+ /* In XCOFF a debugging symbol can follow the
+ function symbol. */
+ if (s->u.syment.n_scnum == N_DEBUG)
+ s = s + 1 + s->u.syment.n_numaux;
+
+ /* S should now point to the .bf of the function. */
+ if (s->u.syment.n_numaux)
+ {
+ /* The linenumber is stored in the auxent. */
+ union internal_auxent *a = &((s + 1)->u.auxent);
+ line_base = a->x_sym.x_misc.x_lnsz.x_lnno;
+ *line_ptr = line_base;
+ }
}
}
+ else
+ {
+ if (l->u.offset > offset)
+ break;
+ *line_ptr = l->line_number + line_base - 1;
+ }
+ l++;
}
- else
+
+ /* If we fell off the end of the loop, then assume that this
+ symbol has no line number info. Otherwise, symbols with no
+ line number info get reported with the line number of the
+ last line of the last symbol which does have line number
+ info. We use 0x100 as a slop to account for cases where the
+ last line has executable code. */
+ if (i >= section->lineno_count
+ && last_value != 0
+ && offset - last_value > 0x100)
{
- if (l->u.offset + bfd_get_section_vma (abfd, section) > offset)
- break;
- *line_ptr = l->line_number + line_base - 1;
+ *functionname_ptr = NULL;
+ *line_ptr = 0;
}
- l++;
}
/* Cache the results for the next call. */
- if (sec_data == NULL)
+ if (sec_data == NULL && section->owner == abfd)
{
section->used_by_bfd =
((PTR) bfd_zalloc (abfd,
sizeof (struct coff_section_tdata)));
- sec_data = section->used_by_bfd;
+ sec_data = (struct coff_section_tdata *) section->used_by_bfd;
}
if (sec_data != NULL)
{
size += abfd->section_count * bfd_coff_scnhsz (abfd);
return size;
}
+
+/* Change the class of a coff symbol held by BFD. */
+boolean
+bfd_coff_set_symbol_class (abfd, symbol, class)
+ bfd * abfd;
+ asymbol * symbol;
+ unsigned int class;
+{
+ coff_symbol_type * csym;
+
+ csym = coff_symbol_from (abfd, symbol);
+ if (csym == NULL)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+ else if (csym->native == NULL)
+ {
+ /* This is an alien symbol which no native coff backend data.
+ We cheat here by creating a fake native entry for it and
+ then filling in the class. This code is based on that in
+ coff_write_alien_symbol(). */
+
+ combined_entry_type * native;
+
+ native = (combined_entry_type *) bfd_alloc (abfd, sizeof (* native));
+ if (native == NULL)
+ return false;
+
+ memset (native, 0, sizeof (* native));
+
+ native->u.syment.n_type = T_NULL;
+ native->u.syment.n_sclass = class;
+
+ if (bfd_is_und_section (symbol->section))
+ {
+ native->u.syment.n_scnum = N_UNDEF;
+ native->u.syment.n_value = symbol->value;
+ }
+ else if (bfd_is_com_section (symbol->section))
+ {
+ native->u.syment.n_scnum = N_UNDEF;
+ native->u.syment.n_value = symbol->value;
+ }
+ else
+ {
+ native->u.syment.n_scnum =
+ symbol->section->output_section->target_index;
+ native->u.syment.n_value = (symbol->value
+ + symbol->section->output_offset);
+ if (! obj_pe (abfd))
+ native->u.syment.n_value += symbol->section->output_section->vma;
+
+ /* Copy the any flags from the the file header into the symbol.
+ FIXME: Why? */
+ native->u.syment.n_flags = bfd_asymbol_bfd (& csym->symbol)->flags;
+ }
+
+ csym->native = native;
+ }
+ else
+ {
+ csym->native->u.syment.n_sclass = class;
+ }
+
+ return true;
+}