if (_bfd_coff_get_external_symbols (abfd))
{
bfd_byte *esymstart, *esym, *esymend;
+ int seen_state = 0;
+ char *target_name;
esymstart = esym = (bfd_byte *) obj_coff_external_syms (abfd);
esymend = esym + obj_raw_syment_count (abfd) * SYMESZ;
abort ();
}
- /* The MS documentation is vague, but it appears to
- require that n_sclass be C_STAT for both entries;
- However, the Alpha compiler uses C_EXT for the one
- with the "real" name, at least for string-pooled
- constants. */
- if (isym.n_scnum == section->target_index
- && (isym.n_sclass == C_STAT || isym.n_sclass == C_EXT)
- && isym.n_type == T_NULL
- && isym.n_value == 0)
+ if (isym.n_scnum == section->target_index)
{
- /* The first TWO entries with the section # are both
- of interest to us. The first one is the "section
+ /* According to the MSVC documentation, the first
+ TWO entries with the section # are both of
+ interest to us. The first one is the "section
symbol" (section name). The second is the comdat
- symbol name. 'value' must be zero for it to
- apply. Here, we've found a qualifying entry; we
- distinguish the first from the second by numaux
- (which should be 0 for the second). FIXME: We
- should use the first one first rather than
- counting on numaux. */
- if (isym.n_numaux == 1)
- {
- union internal_auxent aux;
+ symbol name. Here, we've found the first
+ qualifying entry; we distinguish it from the
+ second with a state flag.
- symname = _bfd_coff_internal_syment_name (abfd, &isym,
- buf);
- if (symname == NULL)
- abort ();
+ In the case of gas-generated (at least until that
+ is fixed) .o files, it isn't necessarily the
+ second one. It may be some other later symbol.
- if (strcmp (name, symname) != 0)
- abort ();
+ Since gas also doesn't follow MS conventions and
+ emits the section similar to .text$<name>, where
+ <something> is the name we're looking for, we
+ distinguish the two as follows:
- /* This is the section symbol. */
+ If the section name is simply a section name (no
+ $) we presume it's MS-generated, and look at
+ precisely the second symbol for the comdat name.
+ If the section name has a $, we assume it's
+ gas-generated, and look for <something> (whatever
+ follows the $) as the comdat symbol. */
- bfd_coff_swap_aux_in (abfd, (PTR) (esym + SYMESZ),
- isym.n_type, isym.n_sclass,
- 0, isym.n_numaux, (PTR) &aux);
+ /* All 3 branches use this */
+ symname = _bfd_coff_internal_syment_name (abfd, &isym, buf);
- /* 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. */
+ if (symname == NULL)
+ abort ();
- switch (aux.x_scn.x_comdat)
- {
- case IMAGE_COMDAT_SELECT_NODUPLICATES:
-/* FIXME: This is bogus. It breaks cross-compilers. */
-#ifdef __INTERIX
- sec_flags |= SEC_LINK_DUPLICATES_ONE_ONLY;
+ switch (seen_state)
+ {
+ case 0:
+ {
+ /* The first time we've seen the symbol. */
+ union internal_auxent aux;
+
+ seen_state = 1;
+
+ /* If it isn't the stuff we're expecting, die;
+ The MS documentation is vague, but it
+ appears that the second entry serves BOTH
+ as the comdat symbol and the defining
+ symbol record (either C_STAT or C_EXT,
+ possibly with an aux entry with debug
+ information if it's a function.) It
+ appears the only way to find the second one
+ is to count. (On Intel, they appear to be
+ adjacent, but on Alpha, they have been
+ found separated.)
+
+ Here, we think we've found the first one,
+ but there's some checking we can do to be
+ sure. */
+
+ if (! (isym.n_sclass == C_STAT
+ && isym.n_type == T_NULL
+ && isym.n_value == 0))
+ abort ();
+
+ /* FIXME LATER: MSVC generates section names
+ like .text for comdats. Gas generates
+ names like .text$foo__Fv (in the case of a
+ function). See comment above for more. */
+
+ if (strcmp (name, symname) != 0)
+ abort ();
+
+ /* This is the section symbol. */
+
+ bfd_coff_swap_aux_in (abfd, (PTR) (esym + SYMESZ),
+ isym.n_type, isym.n_sclass,
+ 0, isym.n_numaux, (PTR) &aux);
+
+ target_name = strchr (name, '$');
+ if (target_name != NULL)
+ {
+ /* Gas mode. */
+ seen_state = 2;
+ /* Skip the `$'. */
+ target_name += 1;
+ }
+
+ /* 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. */
+
+ /* Cygwin does not follow the MS style, and
+ uses ANY and SAME_SIZE where NODUPLICATES
+ and ASSOCIATIVE should be used. For
+ Interix, we just do the right thing up
+ front. */
+
+ switch (aux.x_scn.x_comdat)
+ {
+ case IMAGE_COMDAT_SELECT_NODUPLICATES:
+#ifdef STRICT_PE_FORMAT
+ sec_flags |= SEC_LINK_DUPLICATES_ONE_ONLY;
+#else
+ sec_flags &= ~SEC_LINK_ONCE;
+#endif
+ break;
+
+ case IMAGE_COMDAT_SELECT_ANY:
+ sec_flags |= SEC_LINK_DUPLICATES_DISCARD;
+ break;
+
+ case IMAGE_COMDAT_SELECT_SAME_SIZE:
+ sec_flags |= SEC_LINK_DUPLICATES_SAME_SIZE;
+ break;
+
+ case IMAGE_COMDAT_SELECT_EXACT_MATCH:
+ /* Not yet fully implemented ??? */
+ sec_flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS;
+ break;
+
+ /* debug$S gets this case; other
+ implications ??? */
+
+ /* There may be no symbol... we'll search
+ the whole table... Is this the right
+ place to play this game? Or should we do
+ it when reading it in. */
+ case IMAGE_COMDAT_SELECT_ASSOCIATIVE:
+#ifdef STRICT_PE_FORMAT
+ /* FIXME: This is not currently implemented. */
+ sec_flags |= SEC_LINK_DUPLICATES_DISCARD;
#else
- sec_flags &= ~SEC_LINK_ONCE;
+ sec_flags &= ~SEC_LINK_ONCE;
#endif
- break;
-
- case IMAGE_COMDAT_SELECT_ANY:
- sec_flags |= SEC_LINK_DUPLICATES_DISCARD;
- break;
+ break;
- case IMAGE_COMDAT_SELECT_SAME_SIZE:
- sec_flags |= SEC_LINK_DUPLICATES_SAME_SIZE;
- break;
+ default: /* 0 means "no symbol" */
+ /* debug$F gets this case; other
+ implications ??? */
+ sec_flags |= SEC_LINK_DUPLICATES_DISCARD;
+ break;
+ }
+ }
+ break;
- case IMAGE_COMDAT_SELECT_EXACT_MATCH:
- /* Not yet fully implemented in the linker. */
- sec_flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS;
- break;
+ case 2:
+ /* Gas mode: the first matching on partial name. */
- case IMAGE_COMDAT_SELECT_ASSOCIATIVE:
-/* FIXME: This is bogus. It breaks cross-compilers. */
-#ifdef __INTERIX
- /* FIXME: This is not currently implemented. */
- sec_flags |= SEC_LINK_DUPLICATES_DISCARD;
-#else
- sec_flags &= ~SEC_LINK_ONCE;
+#ifndef TARGET_UNDERSCORE
+#define TARGET_UNDERSCORE 0
#endif
- break;
-
- default:
- /* FIXME: Shouldn't this be at least a
- warning? */
- sec_flags |= SEC_LINK_DUPLICATES_DISCARD;
- break;
+ /* Is this the name we're looking for? */
+ if (strcmp (target_name,
+ symname + (TARGET_UNDERSCORE ? 1 : 0)) != 0)
+ {
+ /* Not the name we're looking for */
+ esym += (isym.n_numaux + 1) * SYMESZ;
+ continue;
}
- }
- else
- {
- char *newname;
-
- /* This should be the the second symbol with the
- section #. It is the actual symbol name.
- Intel puts the two adjacent, but Alpha (at
- least) spreads them out. */
-
- section->comdat =
- bfd_alloc (abfd, sizeof (struct bfd_comdat_info));
- if (section->comdat == NULL)
- abort ();
- section->comdat->symbol = (esym - esymstart) / SYMESZ;
- symname = _bfd_coff_internal_syment_name (abfd, &isym,
- buf);
- if (symname == NULL)
- abort ();
-
- newname = bfd_alloc (abfd, strlen (symname) + 1);
- if (newname == NULL)
- abort ();
- strcpy (newname, symname);
- section->comdat->name = newname;
-
- break;
+ /* Fall through. */
+ case 1:
+ /* MSVC mode: the lexically second symbol (or
+ drop through from the above). */
+ {
+ char *newname;
+
+ /* This must the the second symbol with the
+ section #. It is the actual symbol name.
+ Intel puts the two adjacent, but Alpha (at
+ least) spreads them out. */
+
+ section->comdat =
+ bfd_alloc (abfd, sizeof (struct bfd_comdat_info));
+ if (section->comdat == NULL)
+ abort ();
+ section->comdat->symbol =
+ (esym - esymstart) / SYMESZ;
+
+ newname = bfd_alloc (abfd, strlen (symname) + 1);
+ if (newname == NULL)
+ abort ();
+
+ strcpy (newname, symname);
+ section->comdat->name = newname;
+
+ }
+
+ goto breakloop;
}
}
esym += (isym.n_numaux + 1) * SYMESZ;
}
+ breakloop:
}
}
ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_2BYTES, 1)
ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_1BYTES, 0)
-#ifdef POWERPC_LE_PE
- if (strcmp (section->name, ".idata$2") == 0)
- {
- section->alignment_power = 0;
- }
- else if (strcmp (section->name, ".idata$3") == 0)
- {
- section->alignment_power = 0;
- }
- else if (strcmp (section->name, ".idata$4") == 0)
- {
- section->alignment_power = 2;
- }
- else if (strcmp (section->name, ".idata$5") == 0)
- {
- section->alignment_power = 2;
- }
- else if (strcmp (section->name, ".idata$6") == 0)
- {
- section->alignment_power = 1;
- }
- else if (strcmp (section->name, ".reloc") == 0)
- {
- section->alignment_power = 1;
- }
- else if (strncmp (section->name, ".stab", 5) == 0)
- {
- section->alignment_power = 2;
- }
-#endif
-
/* In a PE image file, the s_paddr field holds the virtual size of a
section, while the s_size field holds the raw size. We also keep
the original section flag value, since not every bit can be
coff->local_auxesz = AUXESZ;
coff->local_linesz = LINESZ;
+ coff->timestamp = internal_f->f_timdat;
+
obj_raw_syment_count (abfd) =
obj_conv_table_size (abfd) =
internal_f->f_nsyms;
coff->flags = 0;
#endif
+#ifdef COFF_WITH_PE
+ /* FIXME: I'm not sure this is ever executed, since peicode.h
+ defines coff_mkobject_hook. */
+ if ((internal_f->f_flags & IMAGE_FILE_DEBUG_STRIPPED) == 0)
+ abfd->flags |= HAS_DEBUG;
+#endif
+
return (PTR) coff;
}
#endif
asection *current;
boolean hasrelocs = false;
boolean haslinno = false;
+ boolean hasdebug = false;
file_ptr scn_base;
file_ptr reloc_base;
file_ptr lineno_base;
current = current->next)
{
struct internal_scnhdr section;
-
-#ifdef COFF_WITH_PE
- /* If we've got a .reloc section, remember. */
+ boolean is_reloc_section = false;
#ifdef COFF_IMAGE_WITH_PE
if (strcmp (current->name, ".reloc") == 0)
{
+ is_reloc_section = true;
+ hasrelocs = true;
pe_data (abfd)->has_reloc_section = 1;
}
#endif
-#endif
internal_f.f_nscns++;
strncpy (section.s_name, current->name, SCNNMLEN);
section.s_lnnoptr = current->line_filepos;
section.s_nreloc = current->reloc_count;
section.s_nlnno = current->lineno_count;
+#ifndef COFF_IMAGE_WITH_PE
+ /* In PEI, relocs come in the .reloc section. */
if (current->reloc_count != 0)
hasrelocs = true;
+#endif
if (current->lineno_count != 0)
haslinno = true;
+ if ((current->flags & SEC_DEBUGGING) != 0
+ && ! is_reloc_section)
+ hasdebug = true;
#ifdef RS6000COFF_C
/* Indicate the use of an XCOFF overflow section header. */
internal_f.f_flags |= F_LNNO;
if (abfd->flags & EXEC_P)
internal_f.f_flags |= F_EXEC;
+#ifdef COFF_IMAGE_WITH_PE
+ if (! hasdebug)
+ internal_f.f_flags |= IMAGE_FILE_DEBUG_STRIPPED;
+#endif
#ifndef COFF_WITH_PE
if (bfd_little_endian (abfd))
return COFF_SYMBOL_LOCAL;
}
-#if 0
+#ifdef STRICT_PE_FORMAT
/* This is correct for Microsoft generated objects, but it
breaks gas generated objects. */