/* Support for the generic parts of most COFF variants, for BFD.
- Copyright 1990, 91, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+ Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
can't call slurp_symtab, because the linker doesn't want the
swapped symbols. */
+ /* COMDAT sections are special. The first symbol is the section
+ symbol, which tells what kind of COMDAT section it is. The
+ *second* symbol is the "comdat symbol" - the one with the
+ unique name. GNU uses the section symbol for the unique
+ name; MS uses ".text" for every comdat section. Sigh. - DJ */
+
if (_bfd_coff_get_external_symbols (abfd))
{
bfd_byte *esym, *esymend;
isym.n_type, isym.n_sclass,
0, isym.n_numaux, (PTR) &aux);
+ /* FIXME: Microsoft uses NODUPLICATES and
+ ASSOCIATIVE, but gnu uses ANY and SAME_SIZE.
+ Unfortunately, gnu doesn't do the comdat
+ symbols right. So, until we can fix it to do
+ the right thing, we are temporarily disabling
+ comdats for the MS types (they're used in
+ DLLs and C++, but we don't support *their*
+ C++ libraries anyway - DJ */
+
switch (aux.x_scn.x_comdat)
{
case IMAGE_COMDAT_SELECT_NODUPLICATES:
+#if 0
sec_flags |= SEC_LINK_DUPLICATES_ONE_ONLY;
+#else
+ sec_flags &= ~SEC_LINK_ONCE;
+#endif
break;
default:
break;
case IMAGE_COMDAT_SELECT_ASSOCIATIVE:
+#if 0
/* FIXME: This is not currently implemented. */
sec_flags |= SEC_LINK_DUPLICATES_DISCARD;
+#else
+ sec_flags &= ~SEC_LINK_ONCE;
+#endif
break;
}
. boolean collect,
. struct bfd_link_hash_entry **hashp));
.
+. boolean (*_bfd_coff_link_output_has_begun) PARAMS ((
+. bfd * abfd,
+. struct coff_final_link_info * pfinfo));
+. boolean (*_bfd_coff_final_link_postscript) PARAMS ((
+. bfd * abfd,
+. struct coff_final_link_info * pfinfo));
+.
.} bfd_coff_backend_data;
.
.#define coff_backend_info(abfd) ((bfd_coff_backend_data *) (abfd)->xvec->backend_data)
. ((coff_backend_info (abfd)->_bfd_coff_link_add_one_symbol)\
. (info, abfd, name, flags, section, value, string, cp, coll, hashp))
.
+.#define bfd_coff_link_output_has_begun(a,p) \
+. ((coff_backend_info (a)->_bfd_coff_link_output_has_begun) (a,p))
+.#define bfd_coff_final_link_postscript(a,p) \
+. ((coff_backend_info (a)->_bfd_coff_final_link_postscript) (a,p))
+.
*/
/* See whether the magic number matches. */
bfd * abfd;
asection * section;
{
+ combined_entry_type *native;
+
section->alignment_power = COFF_DEFAULT_SECTION_ALIGNMENT_POWER;
#ifdef RS6000COFF_C
@@ The 10 is a guess at a plausible maximum number of aux entries
(but shouldn't be a constant). */
- coffsymbol (section->symbol)->native =
- (combined_entry_type *) bfd_zalloc (abfd,
- sizeof (combined_entry_type) * 10);
+ native = ((combined_entry_type *)
+ bfd_zalloc (abfd, sizeof (combined_entry_type) * 10));
+ if (native == NULL)
+ return false;
+
+ /* We don't need to set up n_name, n_value, or n_scnum in the native
+ symbol information, since they'll be overriden by the BFD symbol
+ anyhow. However, we do need to set the type and storage class,
+ in case this symbol winds up getting written out. The value 0
+ for n_numaux is already correct. */
+
+ native->u.syment.n_type = T_NULL;
+ native->u.syment.n_sclass = C_STAT;
+
+ coffsymbol (section->symbol)->native = native;
/* The .stab section must be aligned to 2**2 at most, because
otherwise there may be gaps in the section which gdb will not
if ((1 << i) >= hdr->s_align)
break;
#endif
-/* start-sanitize-tic80 */
#ifdef TIC80COFF
/* TI tools hijack bits 8-11 for the alignment */
i = (hdr->s_flags >> 8) & 0xF ;
#endif
-/* end-sanitize-tic80 */
section->alignment_power = i;
}
}
#endif
+#ifdef COFF_WITH_PE
+ section->lma = hdr->s_vaddr;
+#endif
}
#undef ALIGN_SET
#undef ELIFALIGN_SET
}
#endif
-#if defined ARM && ! defined COFF_WITH_PE
+#ifdef ARM
/* Set the flags field from the COFF header read in */
- if (! coff_arm_bfd_set_private_flags (abfd, internal_f->f_flags))
+ if (! _bfd_coff_arm_set_private_flags (abfd, internal_f->f_flags))
coff->flags = 0;
#endif
arch = bfd_arch_arm;
switch (internal_f->f_flags & F_ARM_ARCHITECTURE_MASK)
{
- case F_ARM_2: machine = bfd_mach_arm_2; break;
- case F_ARM_2a: machine = bfd_mach_arm_2a; break;
- case F_ARM_3: machine = bfd_mach_arm_3; break;
- default:
- case F_ARM_3M: machine = bfd_mach_arm_3M; break;
- case F_ARM_4: machine = bfd_mach_arm_4; break;
- case F_ARM_4T: machine = bfd_mach_arm_4T; break;
+ case F_ARM_2: machine = bfd_mach_arm_2; break;
+ case F_ARM_2a: machine = bfd_mach_arm_2a; break;
+ case F_ARM_3: machine = bfd_mach_arm_3; break;
+ default:
+ case F_ARM_3M: machine = bfd_mach_arm_3M; break;
+ case F_ARM_4: machine = bfd_mach_arm_4; break;
+ case F_ARM_4T: machine = bfd_mach_arm_4T; break;
+ case F_ARM_5: machine = bfd_mach_arm_5; break;
}
break;
#endif
case LYNXCOFFMAGIC:
#endif
arch = bfd_arch_m68k;
- machine = 68020;
+ machine = bfd_mach_m68020;
break;
#endif
#ifdef MC88MAGIC
break;
#endif
-/* start-sanitize-tic80 */
+#ifdef TIC30MAGIC
+ case TIC30MAGIC:
+ arch = bfd_arch_tic30;
+ break;
+#endif
+
#ifdef TIC80_ARCH_MAGIC
case TIC80_ARCH_MAGIC:
arch = bfd_arch_tic80;
break;
#endif
-/* end-sanitize-tic80 */
+#ifdef MCOREMAGIC
+ case MCOREMAGIC:
+ arch = bfd_arch_mcore;
+ break;
+#endif
default: /* Unreadable input file type */
arch = bfd_arch_obscure;
break;
}
break;
#endif
-/* start-sanitize-tic80 */
+
+#ifdef TIC30MAGIC
+ case bfd_arch_tic30:
+ *magicp = TIC30MAGIC;
+ return true;
+#endif
#ifdef TIC80_ARCH_MAGIC
case bfd_arch_tic80:
*magicp = TIC80_ARCH_MAGIC;
return true;
#endif
-/* end-sanitize-tic80 */
#ifdef ARMMAGIC
case bfd_arch_arm:
* magicp = ARMMAGIC;
case bfd_mach_arm_3M: * flagsp |= F_ARM_3M; break;
case bfd_mach_arm_4: * flagsp |= F_ARM_4; break;
case bfd_mach_arm_4T: * flagsp |= F_ARM_4T; break;
+ case bfd_mach_arm_5: * flagsp |= F_ARM_5; break;
+ case bfd_mach_arm_5T: * flagsp |= F_ARM_5; break; /* XXX - we do not have an F_ARM_5T */
}
return true;
#endif
break;
#endif
+#ifdef MCOREMAGIC
+ case bfd_arch_mcore:
+ * magicp = MCOREMAGIC;
+ return true;
+#endif
+
default: /* Unknown architecture */
/* return false; -- fall through to "return false" below, to avoid
"statement never reached" errors on the one below. */
/* Calculate the file position for each section. */
+#ifndef I960
+#define ALIGN_SECTIONS_IN_FILE
+#endif
+#ifdef TIC80COFF
+#undef ALIGN_SECTIONS_IN_FILE
+#endif
+
static boolean
coff_compute_section_file_positions (abfd)
bfd * abfd;
asection *previous = (asection *) NULL;
file_ptr sofar = FILHSZ;
boolean align_adjust;
-
-#ifndef I960
+ unsigned int count;
+#ifdef ALIGN_SECTIONS_IN_FILE
file_ptr old_sofar;
#endif
- unsigned int count;
#ifdef RS6000COFF_C
/* On XCOFF, if we have symbols, set up the .debug section. */
current != (asection *) NULL;
current = current->next, ++count)
{
+#ifdef COFF_IMAGE_WITH_PE
+ /* The NT loader does not want empty section headers, so we omit
+ them. We don't actually remove the section from the BFD,
+ although we probably should. This matches code in
+ coff_write_object_contents. */
+ if (current->_raw_size == 0)
+ {
+ current->target_index = -1;
+ --count;
+ continue;
+ }
+#endif
+
current->target_index = count;
/* Only deal with sections which have contents */
which they are aligned in virtual memory. I960 doesn't
do this (FIXME) so we can stay in sync with Intel. 960
doesn't yet page from files... */
-#ifndef I960
+#ifdef ALIGN_SECTIONS_IN_FILE
if ((abfd->flags & EXEC_P) != 0)
{
/* make sure this section is aligned on the right boundary - by
sofar += current->_raw_size;
-#ifndef I960
+#ifdef ALIGN_SECTIONS_IN_FILE
/* make sure that this section is of the right size too */
if ((abfd->flags & EXEC_P) == 0)
{
section.s_align = (current->alignment_power
? 1 << current->alignment_power
: 0);
-/* start-sanitize-tic80 */
#else
#ifdef TIC80COFF
section.s_flags |= (current->alignment_power & 0xF) << 8;
#endif
-/* end-sanitize-tic80 */
#endif
#ifdef COFF_IMAGE_WITH_PE
{
unsigned int i, count;
asymbol **psym;
- coff_symbol_type *csym;
+ coff_symbol_type *csym = NULL;
+ asymbol **psymsec;
+ psymsec = NULL;
count = bfd_get_symcount (abfd);
for (i = 0, psym = abfd->outsymbols; i < count; i++, psym++)
{
- /* Here *PSYM is the section symbol for CURRENT. */
+ if ((*psym)->section != current)
+ continue;
+ /* Remember the location of the first symbol in this
+ section. */
+ if (psymsec == NULL)
+ psymsec = psym;
+
+ /* See if this is the section symbol. */
if (strcmp ((*psym)->name, current->name) == 0)
{
csym = coff_symbol_from (abfd, *psym);
|| csym->native->u.syment.n_sclass != C_STAT
|| csym->native->u.syment.n_type != T_NULL)
continue;
+
+ /* Here *PSYM is the section symbol for CURRENT. */
+
break;
}
}
IMAGE_COMDAT_SELECT_EXACT_MATCH;
break;
}
+
+ /* The COMDAT symbol must be the first symbol from this
+ section in the symbol table. In order to make this
+ work, we move the COMDAT symbol before the first
+ symbol we found in the search above. It's OK to
+ rearrange the symbol table at this point, because
+ coff_renumber_symbols is going to rearrange it
+ further and fix up all the aux entries. */
+ if (psym != psymsec)
+ {
+ asymbol *hold;
+ asymbol **pcopy;
+
+ hold = *psym;
+ for (pcopy = psym; pcopy > psymsec; pcopy--)
+ pcopy[0] = pcopy[-1];
+ *psymsec = hold;
+ }
}
}
#endif /* COFF_WITH_PE */
else
internal_f.f_flags |= F_AR32W;
-/* start-sanitize-tic80 */
#ifdef TIC80_TARGET_ID
internal_f.f_target_id = TIC80_TARGET_ID;
#endif
-/* end-sanitize-tic80 */
/*
FIXME, should do something about the other byte orders and
internal_a.magic = NMAGIC; /* Assume separate i/d */
#define __A_MAGIC_SET__
#endif /* A29K */
-/* start-sanitize-tic80 */
#ifdef TIC80COFF
internal_a.magic = TIC80_ARCH_MAGIC;
#define __A_MAGIC_SET__
#endif /* TIC80 */
-/* end-sanitize-tic80 */
#ifdef I860
/* FIXME: What are the a.out magic numbers for the i860? */
internal_a.magic = 0;
internal_a.magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
#endif
+#if defined MCORE_PE
+#define __A_MAGIC_SET__
+ internal_a.magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
+#endif
+
#if defined(I386)
#define __A_MAGIC_SET__
#if defined(LYNXOS)
if (! coff_write_relocs (abfd, firstundef))
return false;
}
+#ifdef COFF_LONG_SECTION_NAMES
+ else if (long_section_names)
+ {
+ /* If we have long section names we have to write out the string
+ table even if there are no symbols. */
+ if (! coff_write_symbols (abfd))
+ return false;
+ }
+#endif
#ifdef COFF_IMAGE_WITH_PE
#ifdef PPC_PE
else if ((abfd->flags & EXEC_P) != 0)
warned = false;
symndx = dst.l_addr.l_symndx;
- if (symndx < 0 || symndx >= obj_raw_syment_count (abfd))
+ if (symndx < 0
+ || (unsigned long) symndx >= obj_raw_syment_count (abfd))
{
(*_bfd_error_handler)
- ("%s: warning: illegal symbol index %ld in line numbers",
+ (_("%s: warning: illegal symbol index %ld in line numbers"),
bfd_get_filename (abfd), dst.l_addr.l_symndx);
symndx = 0;
warned = true;
if (sym->lineno != NULL && ! warned)
{
(*_bfd_error_handler)
- ("%s: warning: duplicate line number information for `%s'",
+ (_("%s: warning: duplicate line number information for `%s'"),
bfd_get_filename (abfd),
bfd_asymbol_name (&sym->symbol));
}
#endif
case C_EXT:
+ case C_WEAKEXT:
+#if defined ARM
+ case C_THUMBEXT:
+ case C_THUMBEXTFUNC:
+#endif
#ifdef RS6000COFF_C
case C_HIDEXT:
#endif
#ifdef COFF_WITH_PE
/* PE uses storage class 0x68 to denote a section symbol */
case C_SECTION:
- /* PE uses storage class 0x67 for a weak external symbol. */
+ /* PE uses storage class 0x69 for a weak external symbol. */
case C_NT_WEAK:
#endif
if ((src->u.syment.n_scnum) == 0)
dst->symbol.flags = BSF_EXPORT | BSF_GLOBAL;
-#if defined (COFF_WITH_PE) || defined (COFF_IMAGE_WITH_PE)
+#if defined COFF_WITH_PE
/* PE sets the symbol to a value relative to the
start of the section. */
dst->symbol.value = src->u.syment.n_value;
#ifdef COFF_WITH_PE
if (src->u.syment.n_sclass == C_NT_WEAK)
dst->symbol.flags = BSF_WEAK;
+ if (src->u.syment.n_sclass == C_SECTION
+ && src->u.syment.n_scnum > 0)
+ {
+ dst->symbol.flags = BSF_LOCAL;
+ }
#endif
+ if (src->u.syment.n_sclass == C_WEAKEXT)
+ dst->symbol.flags = BSF_WEAK;
+
break;
case C_STAT: /* static */
#ifdef I960
case C_LEAFSTAT: /* static leaf procedure */
+#endif
+#if defined ARM
+ case C_THUMBSTAT: /* Thumb static */
+ case C_THUMBLABEL: /* Thumb label */
+ case C_THUMBSTATFUNC:/* Thumb static function */
#endif
case C_LABEL: /* label */
if (src->u.syment.n_scnum == -2)
section, if there is one. */
if (dst->symbol.section)
{
-#if defined (COFF_WITH_PE) || defined (COFF_IMAGE_WITH_PE)
+#if defined COFF_WITH_PE
/* PE sets the symbol to a value relative to the
start of the section. */
dst->symbol.value = src->u.syment.n_value;
#endif
case C_REGPARM: /* register parameter */
case C_REG: /* register variable */
-/* start-sanitize-tic80 */
#ifndef TIC80COFF
-/* end-sanitize-tic80 */
#ifdef C_AUTOARG
case C_AUTOARG: /* 960-specific storage class */
#endif
-/* start-sanitize-tic80 */
#endif
-/* end-sanitize-tic80 */
case C_TPDEF: /* type definition */
case C_ARG:
case C_AUTO: /* automatic variable */
case C_FCN: /* ".bf" or ".ef" */
case C_EFCN: /* physical end of function */
dst->symbol.flags = BSF_LOCAL;
-#if defined (COFF_WITH_PE) || defined (COFF_IMAGE_WITH_PE)
+#if defined COFF_WITH_PE
/* PE sets the symbol to a value relative to the start
of the section. */
dst->symbol.value = src->u.syment.n_value;
/* NT uses 0x67 for a weak symbol, not C_ALIAS. */
case C_ALIAS: /* duplicate tag */
#endif
-/* start-sanitize-tic80 */
/* New storage classes for TIc80 */
#ifdef TIC80COFF
case C_UEXT: /* Tentative external definition */
#endif
case C_STATLAB: /* Static load time label */
case C_EXTLAB: /* External load time label */
-/* end-sanitize-tic80 */
case C_HIDDEN: /* ext symbol in dmert public lib */
default:
(*_bfd_error_handler)
- ("%s: Unrecognized storage class %d for %s symbol `%s'",
+ (_("%s: Unrecognized storage class %d for %s symbol `%s'"),
bfd_get_filename (abfd), src->u.syment.n_sclass,
dst->symbol.section->name, dst->symbol.name);
dst->symbol.flags = BSF_DEBUGGING;
#define OTHER_GLOBAL_CLASS C_LEAFEXT
#endif
+#ifdef COFFARM
+#define OTHER_GLOBAL_CLASS C_THUMBEXT || syment->n_sclass == C_THUMBEXTFUNC
+#else
#ifdef COFF_WITH_PE
#define OTHER_GLOBAL_CLASS C_SECTION
#endif
+#endif
#ifdef OTHER_GLOBAL_CLASS
static boolean
coff_sym_is_global (abfd, syment)
- bfd *abfd;
- struct internal_syment *syment;
+ bfd * abfd;
+ struct internal_syment * syment;
{
- if (syment->n_sclass == OTHER_GLOBAL_CLASS)
- return true;
- return false;
+ return (syment->n_sclass == OTHER_GLOBAL_CLASS);
}
#undef OTHER_GLOBAL_CLASS
if (dst.r_symndx < 0 || dst.r_symndx >= obj_conv_table_size (abfd))
{
(*_bfd_error_handler)
- ("%s: warning: illegal symbol index %ld in relocs",
+ (_("%s: warning: illegal symbol index %ld in relocs"),
bfd_get_filename (abfd), dst.r_symndx);
cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
ptr = NULL;
if (cache_ptr->howto == NULL)
{
(*_bfd_error_handler)
- ("%s: illegal relocation type %d at address 0x%lx",
+ (_("%s: illegal relocation type %d at address 0x%lx"),
bfd_get_filename (abfd), dst.r_type, (long) dst.r_vaddr);
bfd_set_error (bfd_error_bad_value);
return false;
#define coff_link_add_one_symbol _bfd_generic_link_add_one_symbol
#endif
+#ifndef coff_link_output_has_begun
+
+static boolean coff_link_output_has_begun
+ PARAMS ((bfd *, struct coff_final_link_info *));
+
+static boolean
+coff_link_output_has_begun (abfd, info)
+ bfd * abfd;
+ struct coff_final_link_info * info;
+{
+ return abfd->output_has_begun;
+}
+#endif
+
+#ifndef coff_final_link_postscript
+
+static boolean coff_final_link_postscript
+ PARAMS ((bfd *, struct coff_final_link_info *));
+
+static boolean
+coff_final_link_postscript (abfd, pfinfo)
+ bfd * abfd;
+ struct coff_final_link_info * pfinfo;
+{
+ return true;
+}
+#endif
+
+#ifndef coff_SWAP_aux_in
+#define coff_SWAP_aux_in coff_swap_aux_in
+#endif
+#ifndef coff_SWAP_sym_in
+#define coff_SWAP_sym_in coff_swap_sym_in
+#endif
+#ifndef coff_SWAP_lineno_in
+#define coff_SWAP_lineno_in coff_swap_lineno_in
+#endif
+#ifndef coff_SWAP_aux_out
+#define coff_SWAP_aux_out coff_swap_aux_out
+#endif
+#ifndef coff_SWAP_sym_out
+#define coff_SWAP_sym_out coff_swap_sym_out
+#endif
+#ifndef coff_SWAP_lineno_out
+#define coff_SWAP_lineno_out coff_swap_lineno_out
+#endif
+#ifndef coff_SWAP_reloc_out
+#define coff_SWAP_reloc_out coff_swap_reloc_out
+#endif
+#ifndef coff_SWAP_filehdr_out
+#define coff_SWAP_filehdr_out coff_swap_filehdr_out
+#endif
+#ifndef coff_SWAP_aouthdr_out
+#define coff_SWAP_aouthdr_out coff_swap_aouthdr_out
+#endif
+#ifndef coff_SWAP_scnhdr_out
+#define coff_SWAP_scnhdr_out coff_swap_scnhdr_out
+#endif
+#ifndef coff_SWAP_reloc_in
+#define coff_SWAP_reloc_in coff_swap_reloc_in
+#endif
+#ifndef coff_SWAP_filehdr_in
+#define coff_SWAP_filehdr_in coff_swap_filehdr_in
+#endif
+#ifndef coff_SWAP_aouthdr_in
+#define coff_SWAP_aouthdr_in coff_swap_aouthdr_in
+#endif
+#ifndef coff_SWAP_scnhdr_in
+#define coff_SWAP_scnhdr_in coff_swap_scnhdr_in
+#endif
+
+
+
static CONST bfd_coff_backend_data bfd_coff_std_swap_table =
{
- coff_swap_aux_in, coff_swap_sym_in, coff_swap_lineno_in,
- coff_swap_aux_out, coff_swap_sym_out,
- coff_swap_lineno_out, coff_swap_reloc_out,
- coff_swap_filehdr_out, coff_swap_aouthdr_out,
- coff_swap_scnhdr_out,
+ coff_SWAP_aux_in, coff_SWAP_sym_in, coff_SWAP_lineno_in,
+ coff_SWAP_aux_out, coff_SWAP_sym_out,
+ coff_SWAP_lineno_out, coff_SWAP_reloc_out,
+ coff_SWAP_filehdr_out, coff_SWAP_aouthdr_out,
+ coff_SWAP_scnhdr_out,
FILHSZ, AOUTSZ, SCNHSZ, SYMESZ, AUXESZ, RELSZ, LINESZ,
#ifdef COFF_LONG_FILENAMES
true,
false,
#endif
COFF_DEFAULT_SECTION_ALIGNMENT_POWER,
- coff_swap_filehdr_in, coff_swap_aouthdr_in, coff_swap_scnhdr_in,
- coff_swap_reloc_in, coff_bad_format_hook, coff_set_arch_mach_hook,
+ coff_SWAP_filehdr_in, coff_SWAP_aouthdr_in, coff_SWAP_scnhdr_in,
+ coff_SWAP_reloc_in, coff_bad_format_hook, coff_set_arch_mach_hook,
coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook,
coff_slurp_symbol_table, symname_in_debug_hook, coff_pointerize_aux_hook,
coff_print_aux, coff_reloc16_extra_cases, coff_reloc16_estimate,
coff_sym_is_global, coff_compute_section_file_positions,
coff_start_final_link, coff_relocate_section, coff_rtype_to_howto,
- coff_adjust_symndx, coff_link_add_one_symbol
+ coff_adjust_symndx, coff_link_add_one_symbol,
+ coff_link_output_has_begun, coff_final_link_postscript
};
#ifndef coff_close_and_cleanup
#ifndef coff_bfd_relax_section
#define coff_bfd_relax_section bfd_generic_relax_section
#endif
+
+#ifndef coff_bfd_gc_sections
+#define coff_bfd_gc_sections bfd_generic_gc_sections
+#endif