aboutsummaryrefslogtreecommitdiff
path: root/ld/emultempl
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2017-04-11 19:37:51 +0930
committerAlan Modra <amodra@gmail.com>2017-04-11 19:49:13 +0930
commitfbea15088db59186960134d11b8bf98070224d6c (patch)
treeb90e6c1a439b2a2441f0075b97198018a60c610e /ld/emultempl
parentb43c520dba2f909c9bbb3ff5f2657c1c9010939b (diff)
downloadgdb-fbea15088db59186960134d11b8bf98070224d6c.zip
gdb-fbea15088db59186960134d11b8bf98070224d6c.tar.gz
gdb-fbea15088db59186960134d11b8bf98070224d6c.tar.bz2
PR 21274, ld segfaults linking PE DLL
Don't use fixed size buffers for symbol names. PR 21274 PR 18466 * emultempl/pe.em (pe_find_data_imports): Don't use fixed size symbol buffer. Instead, xmalloc max size needed with space for prefix. Wrap overlong lines. Formatting. Pass symbol buffer copy of name to pe_walk_relocs_of_symbol. (make_inport_fixup): Add "name" param, pass to pe_create_import_fixup. * emultempl/pe.em (pep_find_data_imports): As for pe_find_data_imports. (make_import_fixup): Add "name" param, pass to pep_create_import_fixup. Use bfd_get_signed_* and remove unnecessary casts. Formatting. * pe-dll.c (pe_walk_relocs_of_symbol): Add "name" param. Pass to callback. (make_import_fixup_mark): Add "name" param. Make use of prefix space rather than xmalloc here. (pe_create_import_fixup): Likewise. * pe-dll.h (pe_walk_relocs_of_symbol): Update prototype. (pe_create_import_fixup): Likewise. * pep-dll.h (pep_walk_relocs_of_symbol): Likewise. (pep_create_import_fixup): Likewise.
Diffstat (limited to 'ld/emultempl')
-rw-r--r--ld/emultempl/pe.em64
-rw-r--r--ld/emultempl/pep.em116
2 files changed, 106 insertions, 74 deletions
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index 8f41f27..e835404 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -1130,7 +1130,7 @@ pe_fixup_stdcalls (void)
}
static int
-make_import_fixup (arelent *rel, asection *s)
+make_import_fixup (arelent *rel, asection *s, char *name)
{
struct bfd_symbol *sym = *rel->sym_ptr_ptr;
char addend[4];
@@ -1143,7 +1143,7 @@ make_import_fixup (arelent *rel, asection *s)
einfo (_("%C: Cannot get section contents - auto-import exception\n"),
s->owner, s, rel->address);
- pe_create_import_fixup (rel, s, bfd_get_32 (s->owner, addend));
+ pe_create_import_fixup (rel, s, bfd_get_32 (s->owner, addend), name);
return 1;
}
@@ -1152,32 +1152,46 @@ static void
pe_find_data_imports (void)
{
struct bfd_link_hash_entry *undef, *sym;
+ size_t namelen;
+ char *buf, *name;
if (link_info.pei386_auto_import == 0)
return;
- for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next)
+ namelen = 0;
+ for (undef = link_info.hash->undefs; undef; undef = undef->u.undef.next)
+ {
+ if (undef->type == bfd_link_hash_undefined)
+ {
+ size_t len = strlen (undef->root.string);
+ if (namelen < len)
+ namelen = len;
+ }
+ }
+ if (namelen == 0)
+ return;
+
+ /* We are being a bit cunning here. The buffer will have space for
+ prefixes at the beginning. The prefix is modified here and in a
+ number of functions called from this function. */
+#define PREFIX_LEN 32
+ buf = xmalloc (PREFIX_LEN + namelen + 1);
+ name = buf + PREFIX_LEN;
+
+ for (undef = link_info.hash->undefs; undef; undef = undef->u.undef.next)
{
if (undef->type == bfd_link_hash_undefined)
{
- /* C++ symbols are *long*. */
-#define BUF_SIZE 4096
- char buf[BUF_SIZE];
+ char *impname;
if (pe_dll_extra_pe_debug)
printf ("%s:%s\n", __FUNCTION__, undef->root.string);
- if (strlen (undef->root.string) > (BUF_SIZE - 6))
- {
- /* PR linker/18466. */
- einfo (_("%P: internal error: symbol too long: %s\n"),
- undef->root.string);
- return;
- }
-
- sprintf (buf, "__imp_%s", undef->root.string);
+ strcpy (name, undef->root.string);
+ impname = name - (sizeof "__imp_" - 1);
+ memcpy (impname, "__imp_", sizeof "__imp_" - 1);
- sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
+ sym = bfd_link_hash_lookup (link_info.hash, impname, 0, 0, 1);
if (sym && sym->type == bfd_link_hash_defined)
{
@@ -1189,15 +1203,18 @@ pe_find_data_imports (void)
{
static bfd_boolean warned = FALSE;
- info_msg (_("Info: resolving %s by linking to %s (auto-import)\n"),
- undef->root.string, buf);
+ info_msg (_("Info: resolving %s by linking to %s "
+ "(auto-import)\n"), name, impname);
/* PR linker/4844. */
if (! warned)
{
warned = TRUE;
- einfo (_("%P: warning: auto-importing has been activated without --enable-auto-import specified on the command line.\n\
-This should work unless it involves constant data structures referencing symbols from auto-imported DLLs.\n"));
+ einfo (_("%P: warning: auto-importing has been activated "
+ "without --enable-auto-import specified on the "
+ "command line.\nThis should work unless it "
+ "involves constant data structures referencing "
+ "symbols from auto-imported DLLs.\n"));
}
}
@@ -1212,8 +1229,7 @@ This should work unless it involves constant data structures referencing symbols
for (i = 0; i < nsyms; i++)
{
- if (! CONST_STRNEQ (symbols[i]->name,
- U ("_head_")))
+ if (! CONST_STRNEQ (symbols[i]->name, U ("_head_")))
continue;
if (pe_dll_extra_pe_debug)
@@ -1224,8 +1240,7 @@ This should work unless it involves constant data structures referencing symbols
break;
}
- pe_walk_relocs_of_symbol (&link_info, undef->root.string,
- make_import_fixup);
+ pe_walk_relocs_of_symbol (&link_info, name, make_import_fixup);
/* Let's differentiate it somehow from defined. */
undef->type = bfd_link_hash_defweak;
@@ -1238,6 +1253,7 @@ This should work unless it involves constant data structures referencing symbols
}
}
}
+ free (buf);
}
static bfd_boolean
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index 8c7ed88..59812ce 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -1075,7 +1075,7 @@ pep_fixup_stdcalls (void)
}
static int
-make_import_fixup (arelent *rel, asection *s)
+make_import_fixup (arelent *rel, asection *s, char *name)
{
struct bfd_symbol *sym = *rel->sym_ptr_ptr;
char addend[8];
@@ -1089,32 +1089,32 @@ make_import_fixup (arelent *rel, asection *s)
memset (addend, 0, sizeof (addend));
switch ((rel->howto->bitsize))
{
- case 8:
- suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 1);
- if (suc && rel->howto->pc_relative)
- _addend = (bfd_vma) ((bfd_signed_vma) ((char) bfd_get_8 (s->owner, addend)));
- else if (suc)
- _addend = ((bfd_vma) bfd_get_8 (s->owner, addend)) & 0xff;
- break;
- case 16:
- suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 2);
- if (suc && rel->howto->pc_relative)
- _addend = (bfd_vma) ((bfd_signed_vma) ((short) bfd_get_16 (s->owner, addend)));
- else if (suc)
- _addend = ((bfd_vma) bfd_get_16 (s->owner, addend)) & 0xffff;
- break;
- case 32:
- suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 4);
- if (suc && rel->howto->pc_relative)
- _addend = (bfd_vma) ((bfd_signed_vma) ((int) bfd_get_32 (s->owner, addend)));
- else if (suc)
- _addend = ((bfd_vma) bfd_get_32 (s->owner, addend)) & 0xffffffff;
- break;
- case 64:
- suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 8);
- if (suc)
- _addend = ((bfd_vma) bfd_get_64 (s->owner, addend));
- break;
+ case 8:
+ suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 1);
+ if (suc && rel->howto->pc_relative)
+ _addend = bfd_get_signed_8 (s->owner, addend);
+ else if (suc)
+ _addend = bfd_get_8 (s->owner, addend);
+ break;
+ case 16:
+ suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 2);
+ if (suc && rel->howto->pc_relative)
+ _addend = bfd_get_signed_16 (s->owner, addend);
+ else if (suc)
+ _addend = bfd_get_16 (s->owner, addend);
+ break;
+ case 32:
+ suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 4);
+ if (suc && rel->howto->pc_relative)
+ _addend = bfd_get_signed_32 (s->owner, addend);
+ else if (suc)
+ _addend = bfd_get_32 (s->owner, addend);
+ break;
+ case 64:
+ suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 8);
+ if (suc)
+ _addend = bfd_get_64 (s->owner, addend);
+ break;
}
if (! suc)
einfo (_("%C: Cannot get section contents - auto-import exception\n"),
@@ -1122,11 +1122,13 @@ make_import_fixup (arelent *rel, asection *s)
if (pep_dll_extra_pe_debug)
{
- printf ("import of 0x%lx(0x%lx) sec_addr=0x%lx", (long) _addend, (long) rel->addend, (long) rel->address);
- if (rel->howto->pc_relative) printf (" pcrel");
- printf (" %d bit rel.\n",(int) rel->howto->bitsize);
- }
- pep_create_import_fixup (rel, s, _addend);
+ printf ("import of 0x%lx(0x%lx) sec_addr=0x%lx",
+ (long) _addend, (long) rel->addend, (long) rel->address);
+ if (rel->howto->pc_relative)
+ printf (" pcrel");
+ printf (" %d bit rel.\n", (int) rel->howto->bitsize);
+ }
+ pep_create_import_fixup (rel, s, _addend, name);
return 1;
}
@@ -1135,32 +1137,46 @@ static void
pep_find_data_imports (void)
{
struct bfd_link_hash_entry *undef, *sym;
+ size_t namelen;
+ char *buf, *name;
if (link_info.pei386_auto_import == 0)
return;
- for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next)
+ namelen = 0;
+ for (undef = link_info.hash->undefs; undef; undef = undef->u.undef.next)
{
if (undef->type == bfd_link_hash_undefined)
{
- /* C++ symbols are *long*. */
-#define BUF_SIZE 4096
- char buf[BUF_SIZE];
+ size_t len = strlen (undef->root.string);
+ if (namelen < len)
+ namelen = len;
+ }
+ }
+ if (namelen == 0)
+ return;
+
+ /* We are being a bit cunning here. The buffer will have space for
+ prefixes at the beginning. The prefix is modified here and in a
+ number of functions called from this function. */
+#define PREFIX_LEN 32
+ buf = xmalloc (PREFIX_LEN + namelen + 1);
+ name = buf + PREFIX_LEN;
+
+ for (undef = link_info.hash->undefs; undef; undef = undef->u.undef.next)
+ {
+ if (undef->type == bfd_link_hash_undefined)
+ {
+ char *impname;
if (pep_dll_extra_pe_debug)
printf ("%s:%s\n", __FUNCTION__, undef->root.string);
- if (strlen (undef->root.string) > (BUF_SIZE - 6))
- {
- /* PR linker/18466. */
- einfo (_("%P: internal error: symbol too long: %s\n"),
- undef->root.string);
- return;
- }
-
- sprintf (buf, "__imp_%s", undef->root.string);
+ strcpy (name, undef->root.string);
+ impname = name - (sizeof "__imp_" - 1);
+ memcpy (impname, "__imp_", sizeof "__imp_" - 1);
- sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
+ sym = bfd_link_hash_lookup (link_info.hash, impname, 0, 0, 1);
if (sym && sym->type == bfd_link_hash_defined)
{
@@ -1185,13 +1201,12 @@ pep_find_data_imports (void)
if (pep_dll_extra_pe_debug)
printf ("->%s\n", symbols[i]->name);
- pep_data_import_dll = (char*) (symbols[i]->name +
- U_SIZE ("_head_") - 1);
+ pep_data_import_dll = (char *) (symbols[i]->name
+ + U_SIZE ("_head_") - 1);
break;
}
- pep_walk_relocs_of_symbol (&link_info, undef->root.string,
- make_import_fixup);
+ pep_walk_relocs_of_symbol (&link_info, name, make_import_fixup);
/* Let's differentiate it somehow from defined. */
undef->type = bfd_link_hash_defweak;
@@ -1204,6 +1219,7 @@ pep_find_data_imports (void)
}
}
}
+ free (buf);
}
static bfd_boolean