aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog5
-rw-r--r--bfd/cofflink.c40
2 files changed, 45 insertions, 0 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 7d00945..ead122e 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,8 @@
+1999-09-12 Ian Lance Taylor <ian@zembu.com>
+
+ * cofflink.c (coff_link_add_symbols): Look for special MSVC string
+ constant symbols, and avoid multiple definition errors on them.
+
1999-09-12 Donn Terry <donn@interix.com>
* libbfd.c (bfd_log2): Rewrite to avoid infinite loop if most
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index 113158c..1ab416d 100644
--- a/bfd/cofflink.c
+++ b/bfd/cofflink.c
@@ -422,6 +422,46 @@ coff_link_add_symbols (abfd, info)
}
}
+ /* The Microsoft Visual C compiler does string pooling by
+ hashing the constants to an internal symbol name, and
+ relying on the the linker comdat support to discard
+ duplicate names. However, if one string is a literal and
+ one is a data initializer, one will end up in the .data
+ section and one will end up in the .rdata section. The
+ Microsoft linker will combine them into the .data
+ section, which seems to be wrong since it might cause the
+ literal to change.
+
+ As long as there are no external references to the
+ symbols, which there shouldn't be, we can treat the .data
+ and .rdata instances as separate symbols. The comdat
+ code in the linker will do the appropriate merging. Here
+ we avoid getting a multiple definition error for one of
+ these special symbols.
+
+ FIXME: I don't think this will work in the case where
+ there are two object files which use the constants as a
+ literal and two object files which use it as a data
+ initializer. One or the other of the second object files
+ is going to wind up with an inappropriate reference. */
+ if (obj_pe (abfd)
+ && (classification == COFF_SYMBOL_GLOBAL
+ || classification == COFF_SYMBOL_PE_SECTION)
+ && section->comdat != NULL
+ && strncmp (name, "??_", 3) == 0
+ && strcmp (name, section->comdat->name) == 0)
+ {
+ if (*sym_hash == NULL)
+ *sym_hash = coff_link_hash_lookup (coff_hash_table (info),
+ name, false, copy, false);
+ if (*sym_hash != NULL
+ && (*sym_hash)->root.type == bfd_link_hash_defined
+ && (*sym_hash)->root.u.def.section->comdat != NULL
+ && strcmp ((*sym_hash)->root.u.def.section->comdat->name,
+ section->comdat->name) == 0)
+ addit = false;
+ }
+
if (addit)
{
if (! (bfd_coff_link_add_one_symbol