From c59356d3b4bdebd4618508b6b4e6afcb86982855 Mon Sep 17 00:00:00 2001 From: DJ Delorie Date: Tue, 24 Nov 1998 04:33:33 +0000 Subject: [PATCH] * 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 --- ld/ChangeLog | 12 ++++ ld/pe-dll.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 185 insertions(+), 11 deletions(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index 0f0d1e75d67..44e19648918 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,15 @@ +1998-11-23 DJ Delorie + + * 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 * emultempl/pe.em (gld_i386pe_parse_args): Conditionalize call to diff --git a/ld/pe-dll.c b/ld/pe-dll.c index aa5d8b89cca..c1d0d08590d 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,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 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