/* Support for the generic parts of COFF, for BFD.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Written by Cygnus Support.
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
+ 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,
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. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
/* Most of this hacked by Steve Chamberlain, sac@cygnus.com.
Split out of coffcode.h by Ian Taylor, ian@cygnus.com. */
Those functions may not use any COFF specific information, such as
coff_data (abfd). */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "libbfd.h"
#include "coff/internal.h"
#include "libcoff.h"
name = NULL;
- /* Handle long section names as in PE. */
- if (bfd_coff_long_section_names (abfd)
+ /* Handle long section names as in PE. On reading, we want to
+ accept long names if the format permits them at all, regardless
+ of the current state of the flag that dictates if we would generate
+ them in outputs; this construct checks if that is the case by
+ attempting to set the flag, without changing its state; the call
+ will fail for formats that do not support long names at all. */
+ if (bfd_coff_set_long_section_names (abfd, bfd_coff_long_section_names (abfd))
&& hdr->s_name[0] == '/')
{
char buf[SCNNMLEN];
char *p;
const char *strings;
+ /* Flag that this BFD uses long names, even though the format might
+ expect them to be off by default. This won't directly affect the
+ format of any output BFD created from this one, but the information
+ can be used to decide what to do. */
+ bfd_coff_set_long_section_names (abfd, TRUE);
memcpy (buf, hdr->s_name + 1, SCNNMLEN - 1);
buf[SCNNMLEN - 1] = '\0';
strindex = strtol (buf, &p, 10);
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, (bfd_size_type) strlen (strings) + 1);
+ name = (char *) bfd_alloc (abfd,
+ (bfd_size_type) strlen (strings) + 1);
if (name == NULL)
return FALSE;
strcpy (name, strings);
if (name == NULL)
{
/* Assorted wastage to null-terminate the name, thanks AT&T! */
- name = bfd_alloc (abfd, (bfd_size_type) sizeof (hdr->s_name) + 1);
+ name = (char *) bfd_alloc (abfd,
+ (bfd_size_type) sizeof (hdr->s_name) + 1);
if (name == NULL)
return FALSE;
strncpy (name, (char *) &hdr->s_name[0], sizeof (hdr->s_name));
scnhsz = bfd_coff_scnhsz (abfd);
readsize = (bfd_size_type) nscns * scnhsz;
- external_sections = bfd_alloc (abfd, readsize);
+ external_sections = (char *) bfd_alloc (abfd, readsize);
if (!external_sections)
goto fail;
/* Get the BFD section from a COFF symbol section number. */
asection *
-coff_section_from_bfd_index (bfd *abfd, int index)
+coff_section_from_bfd_index (bfd *abfd, int section_index)
{
struct bfd_section *answer = abfd->sections;
- if (index == N_ABS)
+ if (section_index == N_ABS)
return bfd_abs_section_ptr;
- if (index == N_UNDEF)
+ if (section_index == N_UNDEF)
return bfd_und_section_ptr;
- if (index == N_DEBUG)
+ if (section_index == N_DEBUG)
return bfd_abs_section_ptr;
while (answer)
{
- if (answer->target_index == index)
+ if (answer->target_index == section_index)
return answer;
answer = answer->next;
}
struct internal_reloc *irel;
bfd_size_type amt;
+ if (sec->reloc_count == 0)
+ return internal_relocs; /* Nothing to do. */
+
if (coff_section_data (abfd, sec) != NULL
&& coff_section_data (abfd, sec)->relocs != NULL)
{
amt = sec->reloc_count * relsz;
if (external_relocs == NULL)
{
- free_external = bfd_malloc (amt);
- if (free_external == NULL && sec->reloc_count > 0)
+ free_external = (bfd_byte *) bfd_malloc (amt);
+ if (free_external == NULL)
goto error_return;
external_relocs = free_external;
}
{
amt = sec->reloc_count;
amt *= sizeof (struct internal_reloc);
- free_internal = bfd_malloc (amt);
- if (free_internal == NULL && sec->reloc_count > 0)
+ free_internal = (struct internal_reloc *) bfd_malloc (amt);
+ if (free_internal == NULL)
goto error_return;
internal_relocs = free_internal;
}
struct internal_syment *syment)
{
/* Normalize the symbol flags. */
- if (bfd_is_com_section (coff_symbol_ptr->symbol.section))
+ if (coff_symbol_ptr->symbol.section
+ && bfd_is_com_section (coff_symbol_ptr->symbol.section))
{
/* A common symbol is undefined with a value. */
syment->n_scnum = N_UNDEF;
bfd_size_type amt;
amt = sizeof (asymbol *) * ((bfd_size_type) symbol_count + 1);
- newsyms = bfd_alloc (bfd_ptr, amt);
+ newsyms = (asymbol **) bfd_alloc (bfd_ptr, amt);
if (!newsyms)
return FALSE;
bfd_ptr->outsymbols = newsyms;
{
/* FIXME: We should use a union here. */
s->u.syment.n_value =
- (bfd_vma)((combined_entry_type *)
- ((unsigned long) s->u.syment.n_value))->offset;
+ (bfd_hostptr_t) ((combined_entry_type *)
+ ((bfd_hostptr_t) s->u.syment.n_value))->offset;
s->fix_value = 0;
}
if (s->fix_line)
{
unsigned int numaux = native->u.syment.n_numaux;
int type = native->u.syment.n_type;
- int class = native->u.syment.n_sclass;
+ int n_sclass = (int) native->u.syment.n_sclass;
void * buf;
bfd_size_type symesz;
{
bfd_coff_swap_aux_out (abfd,
&((native + j + 1)->u.auxent),
- type, class, (int) j,
+ type, n_sclass, (int) j,
native->u.syment.n_numaux,
buf);
if (bfd_bwrite (buf, auxesz, abfd) != auxesz)
debug_string_size_p);
}
+static void
+null_error_handler (const char * fmt ATTRIBUTE_UNUSED, ...)
+{
+}
+
/* Write out the COFF symbols. */
bfd_boolean
}
else
{
+ if (coff_backend_info (abfd)->_bfd_coff_classify_symbol != NULL)
+ {
+ bfd_error_handler_type current_error_handler;
+ enum coff_symbol_classification sym_class;
+ unsigned char *n_sclass;
+
+ /* Suppress error reporting by bfd_coff_classify_symbol.
+ Error messages can be generated when we are processing a local
+ symbol which has no associated section and we do not have to
+ worry about this, all we need to know is that it is local. */
+ current_error_handler = bfd_set_error_handler (null_error_handler);
+ sym_class = bfd_coff_classify_symbol (abfd,
+ &c_symbol->native->u.syment);
+ (void) bfd_set_error_handler (current_error_handler);
+
+ n_sclass = &c_symbol->native->u.syment.n_sclass;
+
+ /* If the symbol class has been changed (eg objcopy/ld script/etc)
+ we cannot retain the existing sclass from the original symbol.
+ Weak symbols only have one valid sclass, so just set it always.
+ If it is not local class and should be, set it C_STAT.
+ If it is global and not classified as global, or if it is
+ weak (which is also classified as global), set it C_EXT. */
+
+ if (symbol->flags & BSF_WEAK)
+ *n_sclass = obj_pe (abfd) ? C_NT_WEAK : C_WEAKEXT;
+ else if (symbol->flags & BSF_LOCAL && sym_class != COFF_SYMBOL_LOCAL)
+ *n_sclass = C_STAT;
+ else if (symbol->flags & BSF_GLOBAL
+ && (sym_class != COFF_SYMBOL_GLOBAL
+#ifdef COFF_WITH_PE
+ || *n_sclass == C_NT_WEAK
+#endif
+ || *n_sclass == C_WEAKEXT))
+ c_symbol->native->u.syment.n_sclass = C_EXT;
+ }
+
if (!coff_write_native_symbol (abfd, c_symbol, &written,
&string_size, &debug_string_section,
&debug_string_size))
combined_entry_type *auxent)
{
unsigned int type = symbol->u.syment.n_type;
- unsigned int class = symbol->u.syment.n_sclass;
+ unsigned int n_sclass = symbol->u.syment.n_sclass;
if (coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook)
{
}
/* Don't bother if this is a file or a section. */
- if (class == C_STAT && type == T_NULL)
+ if (n_sclass == C_STAT && type == T_NULL)
return;
- if (class == C_FILE)
+ if (n_sclass == C_FILE)
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 || class == C_FCN)
+ if ((ISFCN (type) || ISTAG (n_sclass) || n_sclass == C_BLOCK
+ || n_sclass == 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 =
}
sec_size = sect->size;
- debug_section = bfd_alloc (abfd, sec_size);
+ debug_section = (char *) bfd_alloc (abfd, sec_size);
if (debug_section == NULL)
return NULL;
if (name[len] == '\0')
break;
- if ((newname = bfd_alloc (abfd, (bfd_size_type) len + 1)) == NULL)
+ if ((newname = (char *) bfd_alloc (abfd, (bfd_size_type) len + 1)) == NULL)
return NULL;
strncpy (newname, name, len);
symesz = bfd_coff_symesz (abfd);
size = obj_raw_syment_count (abfd) * symesz;
+ if (size == 0)
+ return TRUE;
syms = bfd_malloc (size);
- if (syms == NULL && size != 0)
+ if (syms == NULL)
return FALSE;
if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
return NULL;
}
- strings = bfd_malloc (strsize);
+ strings = (char *) bfd_malloc (strsize);
if (strings == NULL)
return NULL;
return obj_raw_syments (abfd);
size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type);
- internal = bfd_zalloc (abfd, size);
+ internal = (combined_entry_type *) bfd_zalloc (abfd, size);
if (internal == NULL && size != 0)
return NULL;
internal_end = internal + obj_raw_syment_count (abfd);
}
internal_ptr->u.syment._n._n_n._n_offset =
- ((long)
+ ((bfd_hostptr_t)
(string_table
+ (internal_ptr + 1)->u.auxent.x_file.x_n.x_offset));
}
if (internal_ptr->u.syment.n_numaux > 1
&& coff_data (abfd)->pe)
internal_ptr->u.syment._n._n_n._n_offset =
- ((long)
+ ((bfd_hostptr_t)
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)
+ ((bfd_hostptr_t)
copy_name (abfd,
(internal_ptr + 1)->u.auxent.x_file.x_fname,
(size_t) bfd_coff_filnmlen (abfd)));
if (internal_ptr->u.syment._n._n_name[i] == '\0')
break;
- newstring = bfd_zalloc (abfd, (bfd_size_type) (i + 1));
+ newstring = (char *) bfd_zalloc (abfd, (bfd_size_type) (i + 1));
if (newstring == NULL)
return NULL;
strncpy (newstring, internal_ptr->u.syment._n._n_name, i);
- internal_ptr->u.syment._n._n_n._n_offset = (long int) newstring;
+ internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) newstring;
internal_ptr->u.syment._n._n_n._n_zeroes = 0;
}
else if (internal_ptr->u.syment._n._n_n._n_offset == 0)
- internal_ptr->u.syment._n._n_n._n_offset = (long int) "";
+ internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) "";
else if (!bfd_coff_symname_in_debug (abfd, &internal_ptr->u.syment))
{
/* Long name already. Point symbol at the string in the
return NULL;
}
internal_ptr->u.syment._n._n_n._n_offset =
- ((long int)
+ ((bfd_hostptr_t)
(string_table
+ internal_ptr->u.syment._n._n_n._n_offset));
}
/* Long name in debug section. Very similar. */
if (debug_section == NULL)
debug_section = build_debug_section (abfd);
- internal_ptr->u.syment._n._n_n._n_offset = (long int)
+ internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t)
(debug_section + internal_ptr->u.syment._n._n_n._n_offset);
}
}
coff_make_empty_symbol (bfd *abfd)
{
bfd_size_type amt = sizeof (coff_symbol_type);
- coff_symbol_type *new = bfd_zalloc (abfd, amt);
+ coff_symbol_type *new_symbol = (coff_symbol_type *) bfd_zalloc (abfd, amt);
- if (new == NULL)
+ if (new_symbol == NULL)
return NULL;
- new->symbol.section = 0;
- new->native = 0;
- new->lineno = NULL;
- new->done_lineno = FALSE;
- new->symbol.the_bfd = abfd;
+ new_symbol->symbol.section = 0;
+ new_symbol->native = 0;
+ new_symbol->lineno = NULL;
+ new_symbol->done_lineno = FALSE;
+ new_symbol->symbol.the_bfd = abfd;
- return & new->symbol;
+ return & new_symbol->symbol;
}
/* Make a debugging symbol. */
unsigned long sz ATTRIBUTE_UNUSED)
{
bfd_size_type amt = sizeof (coff_symbol_type);
- coff_symbol_type *new = bfd_alloc (abfd, amt);
+ coff_symbol_type *new_symbol = (coff_symbol_type *) bfd_alloc (abfd, amt);
- if (new == NULL)
+ if (new_symbol == NULL)
return NULL;
/* @@ The 10 is a guess at a plausible maximum number of aux entries
(but shouldn't be a constant). */
amt = sizeof (combined_entry_type) * 10;
- new->native = bfd_zalloc (abfd, amt);
- if (!new->native)
+ new_symbol->native = (combined_entry_type *) bfd_zalloc (abfd, amt);
+ if (!new_symbol->native)
return NULL;
- new->symbol.section = bfd_abs_section_ptr;
- new->symbol.flags = BSF_DEBUGGING;
- new->lineno = NULL;
- new->done_lineno = FALSE;
- new->symbol.the_bfd = abfd;
+ new_symbol->symbol.section = bfd_abs_section_ptr;
+ new_symbol->symbol.flags = BSF_DEBUGGING;
+ new_symbol->lineno = NULL;
+ new_symbol->done_lineno = FALSE;
+ new_symbol->symbol.the_bfd = abfd;
- return & new->symbol;
+ return & new_symbol->symbol;
}
void
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);
+ (bfd_hostptr_t) obj_raw_syments (abfd);
}
/* Return the COFF syment for a symbol. */
if (csym->native->fix_value)
psyment->n_value = psyment->n_value -
- (unsigned long) obj_raw_syments (abfd);
+ (bfd_hostptr_t) obj_raw_syments (abfd);
/* FIXME: We should handle fix_line here. */
if (! combined->fix_value)
val = (bfd_vma) combined->u.syment.n_value;
else
- val = combined->u.syment.n_value - (unsigned long) root;
+ val = combined->u.syment.n_value - (bfd_hostptr_t) root;
fprintf (file, "(sec %2d)(fl 0x%02x)(ty %3x)(scl %3d) (nx %d) 0x",
combined->u.syment.n_scnum,
combined->u.syment.n_type,
combined->u.syment.n_sclass,
combined->u.syment.n_numaux);
- fprintf_vma (file, val);
+ bfd_fprintf_vma (abfd, file, val);
fprintf (file, " %s", symbol->name);
for (aux = 0; aux < combined->u.syment.n_numaux; aux++)
/* Probably a section symbol ? */
{
fprintf (file, "AUX scnlen 0x%lx nreloc %d nlnno %d",
- (long) auxp->u.auxent.x_scn.x_scnlen,
+ (unsigned 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
}
/* Otherwise fall through. */
case C_EXT:
+ case C_AIX_WEAKEXT:
if (ISFCN (combined->u.syment.n_type))
{
long next, llnos;
llnos = auxp->u.auxent.x_sym.x_fcnary.x_fcn.x_lnnoptr;
fprintf (file,
"AUX tagndx %ld ttlsiz 0x%lx lnnos %ld next %ld",
- tagndx, auxp->u.auxent.x_sym.x_misc.x_fsize,
+ tagndx,
+ (unsigned long) auxp->u.auxent.x_sym.x_misc.x_fsize,
llnos, next);
break;
}
while (l->line_number)
{
fprintf (file, "\n%4d : ", l->line_number);
- fprintf_vma (file, l->u.offset + symbol->section->vma);
+ bfd_fprintf_vma (abfd, file, l->u.offset + symbol->section->vma);
l++;
}
}
maxdiff = (bfd_vma) 0 - (bfd_vma) 1;
while (1)
{
+ bfd_vma file_addr;
combined_entry_type *p2;
for (p2 = p + 1 + p->u.syment.n_numaux;
}
}
+ file_addr = (bfd_vma) p2->u.syment.n_value;
+ /* PR 11512: Include the section address of the function name symbol. */
+ if (p2->u.syment.n_scnum > 0)
+ file_addr += coff_section_from_bfd_index (abfd,
+ p2->u.syment.n_scnum)->vma;
/* We use <= MAXDIFF here so that if we get a zero length
file, we actually use the next file entry. */
if (p2 < pend
- && offset + sec_vma >= (bfd_vma) p2->u.syment.n_value
- && offset + sec_vma - (bfd_vma) p2->u.syment.n_value <= maxdiff)
+ && offset + sec_vma >= file_addr
+ && offset + sec_vma - file_addr <= maxdiff)
{
*filename_ptr = (char *) p->u.syment._n._n_n._n_offset;
maxdiff = offset + sec_vma - p2->u.syment.n_value;
}
/* Now wander though the raw linenumbers of the section. */
- /* If we have been called on this section before, and th. e offset we
+ /* If we have been called on this section before, and the offset we
want is further down then we can prime the lookup loop. */
sec_data = coff_section_data (abfd, section);
if (sec_data != NULL
if (sec_data != NULL)
{
sec_data->offset = offset;
- sec_data->i = i;
+ sec_data->i = i - 1;
sec_data->function = *functionname_ptr;
sec_data->line_base = line_base;
}
return TRUE;
}
+bfd_boolean
+coff_find_inliner_info (bfd *abfd,
+ const char **filename_ptr,
+ const char **functionname_ptr,
+ unsigned int *line_ptr)
+{
+ bfd_boolean found;
+
+ found = _bfd_dwarf2_find_inliner_info (abfd, filename_ptr,
+ functionname_ptr, line_ptr,
+ &coff_data(abfd)->dwarf2_find_line_info);
+ return (found);
+}
+
int
-coff_sizeof_headers (bfd *abfd, bfd_boolean reloc)
+coff_sizeof_headers (bfd *abfd, struct bfd_link_info *info)
{
size_t size;
- if (! reloc)
+ if (!info->relocatable)
size = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd);
else
size = bfd_coff_filhsz (abfd);
bfd_boolean
bfd_coff_set_symbol_class (bfd * abfd,
asymbol * symbol,
- unsigned int class)
+ unsigned int symbol_class)
{
coff_symbol_type * csym;
combined_entry_type * native;
bfd_size_type amt = sizeof (* native);
- native = bfd_zalloc (abfd, amt);
+ native = (combined_entry_type *) bfd_zalloc (abfd, amt);
if (native == NULL)
return FALSE;
native->u.syment.n_type = T_NULL;
- native->u.syment.n_sclass = class;
+ native->u.syment.n_sclass = symbol_class;
if (bfd_is_und_section (symbol->section))
{
csym->native = native;
}
else
- csym->native->u.syment.n_sclass = class;
+ csym->native->u.syment.n_sclass = symbol_class;
return TRUE;
}