* pe-dll.c (make_head): name object files sequentially to ensure
authorDJ Delorie <dj@redhat.com>
Tue, 24 Nov 1998 04:33:33 +0000 (04:33 +0000)
committerDJ Delorie <dj@redhat.com>
Tue, 24 Nov 1998 04:33:33 +0000 (04:33 +0000)
they link in the right order.
(make_tail): same here
(pe_process_import_defs): use sequential names for bfds to ensure
proper link order.
(pe_implied_import_dll): new function; handles linking directly
against DLLs by simulating IMPORTS directives.  * emultempl/pe.em
(gld_i386pe_before_parse): hack bfd to not recognize .dll files
via bfd_pe_dll_not_recognized_hack

ld/ChangeLog
ld/pe-dll.c

index 0f0d1e75d6786c6b324f578fcbba7de891d01285..44e196489182fa7c3bf4507f3cfb098bcd7fcaa8 100644 (file)
@@ -1,3 +1,15 @@
+1998-11-23  DJ Delorie  <dj@cygnus.com>
+
+       * pe-dll.c (make_head): name object files sequentially to ensure
+       they link in the right order.
+       (make_tail): same here
+       (pe_process_import_defs): use sequential names for bfds to ensure
+       proper link order.
+       (pe_implied_import_dll): new function; handles linking directly
+       against DLLs by simulating IMPORTS directives.  * emultempl/pe.em
+       (gld_i386pe_before_parse): hack bfd to not recognize .dll files
+       via bfd_pe_dll_not_recognized_hack
+
 1998-11-23  DJ Delorie  <dj@cygnus.com>
 
        * emultempl/pe.em (gld_i386pe_parse_args): Conditionalize call to
index aa5d8b89cca433326ab8f33668d6755045c63daf..c1d0d08590de4469e7c6fe018cb085e4fe8881af 100644 (file)
@@ -1023,14 +1023,20 @@ save_relocs (asection *sec)
  * hname:
  */
 
-bfd *
+static bfd *
 make_head (parent)
      bfd *parent;
 {
   asection *id2, *id5, *id4;
   unsigned char *d2, *d5, *d4;
+  char *oname;
+  bfd *abfd;
 
-  bfd *abfd = bfd_create ("dh.o", parent);
+  oname = (char *) xmalloc (20);
+  sprintf (oname, "d%06d.o", tmp_seq);
+  tmp_seq++;
+
+  abfd = bfd_create (oname, parent);
   bfd_find_target ("pe-i386", abfd);
   bfd_make_writable (abfd);
 
@@ -1086,15 +1092,21 @@ make_head (parent)
  *     .asciz          "my.dll"
  */
 
-bfd *
+static bfd *
 make_tail (parent)
      bfd *parent;
 {
   asection *id4, *id5, *id7;
   unsigned char *d4, *d5, *d7;
   int len;
+  char *oname;
+  bfd *abfd;
+
+  oname = (char *) xmalloc (20);
+  sprintf (oname, "d%06d.o", tmp_seq);
+  tmp_seq++;
 
-  bfd *abfd = bfd_create ("dt.o", parent);
+  abfd = bfd_create (oname, parent);
   bfd_find_target ("pe-i386", abfd);
   bfd_make_writable (abfd);
 
@@ -1159,12 +1171,12 @@ make_tail (parent)
  *     .asciz          "function" xlate? (add underscore, kill at)
  */
 
-unsigned char jmp_ix86_bytes[] = {
+static unsigned char jmp_ix86_bytes[] = {
   0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
 };
 
 
-bfd *
+static bfd *
 make_one (exp, parent)
      def_file_export *exp;
      bfd *parent;
@@ -1176,8 +1188,9 @@ make_one (exp, parent)
   bfd *abfd;
 
   oname = (char *) xmalloc (20);
-  sprintf (oname, "ds%d.o", tmp_seq);
+  sprintf (oname, "d%06d.o", tmp_seq);
   tmp_seq++;
+
   abfd = bfd_create (oname, parent);
   bfd_find_target ("pe-i386", abfd);
   bfd_make_writable (abfd);
@@ -1411,30 +1424,179 @@ pe_process_import_defs (output_bfd, link_info)
            free (name);
            if (blhe && blhe->type == bfd_link_hash_undefined)
              {
+               bfd *one;
                /* we do */
                if (!do_this_dll)
                  {
-                   add_bfd_to_link (make_head (output_bfd), "imp-head", link_info);
+                   bfd *ar_head = make_head (output_bfd);
+                   add_bfd_to_link (ar_head, ar_head->filename, link_info);
                    do_this_dll = 1;
                  }
                exp.internal_name = pe_def_file->imports[i].internal_name;
                exp.name = pe_def_file->imports[i].name;
                exp.ordinal = pe_def_file->imports[i].ordinal;
-               exp.hint = 0;
+               exp.hint = exp.ordinal;
                exp.flag_private = 0;
                exp.flag_constant = 0;
                exp.flag_data = 0;
                exp.flag_noname = exp.name ? 0 : 1;
-               add_bfd_to_link (make_one (&exp, output_bfd), "imp-sym", link_info);
+               one = make_one (&exp, output_bfd);
+               add_bfd_to_link (one, one->filename, link_info);
              }
          }
       if (do_this_dll)
-       add_bfd_to_link (make_tail (output_bfd), "imp-tail", link_info);
+       {
+         bfd *ar_tail = make_tail (output_bfd);
+         add_bfd_to_link (ar_tail, ar_tail->filename, link_info);
+       }
 
       free (dll_symname);
     }
 }
 
+/************************************************************************
+
+ We were handed a *.DLL file.  Parse it and turn it into a set of
+ IMPORTS directives in the def file.  Return true if the file was
+ handled, false if not.
+
+ ************************************************************************/
+
+static unsigned int
+pe_get16 (abfd, where)
+     bfd *abfd;
+     int where;
+{
+  unsigned char b[2];
+  bfd_seek (abfd, where, SEEK_SET);
+  bfd_read (b, 1, 2, abfd);
+  return b[0] + (b[1]<<8);
+}
+
+static unsigned int
+pe_get32 (abfd, where)
+     bfd *abfd;
+     int where;
+{
+  unsigned char b[4];
+  bfd_seek (abfd, where, SEEK_SET);
+  bfd_read (b, 1, 4, abfd);
+  return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+}
+
+static unsigned int
+pe_as16 (ptr)
+     void *ptr;
+{
+  unsigned char *b = ptr;
+  return b[0] + (b[1]<<8);
+}
+
+static unsigned int
+pe_as32 (ptr)
+     void *ptr;
+{
+  unsigned char *b = ptr;
+  return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+}
+
+extern int bfd_pe_dll_not_recognized_hack;
+
+boolean
+pe_implied_import_dll (filename)
+     char *filename;
+{
+  bfd *dll;
+  unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
+  unsigned long export_rva, export_size, nsections, secptr, expptr;
+  unsigned char *expdata, *erva;
+  unsigned long name_rvas, ordinals, nexp, ordbase;
+  char *dll_name;
+
+  /* No, I can't use bfd here.  kernel32.dll puts its export table in
+     the middle of the .rdata section. */
+
+  bfd_pe_dll_not_recognized_hack = 0;
+  dll = bfd_openr (filename, "pei-i386");
+  if (!dll)
+    {
+      einfo ("%Xopen %s: %s\n", filename, bfd_errmsg (bfd_get_error ()));
+      bfd_pe_dll_not_recognized_hack = 1;
+      return false;
+    }
+  /* PEI dlls seem to be bfd_objects */
+  if (!bfd_check_format (dll, bfd_object))
+    {
+      einfo ("%X%s: this doesn't appear to be a DLL\n", filename);
+      bfd_pe_dll_not_recognized_hack = 1;
+      return false;
+    }
+  bfd_pe_dll_not_recognized_hack = 1;
+  printf("dj: importing dll %s at %x\n", filename, dll->where);
+
+  dll_name = filename;
+  for (i=0; filename[i]; i++)
+    if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':')
+      dll_name = filename + i + 1;
+
+  pe_header_offset = pe_get32 (dll, 0x3c);
+  opthdr_ofs = pe_header_offset + 4 + 20;
+  num_entries = pe_get32 (dll, opthdr_ofs + 92);
+  if (num_entries < 1) /* no exports */
+    return false;
+  export_rva = pe_get32 (dll, opthdr_ofs + 96);
+  export_size = pe_get32 (dll, opthdr_ofs + 100);
+  nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
+  secptr = (pe_header_offset + 4 + 20 +
+           pe_get16 (dll, pe_header_offset + 4 + 16));
+  expptr = 0;
+  printf("export: rva=%08x size=%08x secptr=%08x\n",
+        export_rva, export_size, secptr);
+  for (i=0; i<nsections; i++)
+    {
+      char sname[8];
+      unsigned long secptr1 = secptr + 40 * i;
+      unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
+      unsigned long vsize = pe_get32 (dll, secptr1 + 16);
+      unsigned long fptr = pe_get32 (dll, secptr1 + 20);
+      bfd_seek(dll, secptr1, SEEK_SET);
+      bfd_read(sname, 1, 8, dll);
+      printf("sec: %.8s addr=%08x size=%08x fptr=%08x\n",
+            sname, vaddr, vsize, fptr);
+      if (vaddr <= export_rva && vaddr+vsize > export_rva)
+       {
+         expptr = fptr + (export_rva - vaddr);
+         if (export_rva + export_size > vaddr + vsize)
+           export_size = vsize - (export_rva - vaddr);
+         break;
+       }
+    }
+  printf("expptr=%08x size=%08x\n", expptr, export_size);
+
+  expdata = (unsigned char *) xmalloc (export_size);
+  bfd_seek (dll, expptr, SEEK_SET);
+  bfd_read (expdata, 1, export_size, dll);
+  erva = expdata - export_rva;
+
+  if (pe_def_file == 0)
+    pe_def_file = def_file_empty();
+
+  nexp = pe_as32 (expdata+24);
+  name_rvas = pe_as32 (expdata+32);
+  ordinals = pe_as32 (expdata+36);
+  ordbase = pe_as32 (expdata+16);
+  printf("%d exports ob=%d\n", nexp, ordbase);
+  for (i=0; i<nexp; i++)
+    {
+      unsigned long name_rva = pe_as32 (erva+name_rvas+i*4);
+      def_file_import *imp;
+      imp = def_file_add_import (pe_def_file, erva+name_rva, dll_name,
+                                i, 0);
+    }
+
+  return true;
+}
+
 /************************************************************************
 
  These are the main functions, called from the emulation.  The first