diff options
author | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2018-04-04 12:13:05 +0200 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2018-04-04 12:13:05 +0200 |
commit | 9d8e8f445c1a021a1e381f4bd0bbc756b4258038 (patch) | |
tree | 9c525142c2dce2687d24bda075f470a82f245d44 /ld/pe-dll.c | |
parent | 317ff0084bc68bfae2eabd82015e9239a68b5195 (diff) | |
download | gdb-9d8e8f445c1a021a1e381f4bd0bbc756b4258038.zip gdb-9d8e8f445c1a021a1e381f4bd0bbc756b4258038.tar.gz gdb-9d8e8f445c1a021a1e381f4bd0bbc756b4258038.tar.bz2 |
Speed up direct linking with DLLs on Windows (2/2).
This patch deals with the generation of the import library on the fly.
The implementation is inefficient because the linker makes a lot of
calls to realloc and memmove when importing the symbols in order to
maintain a sorted list of symbols.
This is fixable by relying on the fact that, for every linked DLL,
the list of symbols it exports is already sorted so you can import
them en masse once you have found the insertion point.
ld/
* 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.
Diffstat (limited to 'ld/pe-dll.c')
-rw-r--r-- | ld/pe-dll.c | 35 |
1 files changed, 35 insertions, 0 deletions
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++) { |