aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
Diffstat (limited to 'ld')
-rw-r--r--ld/ChangeLog11
-rw-r--r--ld/deffile.h10
-rw-r--r--ld/deffilep.y100
-rw-r--r--ld/pe-dll.c35
4 files changed, 144 insertions, 12 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index b1a1dda..c6f85ff 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,5 +1,16 @@
2018-04-04 Eric Botcazou <ebotcazou@adacore.com>
+ * deffile.h (def_file_add_import_from): Declare.
+ (def_file_add_import_at): Likewise.
+ * deffilep.y (fill_in_import): New function extracted from...
+ (def_file_add_import): ...here. Call it.
+ (def_file_add_import_from): New function.
+ (def_file_add_import_at): Likewise.
+ * pe-dll.c (pe_implied_import_dll): Use an optimized version of the
+ insertion loop for imported symbols if possible.
+
+2018-04-04 Eric Botcazou <ebotcazou@adacore.com>
+
* emultempl/pe.em (U_SIZE): Delete.
(pe_data_import_dll): Likewise.
(make_import_fixup): Return void, take 4th parameter and pass it down
diff --git a/ld/deffile.h b/ld/deffile.h
index 9a1e539..4275e71 100644
--- a/ld/deffile.h
+++ b/ld/deffile.h
@@ -108,6 +108,16 @@ extern def_file_export *def_file_add_export (def_file *, const char *,
extern def_file_import *def_file_add_import (def_file *, const char *,
const char *, int, const char *,
const char *, int *);
+extern int def_file_add_import_from (def_file *fdef,
+ int num_imports,
+ const char *name,
+ const char *module,
+ int ordinal,
+ const char *internal_name,
+ const char *its_name);
+extern def_file_import *def_file_add_import_at (def_file *, int, const char *,
+ const char *, int, const char *,
+ const char *);
extern void def_file_add_directive (def_file *, const char *, int);
extern def_file_module *def_get_module (def_file *, const char *);
#ifdef DEF_FILE_PRINT
diff --git a/ld/deffilep.y b/ld/deffilep.y
index 1931c00..1aebdf6 100644
--- a/ld/deffilep.y
+++ b/ld/deffilep.y
@@ -816,6 +816,26 @@ find_import_in_list (def_file_import *b, int max,
return l;
}
+static void
+fill_in_import (def_file_import *i,
+ const char *name,
+ def_file_module *module,
+ int ordinal,
+ const char *internal_name,
+ const char *its_name)
+{
+ memset (i, 0, sizeof (def_file_import));
+ if (name)
+ i->name = xstrdup (name);
+ i->module = module;
+ i->ordinal = ordinal;
+ if (internal_name)
+ i->internal_name = xstrdup (internal_name);
+ else
+ i->internal_name = i->name;
+ i->its_name = (its_name ? xstrdup (its_name) : NULL);
+}
+
def_file_import *
def_file_add_import (def_file *fdef,
const char *name,
@@ -850,18 +870,74 @@ def_file_add_import (def_file *fdef,
}
i = fdef->imports + pos;
if (pos != fdef->num_imports)
- memmove (&i[1], i, (sizeof (def_file_import) * (fdef->num_imports - pos)));
- memset (i, 0, sizeof (def_file_import));
- if (name)
- i->name = xstrdup (name);
- if (module)
- i->module = def_stash_module (fdef, module);
- i->ordinal = ordinal;
- if (internal_name)
- i->internal_name = xstrdup (internal_name);
- else
- i->internal_name = i->name;
- i->its_name = (its_name ? xstrdup (its_name) : NULL);
+ memmove (i + 1, i, sizeof (def_file_import) * (fdef->num_imports - pos));
+
+ fill_in_import (i, name, def_stash_module (fdef, module), ordinal,
+ internal_name, its_name);
+ fdef->num_imports++;
+
+ return i;
+}
+
+int
+def_file_add_import_from (def_file *fdef,
+ int num_imports,
+ const char *name,
+ const char *module,
+ int ordinal,
+ const char *internal_name,
+ const char *its_name ATTRIBUTE_UNUSED)
+{
+ def_file_import *i;
+ int is_dup;
+ int pos;
+ int max_imports = ROUND_UP (fdef->num_imports, 16);
+
+ /* We need to avoid here duplicates. */
+ is_dup = 0;
+ pos = find_import_in_list (fdef->imports, fdef->num_imports,
+ name, internal_name ? internal_name : name,
+ module, ordinal, &is_dup);
+ if (is_dup != 0)
+ return -1;
+ if (fdef->imports && pos != fdef->num_imports)
+ {
+ i = fdef->imports + pos;
+ if (i->module && strcmp (i->module->name, module) == 0)
+ return -1;
+ }
+
+ if (fdef->num_imports + num_imports - 1 >= max_imports)
+ {
+ max_imports = ROUND_UP (fdef->num_imports + num_imports, 16);
+
+ if (fdef->imports)
+ fdef->imports = xrealloc (fdef->imports,
+ max_imports * sizeof (def_file_import));
+ else
+ fdef->imports = xmalloc (max_imports * sizeof (def_file_import));
+ }
+ i = fdef->imports + pos;
+ if (pos != fdef->num_imports)
+ memmove (i + num_imports, i,
+ sizeof (def_file_import) * (fdef->num_imports - pos));
+
+ return pos;
+}
+
+def_file_import *
+def_file_add_import_at (def_file *fdef,
+ int pos,
+ const char *name,
+ const char *module,
+ int ordinal,
+ const char *internal_name,
+ const char *its_name)
+{
+ def_file_import *i = fdef->imports + pos;
+
+ fill_in_import (i, name, def_stash_module (fdef, module), ordinal,
+ internal_name, its_name);
fdef->num_imports++;
return i;
diff --git a/ld/pe-dll.c b/ld/pe-dll.c
index ad0ffcf..efb75f2 100644
--- a/ld/pe-dll.c
+++ b/ld/pe-dll.c
@@ -3317,6 +3317,7 @@ pe_implied_import_dll (const char *filename)
bfd_vma rdata_end = 0;
bfd_vma bss_start = 1;
bfd_vma bss_end = 0;
+ int from;
/* No, I can't use bfd here. kernel32.dll puts its export table in
the middle of the .rdata section. */
@@ -3457,6 +3458,40 @@ pe_implied_import_dll (const char *filename)
return TRUE;
}
+ /* This is an optimized version of the insertion loop, which avoids lots of
+ calls to realloc and memmove from def_file_add_import. */
+ if ((from = def_file_add_import_from (pe_def_file, nexp,
+ erva + pe_as32 (erva + name_rvas),
+ dllname, 0, NULL, NULL)) >= 0)
+ {
+ for (i = 0; i < nexp; i++)
+ {
+ /* Pointer to the names vector. */
+ bfd_vma name_rva = pe_as32 (erva + name_rvas + i * 4);
+ def_file_import *imp;
+ /* Pointer to the function address vector. */
+ bfd_vma func_rva = pe_as32 (erva + exp_funcbase + i * 4);
+ /* is_data is true if the address is in the data, rdata or bss
+ segment. */
+ const int is_data =
+ (func_rva >= data_start && func_rva < data_end)
+ || (func_rva >= rdata_start && func_rva < rdata_end)
+ || (func_rva >= bss_start && func_rva < bss_end);
+
+ imp = def_file_add_import_at (pe_def_file, from + i, erva + name_rva,
+ dllname, i, NULL, NULL);
+ /* Mark symbol type. */
+ imp->data = is_data;
+
+ if (pe_dll_extra_pe_debug)
+ printf ("%s dll-name: %s sym: %s addr: 0x%lx %s\n",
+ __FUNCTION__, dllname, erva + name_rva,
+ (unsigned long) func_rva, is_data ? "(data)" : "");
+ }
+
+ return TRUE;
+ }
+
/* Iterate through the list of symbols. */
for (i = 0; i < nexp; i++)
{