diff options
author | Ian Lance Taylor <ian@airs.com> | 1999-09-12 16:28:20 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1999-09-12 16:28:20 +0000 |
commit | 49147fca36763ec648aea5b9bdbb270556146103 (patch) | |
tree | 2d4071fbc73b1529b93909bc2bd03e109c22f3bd /bfd/cofflink.c | |
parent | bb8fe706a0428fb66102378066d64af3796f0487 (diff) | |
download | fsf-binutils-gdb-49147fca36763ec648aea5b9bdbb270556146103.zip fsf-binutils-gdb-49147fca36763ec648aea5b9bdbb270556146103.tar.gz fsf-binutils-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.c | 40 |
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 |