aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDJ Delorie <dj@redhat.com>1998-11-24 04:33:33 +0000
committerDJ Delorie <dj@redhat.com>1998-11-24 04:33:33 +0000
commitc59356d3b4bdebd4618508b6b4e6afcb86982855 (patch)
tree0815471d31651258e4168886e02a0451bd7cdb37
parent11dddceff52cfa677af53ea32edc9c24fa467b80 (diff)
downloadgdb-c59356d3b4bdebd4618508b6b4e6afcb86982855.zip
gdb-c59356d3b4bdebd4618508b6b4e6afcb86982855.tar.gz
gdb-c59356d3b4bdebd4618508b6b4e6afcb86982855.tar.bz2
* 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
-rw-r--r--ld/ChangeLog12
-rw-r--r--ld/pe-dll.c184
2 files changed, 185 insertions, 11 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 0f0d1e7..44e1964 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,5 +1,17 @@
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
pe_dll_add_excludes
diff --git a/ld/pe-dll.c b/ld/pe-dll.c
index aa5d8b8..c1d0d08 100644
--- a/ld/pe-dll.c
+++ b/ld/pe-dll.c
@@ -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,25 +1424,31 @@ 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);
}
@@ -1437,6 +1456,149 @@ pe_process_import_defs (output_bfd, link_info)
/************************************************************************
+ 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
is called after the bfds are read, so we can guess at how much space
we need. The second is called after everything is placed, so we