Index: pe-dll.c =================================================================== RCS file: /cvs/src/src/ld/pe-dll.c,v retrieving revision 1.60 diff -u -3 -p -B -r1.60 pe-dll.c --- pe-dll.c 17 Jul 2003 15:47:49 -0000 1.60 +++ pe-dll.c 28 Aug 2003 19:45:39 -0000 @@ -120,6 +120,44 @@ See also: ld/emultempl/pe.em. */ +/* gcc3 support for direct-linking-to-dll and auto-import + + Background: + + gcc2/3 stores regular initialized variables in the .data and uninitialized + variables in the .bss section. While gcc2 stores constant variables also in + the .data section, gcc3 stores constant variables in the .text section. + + This is no problem when using import libraries, but using the direct-linking- + to-dll feature with gcc3 compiled sources let the auto-import stuff fail because + data variables are only expected to be in the .data section, which results in + not auto-imported data variables; they are linked as functions and this results + in runtime segfaults. + + How it works: + + The gcc3 support for direct-linking-to-dll and auto-import remove this + limitation in two steps: + 1. On linking a dll exported constant variables are prefixed with a string + (CONST_KEY), which could not be emulated by regular c++ symbols to avoid + unwanted triggering of the auto-import stuff. + 2. On linking a dll or application with another dll containing exported const + symbols ld searches for such prefixed symbols and auto-import this symbols + like regular data symbols. + + Example: + const int constvar = 2; => .const$constvar + + class test { + static const int staticconstvar; => .const$_ZN4test14staticconstvarE + } +*/ + +/* name prefix for gcc3 direct-linking-to-dll and auto-import support */ +#define CONST_KEY ".const$" +#define CONST_KEY_SIZE 7 + + static void add_bfd_to_link (bfd *, const char *, struct bfd_link_info *); /* For emultempl/pe.em. */ @@ -536,11 +574,13 @@ process_def_file (bfd *abfd ATTRIBUTE_UN { asymbol **symbols; int nsyms, symsize; + asection *section_text; symsize = bfd_get_symtab_upper_bound (b); symbols = xmalloc (symsize); nsyms = bfd_canonicalize_symtab (b, symbols); - + section_text = bfd_get_section_by_name (b, ".text"); + for (j = 0; j < nsyms; j++) { /* We should export symbols which are either global or not @@ -571,9 +611,25 @@ process_def_file (bfd *abfd ATTRIBUTE_UN if (auto_export (b, pe_def_file, sn)) { def_file_export *p; - p=def_file_add_export (pe_def_file, sn, 0, -1); - /* Fill data flag properly, from dlltool.c. */ - p->flag_data = !(symbols[j]->flags & BSF_FUNCTION); + + /* prefix CONST_KEY to symbolname in case of data symbols + pointing to the text segment (const vars) to support auto-import */ + if (!(symbols[j]->flags & BSF_FUNCTION) && + symbols[j]->section == section_text) + { + char *prefix = CONST_KEY; + char *tmp = xmalloc (strlen(sn) + strlen(prefix) + 1); + strcpy(tmp,prefix); + strcat(tmp,sn); + p=def_file_add_export (pe_def_file, tmp, sn, -1); + p->flag_data = 1; + } + else + { + p=def_file_add_export (pe_def_file, sn, 0, -1); + /* Fill data flag properly, from dlltool.c. */ + p->flag_data = !(symbols[j]->flags & BSF_FUNCTION); + } } } } @@ -2246,17 +2303,23 @@ pe_dll_generate_implib (def_file *def, c for (i = 0; i < def->num_exports; i++) { - /* The import library doesn't know about the internal name. */ - char *internal = def->exports[i].internal_name; bfd *n; - - def->exports[i].internal_name = def->exports[i].name; - n = make_one (def->exports + i, outarch); - n->next = head; - head = n; - def->exports[i].internal_name = internal; - } - + /* the prefix CONST_KEY used for const var symbols must not be put into the import library */ + if (strncmp(def->exports[i].name,CONST_KEY,CONST_KEY_SIZE) == 0) { + char *external = def->exports[i].name; + def->exports[i].name = def->exports[i].internal_name; + n = make_one (def->exports + i, outarch); + def->exports[i].name = external; + } else { + /* The import library doesn't know about the internal name. */ + char *internal = def->exports[i].internal_name; + def->exports[i].internal_name = def->exports[i].name; + n = make_one (def->exports + i, outarch); + def->exports[i].internal_name = internal; + } + n->next = head; + head = n; + } ar_tail = make_tail (outarch); if (ar_head == NULL || ar_tail == NULL) @@ -2567,26 +2630,32 @@ pe_implied_import_dll (const char *filen def_file_import *imp; /* Pointer to the function address vector. */ unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4); - int is_data = 0; + char *sym_name = erva + name_rva; /* Skip unwanted symbols, which are exported in buggy auto-import releases. */ - if (strncmp (erva + name_rva, "_nm_", 4) != 0) + if (strncmp (sym_name, "_nm_", 4) != 0) { - /* is_data is true if the address is in the data or bss segment. */ - is_data = - (func_rva >= data_start && func_rva < data_end) - || (func_rva >= bss_start && func_rva < bss_end); - - imp = def_file_add_import (pe_def_file, erva + name_rva, + /* handle const var auto-importing with direct linking to dll */ + if (strncmp (sym_name, CONST_KEY, CONST_KEY_SIZE) == 0 ) + { + imp = def_file_add_import (pe_def_file, sym_name, + dll_name, i, sym_name+CONST_KEY_SIZE); + imp->data = 1; + } + else + { + imp = def_file_add_import (pe_def_file, sym_name, dll_name, i, 0); - /* 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__, dll_name, erva + name_rva, - func_rva, is_data ? "(data)" : ""); + /* symbol is data if the address is in the data or bss segment. */ + imp->data = + (func_rva >= data_start && func_rva < data_end) + || (func_rva >= bss_start && func_rva < bss_end); + } + if (pe_dll_extra_pe_debug) + printf ("%s dll-name: %s sym: %s addr: 0x%lx %s\n", + __FUNCTION__, dll_name, sym_name, + func_rva, imp->data ? "(data)" : ""); } }