diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 5 | ||||
-rw-r--r-- | bfd/cofflink.c | 40 |
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 |