/* 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, 2007, 2008, 2009
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Written by Cygnus Support.
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 + 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 + 1);
if (name == NULL)
return FALSE;
strncpy (name, (char *) &hdr->s_name[0], sizeof (hdr->s_name));
if (hdr->s_scnptr != 0)
return_section->flags |= SEC_HAS_CONTENTS;
+ /* Compress/decompress DWARF debug sections with names: .debug_* and
+ .zdebug_*, after the section flags is set. */
+ if ((flags & SEC_DEBUGGING)
+ && ((name[1] == 'd' && name[6] == '_')
+ || (name[1] == 'z' && name[7] == '_')))
+ {
+ enum { nothing, compress, decompress } action = nothing;
+ char *new_name = NULL;
+
+ if (bfd_is_section_compressed (abfd, return_section))
+ {
+ /* Compressed section. Check if we should decompress. */
+ if ((abfd->flags & BFD_DECOMPRESS))
+ action = decompress;
+ }
+ else if (!bfd_is_section_compressed (abfd, return_section))
+ {
+ /* Normal section. Check if we should compress. */
+ if ((abfd->flags & BFD_COMPRESS) && return_section->size != 0)
+ action = compress;
+ }
+
+ switch (action)
+ {
+ case nothing:
+ break;
+ case compress:
+ if (!bfd_init_section_compress_status (abfd, return_section))
+ {
+ (*_bfd_error_handler)
+ (_("%B: unable to initialize compress status for section %s"),
+ abfd, name);
+ return FALSE;
+ }
+ if (name[1] != 'z')
+ {
+ unsigned int len = strlen (name);
+
+ new_name = bfd_alloc (abfd, len + 2);
+ if (new_name == NULL)
+ return FALSE;
+ new_name[0] = '.';
+ new_name[1] = 'z';
+ memcpy (new_name + 2, name + 1, len);
+ }
+ break;
+ case decompress:
+ if (!bfd_init_section_decompress_status (abfd, return_section))
+ {
+ (*_bfd_error_handler)
+ (_("%B: unable to initialize decompress status for section %s"),
+ abfd, name);
+ return FALSE;
+ }
+ if (name[1] == 'z')
+ {
+ unsigned int len = strlen (name);
+
+ new_name = bfd_alloc (abfd, len);
+ if (new_name == NULL)
+ return FALSE;
+ new_name[0] = '.';
+ memcpy (new_name + 1, name + 2, len - 1);
+ }
+ break;
+ }
+ if (new_name != NULL)
+ bfd_rename_section (abfd, return_section, new_name);
+ }
+
return result;
}
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;
}
amt = sec->reloc_count * relsz;
if (external_relocs == NULL)
{
- free_external = bfd_malloc (amt);
+ 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);
+ free_internal = (struct internal_reloc *) bfd_malloc (amt);
if (free_internal == NULL)
goto error_return;
internal_relocs = free_internal;
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;
{
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;
+ asection *output_section = symbol->section->output_section
+ ? symbol->section->output_section
+ : symbol->section;
void * buf;
bfd_size_type symesz;
else
native->u.syment.n_scnum =
- symbol->section->output_section->target_index;
+ output_section->target_index;
coff_fix_symbol_name (abfd, symbol, native, string_size_p,
debug_string_section_p, debug_string_size_p);
{
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)
file originally. This symbol may have been created by the linker,
or we may be linking a non COFF file to a COFF file. */
-static bfd_boolean
+bfd_boolean
coff_write_alien_symbol (bfd *abfd,
asymbol *symbol,
+ struct internal_syment *isym,
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 = &dummy;
+ combined_entry_type dummy[2];
+ asection *output_section = symbol->section->output_section
+ ? symbol->section->output_section
+ : symbol->section;
+ struct bfd_link_info *link_info = coff_data (abfd)->link_info;
+ bfd_boolean ret;
+
+ if ((!link_info || link_info->strip_discarded)
+ && !bfd_is_abs_section (symbol->section)
+ && symbol->section->output_section == bfd_abs_section_ptr)
+ {
+ symbol->name = "";
+ if (isym != NULL)
+ memset (isym, 0, sizeof(*isym));
+ return TRUE;
+ }
+ native = dummy;
native->u.syment.n_type = T_NULL;
native->u.syment.n_flags = 0;
+ native->u.syment.n_numaux = 0;
if (bfd_is_und_section (symbol->section))
{
native->u.syment.n_scnum = N_UNDEF;
native->u.syment.n_scnum = N_UNDEF;
native->u.syment.n_value = symbol->value;
}
+ else if (symbol->flags & BSF_FILE)
+ {
+ native->u.syment.n_scnum = N_DEBUG;
+ native->u.syment.n_numaux = 1;
+ }
else if (symbol->flags & BSF_DEBUGGING)
{
/* There isn't much point to writing out a debugging symbol
format. So, we just ignore them. We must clobber the symbol
name to keep it from being put in the string table. */
symbol->name = "";
+ if (isym != NULL)
+ memset (isym, 0, sizeof(*isym));
return TRUE;
}
else
{
- native->u.syment.n_scnum =
- symbol->section->output_section->target_index;
+ native->u.syment.n_scnum = 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;
+ native->u.syment.n_value += output_section->vma;
/* Copy the any flags from the file header into the symbol.
FIXME: Why? */
}
native->u.syment.n_type = 0;
- if (symbol->flags & BSF_LOCAL)
+ if (symbol->flags & BSF_FILE)
+ native->u.syment.n_sclass = C_FILE;
+ else 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, string_size_p,
- debug_string_section_p, debug_string_size_p);
+ ret = coff_write_symbol (abfd, symbol, native, written, string_size_p,
+ debug_string_section_p, debug_string_size_p);
+ if (isym != NULL)
+ *isym = native->u.syment;
+ return ret;
}
/* Write a native symbol to a COFF file. */
{
combined_entry_type *native = symbol->native;
alent *lineno = symbol->lineno;
+ struct bfd_link_info *link_info = coff_data (abfd)->link_info;
+
+ if ((!link_info || link_info->strip_discarded)
+ && !bfd_is_abs_section (symbol->symbol.section)
+ && symbol->symbol.section->output_section == bfd_abs_section_ptr)
+ {
+ symbol->symbol.name = "";
+ return TRUE;
+ }
/* 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
if (c_symbol == (coff_symbol_type *) NULL
|| c_symbol->native == (combined_entry_type *) NULL)
{
- if (!coff_write_alien_symbol (abfd, symbol, &written, &string_size,
- &debug_string_section,
+ if (!coff_write_alien_symbol (abfd, symbol, NULL, &written,
+ &string_size, &debug_string_section,
&debug_string_size))
return FALSE;
}
if (coff_backend_info (abfd)->_bfd_coff_classify_symbol != NULL)
{
bfd_error_handler_type current_error_handler;
- enum coff_symbol_classification class;
+ enum coff_symbol_classification sym_class;
unsigned char *n_sclass;
/* Suppress error reporting by bfd_coff_classify_symbol.
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);
- class = bfd_coff_classify_symbol (abfd, &c_symbol->native->u.syment);
+ 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)
if (symbol->flags & BSF_WEAK)
*n_sclass = obj_pe (abfd) ? C_NT_WEAK : C_WEAKEXT;
- else if (symbol->flags & BSF_LOCAL && class != COFF_SYMBOL_LOCAL)
+ else if (symbol->flags & BSF_LOCAL && sym_class != COFF_SYMBOL_LOCAL)
*n_sclass = C_STAT;
else if (symbol->flags & BSF_GLOBAL
- && (class != COFF_SYMBOL_GLOBAL
+ && (sym_class != COFF_SYMBOL_GLOBAL
#ifdef COFF_WITH_PE
|| *n_sclass == C_NT_WEAK
#endif
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);
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);
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);
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
combined->u.syment.n_type,
combined->u.syment.n_sclass,
combined->u.syment.n_numaux);
-#ifdef BFD64
- /* fprintf_vma() on a 64-bit enabled host will always print a 64-bit
- value, but really we want to display the address in the target's
- address size. Since we do not have a field in the bfd structure
- to tell us this, we take a guess, based on the target's name. */
- if (strstr (bfd_get_target (abfd), "64") == NULL)
- fprintf (file, "%08lx", (unsigned long) (val & 0xffffffff));
- else
-#endif
- 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++)
}
/* Otherwise fall through. */
case C_EXT:
+ case C_AIX_WEAKEXT:
if (ISFCN (combined->u.syment.n_type))
{
long next, llnos;
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++;
}
}
nearest to the wanted location. */
bfd_boolean
-coff_find_nearest_line (bfd *abfd,
- asection *section,
- asymbol **symbols,
- bfd_vma offset,
- const char **filename_ptr,
- const char **functionname_ptr,
- unsigned int *line_ptr)
+coff_find_nearest_line_with_names (bfd *abfd,
+ const struct dwarf_debug_section *debug_sections,
+ asection *section,
+ asymbol **symbols,
+ bfd_vma offset,
+ const char **filename_ptr,
+ const char **functionname_ptr,
+ unsigned int *line_ptr)
{
bfd_boolean found;
unsigned int i;
return TRUE;
/* Also try examining DWARF2 debugging information. */
- if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
+ if (_bfd_dwarf2_find_nearest_line (abfd, debug_sections,
+ section, symbols, offset,
filename_ptr, functionname_ptr,
- line_ptr, 0,
+ line_ptr, NULL, 0,
&coff_data(abfd)->dwarf2_find_line_info))
return TRUE;
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;
return TRUE;
}
+bfd_boolean
+coff_find_nearest_line (bfd *abfd,
+ asection *section,
+ asymbol **symbols,
+ bfd_vma offset,
+ const char **filename_ptr,
+ const char **functionname_ptr,
+ unsigned int *line_ptr)
+{
+ return coff_find_nearest_line_with_names (abfd, dwarf_debug_sections,
+ section, symbols, offset,
+ filename_ptr, functionname_ptr,
+ line_ptr);
+}
+
+bfd_boolean
+coff_find_nearest_line_discriminator (bfd *abfd,
+ asection *section,
+ asymbol **symbols,
+ bfd_vma offset,
+ const char **filename_ptr,
+ const char **functionname_ptr,
+ unsigned int *line_ptr,
+ unsigned int *discriminator)
+{
+ *discriminator = 0;
+ return coff_find_nearest_line_with_names (abfd, dwarf_debug_sections,
+ section, symbols, offset,
+ filename_ptr, functionname_ptr,
+ line_ptr);
+}
+
+
bfd_boolean
coff_find_inliner_info (bfd *abfd,
const char **filename_ptr,
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;
}
else
return NULL;
}
+
+bfd_boolean
+_bfd_coff_section_already_linked (bfd *abfd,
+ asection *sec,
+ struct bfd_link_info *info)
+{
+ flagword flags;
+ const char *name, *key;
+ struct bfd_section_already_linked *l;
+ struct bfd_section_already_linked_hash_entry *already_linked_list;
+ struct coff_comdat_info *s_comdat;
+
+ flags = sec->flags;
+ if ((flags & SEC_LINK_ONCE) == 0)
+ return FALSE;
+
+ /* The COFF backend linker doesn't support group sections. */
+ if ((flags & SEC_GROUP) != 0)
+ return FALSE;
+
+ name = bfd_get_section_name (abfd, sec);
+ s_comdat = bfd_coff_get_comdat_section (abfd, sec);
+
+ if (s_comdat != NULL)
+ key = s_comdat->name;
+ else
+ {
+ if (CONST_STRNEQ (name, ".gnu.linkonce.")
+ && (key = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL)
+ key++;
+ else
+ /* FIXME: gcc as of 2011-09 emits sections like .text$<key>,
+ .xdata$<key> and .pdata$<key> only the first of which has a
+ comdat key. Should these all match the LTO IR key? */
+ key = name;
+ }
+
+ already_linked_list = bfd_section_already_linked_table_lookup (key);
+
+ for (l = already_linked_list->entry; l != NULL; l = l->next)
+ {
+ struct coff_comdat_info *l_comdat;
+
+ l_comdat = bfd_coff_get_comdat_section (l->sec->owner, l->sec);
+
+ /* The section names must match, and both sections must be
+ comdat and have the same comdat name, or both sections must
+ be non-comdat. LTO IR plugin sections are an exception. They
+ are always named .gnu.linkonce.t.<key> (<key> is some string)
+ and match any comdat section with comdat name of <key>, and
+ any linkonce section with the same suffix, ie.
+ .gnu.linkonce.*.<key>. */
+ if (((s_comdat != NULL) == (l_comdat != NULL)
+ && strcmp (name, l->sec->name) == 0)
+ || (l->sec->owner->flags & BFD_PLUGIN) != 0)
+ {
+ /* The section has already been linked. See if we should
+ issue a warning. */
+ return _bfd_handle_already_linked (sec, l, info);
+ }
+ }
+
+ /* This is the first section with this name. Record it. */
+ if (!bfd_section_already_linked_table_insert (already_linked_list, sec))
+ info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
+ return FALSE;
+}