This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

WG: ld --auto-import for cygwin and libtool


> Ralf Habacker wrote:
> >In a previous mail I told about segmentation faults with the
> auto-import ld
> on compiling kde2-libs.
> >This segmentation fault is caused be xmalloc thich returns a
> zero pointer.
> >I have analysed the stackdump and recognized that the exception
> occured in
> the cygwin dll in the >>>mount_info::conv_to_win32_path function
>
> Currently I'm creating a test case for this bug.
>
> Can anyone tell me, how I can get the number and types (func/var/... of
> loaded symbols ?
>

Regarding to the above bug I have found the reason for crashing ld. The bug
is restricted to the current implementation of the auto-import patch, which
has been discussed in this article containing the patch
http://sources.redhat.com/ml/binutils/2001-05/msg00025.html and other on the
binutils mailing list.

In some parts of the patch used memory wasn't free'd, which causes much
memory lost on linking bigger libs. The related parts are listed below.
Additional I have added a testcase to reproduce the error.
Thre reason why this memory isn't free ins't clear for me yet. Paul
Sokolovsky says in
http://sources.redhat.com/ml/binutils/2001-05/msg00547.html, that this
relates to the general way ld is building symbol tables.

On my PIII Win2K workstation with 195 MB real RAM I have tried to build
dll/exe with 500 functions and 1000 vars. Using dllexport/dllimport ld needs
about 40 MB RAM (no errors), linking without that ld uses 280 MB RAM an
crashes. (See dll.awk in the testcase for switching the two case).

Currently I'm not able to understand full how the ld is organized (the
binutils doc contains some infos but not enough for me) and if the not
free'd mem relates to the mentioned topic from Paul oth if this was an
additional problem, so if anyone can tell me something more about this, I
would be glad.
Perhaps someone is able to send a detailed instruction for changing the
desribed behavior.


-------- src/ld/emultempl/pe.em -------------------------------------

+char *data_import_dll;
+
+static void
+pe_find_data_imports ()
+{
+  struct bfd_link_hash_entry *undef, *sym;
+  for (undef = link_info.hash->undefs; undef; undef=undef->next)
+    if (undef->type == bfd_link_hash_undefined)
+    {
+      /* C++ symbols are *long* */
+      char buf[4096];
+if (pe_dll_gory_debug) printf(__FUNCTION__":%s\n",undef->root.string);
+      sprintf(buf,"__imp_%s",undef->root.string);
+
+	sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
+	if (sym && sym->type == bfd_link_hash_defined)
+	{
+          einfo (_("Warning: resolving %s by linking to %s
(auto-import)\n"),
+    	     undef->root.string, buf);
+
+          {
+            bfd *b=sym->u.def.section->owner;
+            asymbol **symbols;
+            int nsyms, symsize, i;
+
+            symsize = bfd_get_symtab_upper_bound (b);
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
symbols will never be freed, only overwritten
!!!!!
+            symbols = (asymbol **) xmalloc (symsize);
+            nsyms = bfd_canonicalize_symtab (b, symbols);
+
+            for (i = 0; i < nsyms; i++)
+	    {
+              if (memcmp(symbols[i]->name,"__head_",sizeof("__head_")-1))
+              	continue;
+if (pe_dll_gory_debug) printf("->%s\n",symbols[i]->name);

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! data_import_dll could be set with strdup() and
!! free'd before a new allocation only when the containing
!! name is changed. This would be cause one string overhead
!! (the one of the last call, that be freed on ld exit)
!! Before calling pe_walk_relocs_of_symbol() the symbols pointer could be
free'd
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
data_import_dll=(char*)(symbols[i]->name+sizeof("__head_")-1);
+              break;
+            }
+          }
+
+
+          pe_walk_relocs_of_symbol(&link_info, undef->root.string,
make_import_fixup);
+
+          /* let's differentiate it somehow from defined */
+	  undef->type = bfd_link_hash_defweak;

+          /* we replace original name with __imp_ prefixed, this
+          1) may trash memory 2) leads to duplicate symbol generation.
+          Still, IMHO it's better than having name poluted. */

+	  undef->root.string = sym->root.string;
+	  undef->u.def.value = sym->u.def.value;
+	  undef->u.def.section = sym->u.def.section;
+      }
+    }
+}
 #endif /* DLL_SUPPORT */


------------- src/ld/pe-dll.c ------------------------------------------
+void
+pe_walk_relocs_of_symbol (info, name, cb)
+     struct bfd_link_info *info;
+     CONST char *name;
+     int (*cb)(arelent*);
+{
+  bfd *b;
+  struct sec *s;
+
+  for (b = info->input_bfds; b; b = b->link_next)
+    {
+      arelent **relocs;
+      int relsize, nrelocs, i;
+
+      for (s = b->sections; s; s = s->next)
+	{
+	  asymbol **symbols;
+	  int nsyms, symsize;
+
+          current_sec=s;
+
+	  symsize = bfd_get_symtab_upper_bound (b);
+	  symbols = (asymbol **) xmalloc (symsize);
+	  nsyms = bfd_canonicalize_symtab (b, symbols);
+
+	  relsize = bfd_get_reloc_upper_bound (b, s);
+	  relocs = (arelent **) xmalloc ((size_t) relsize);
+	  nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols);
+
+	  for (i = 0; i < nrelocs; i++)
+	    {
+              struct symbol_cache_entry *sym = *relocs[i]->sym_ptr_ptr;
+              if (!strcmp(name,sym->name)) cb(relocs[i]);
+	    }
+	  free (relocs);
+	  /* Warning: the allocated symbols are remembered in BFD and reused
+	     later, so don't free them! */
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!! Where do they be used later ??? Can this not be done in another way ?
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+	  /* free (symbols); */
+	}
+    }
+
+}
+

Regards Ralf

ldmemtest.tar.gz


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]