[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-cygwin
Subject: [PATCH] gcc3/ld patch for direct-linking-to-dll and auto-import
From: "Ralf Habacker" <Ralf.Habacker () freenet ! de>
Date: 2003-08-28 19:59:34
[Download RAW message or body]
Hi
while compiling trolltechs qt/xfree library with gcc3 (3.2x) on cygwin I
recognized, that the auto-import stuff in combination of recent ld does not work
in case of const variables in a dll when using direct linking to a dll, because
gcc put those variables into a readonly, that means the .text section.
The patch and a testcase is appended. A documentation could be found in the
patch file.
A binary update (only containing ld) could be found here:
http://kde-cygwin.sourceforge.net/snapshots/ld-gcc3-const-var-patch.tar.bz2
Cheers
Ralf
["ld-gcc3-const-var-patch-testcase.tar.bz2" (application/octet-stream)]
["ld-gcc3-const-var-patch.patch" (application/octet-stream)]
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)" : "");
}
}
_______________________________________________
kde-cygwin mailing list
kde-cygwin@mail.kde.org
http://mail.kde.org/mailman/listinfo/kde-cygwin
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic