don't know the length of the string table. */
strings += strindex;
name = (char *) bfd_alloc (abfd,
- (bfd_size_type) strlen (strings) + 1);
+ (bfd_size_type) strlen (strings) + 1 + 1);
if (name == NULL)
return FALSE;
strcpy (name, strings);
{
/* Assorted wastage to null-terminate the name, thanks AT&T! */
name = (char *) bfd_alloc (abfd,
- (bfd_size_type) sizeof (hdr->s_name) + 1);
+ (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;
}
/* Read in a COFF object and make it into a BFD. This is used by
ECOFF as well. */
-
-static const bfd_target *
+const bfd_target *
+coff_real_object_p (bfd *,
+ unsigned,
+ struct internal_filehdr *,
+ struct internal_aouthdr *);
+const bfd_target *
coff_real_object_p (bfd *abfd,
unsigned nscns,
struct internal_filehdr *internal_f,
struct internal_syment *syment)
{
/* Normalize the symbol flags. */
- if (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. */
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;
+ 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;
- native = &dummy;
+ 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_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;
}
/* 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 (n_sclass) || n_sclass == C_BLOCK
|| n_sclass == C_FCN)
&& auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l > 0)
new_symbol->lineno = NULL;
new_symbol->done_lineno = FALSE;
new_symbol->symbol.the_bfd = abfd;
-
+
return & new_symbol->symbol;
}
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;
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,
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;
+}