aboutsummaryrefslogtreecommitdiff
path: root/bfd/cofflink.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1999-09-12 16:28:20 +0000
committerIan Lance Taylor <ian@airs.com>1999-09-12 16:28:20 +0000
commit49147fca36763ec648aea5b9bdbb270556146103 (patch)
tree2d4071fbc73b1529b93909bc2bd03e109c22f3bd /bfd/cofflink.c
parentbb8fe706a0428fb66102378066d64af3796f0487 (diff)
downloadgdb-49147fca36763ec648aea5b9bdbb270556146103.zip
gdb-49147fca36763ec648aea5b9bdbb270556146103.tar.gz
gdb-49147fca36763ec648aea5b9bdbb270556146103.tar.bz2
* cofflink.c (coff_link_add_symbols): Look for special MSVC string
constant symbols, and avoid multiple definition errors on them.
Diffstat (limited to 'bfd/cofflink.c')
-rw-r--r--bfd/cofflink.c40
1 files changed, 40 insertions, 0 deletions
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