projecttype:gdb revision:HEAD email:muller@ics.u-strasbg.fr 2012-10-15 Pierre Muller * coff-pe-read.h (pe_text_section_offset): Declare new function. * coff-pe-read.c (pe_as16): New function. (read_pe_exported_syms): Use ordinal of function to retrieve correct RVA address of function. (pe_text_section_offset): New function. * windows-tdep.c (windows_xfer_shared_library): Use pe_text_section_offset function instead of possibly wrong 0x1000 constant for .text sextion offset. Index: src/gdb/coff-pe-read.h =================================================================== RCS file: /cvs/src/src/gdb/coff-pe-read.h,v retrieving revision 1.11 diff -u -p -r1.11 coff-pe-read.h --- src/gdb/coff-pe-read.h 4 Jan 2012 08:17:00 -0000 1.11 +++ src/gdb/coff-pe-read.h 15 Oct 2012 12:36:49 -0000 @@ -21,11 +21,15 @@ #if !defined (COFF_PE_READ_H) #define COFF_PE_READ_H +#include "defs.h" struct objfile; +struct bfd; /* Read the export table and convert it to minimal symbol table entries */ extern void read_pe_exported_syms (struct objfile *objfile); +extern CORE_ADDR pe_text_section_offset (struct bfd *abfd); + #endif /* !defined (COFF_PE_READ_H) */ Index: src/gdb/coff-pe-read.c =================================================================== RCS file: /cvs/src/src/gdb/coff-pe-read.c,v retrieving revision 1.17 diff -u -p -r1.17 coff-pe-read.c --- src/gdb/coff-pe-read.c 4 Jan 2012 08:17:00 -0000 1.17 +++ src/gdb/coff-pe-read.c 15 Oct 2012 12:36:49 -0000 @@ -170,6 +170,14 @@ pe_get32 (bfd *abfd, int where) } static unsigned int +pe_as16 (void *ptr) +{ + unsigned char *b = ptr; + + return b[0] + (b[1] << 8); +} + +static unsigned int pe_as32 (void *ptr) { unsigned char *b = ptr; @@ -336,26 +344,119 @@ read_pe_exported_syms (struct objfile *o { /* Pointer to the names vector. */ unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4); + /* Retrieve ordinal value */ + + unsigned long ordinal = pe_as16 (erva + ordinals + i * 2); + /* Pointer to the function address vector. */ - unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4); + /* This is relatived to ordinal value. */ + unsigned long func_rva = pe_as32 (erva + exp_funcbase + + ordinal * 4); /* Find this symbol's section in our own array. */ int sectix = 0; + int section_found = 0; for (sectix = 0; sectix < PE_SECTION_TABLE_SIZE; ++sectix) { if ((func_rva >= section_data[sectix].rva_start) && (func_rva < section_data[sectix].rva_end)) { + section_found = 1; add_pe_exported_sym (erva + name_rva, func_rva, section_data + sectix, dll_name, objfile); break; } } + if (!section_found) + { + char * forward_name = (char *) (erva + func_rva); + char * funcname = (char *) (erva + name_rva); + if ((func_rva >= export_rva) + && (func_rva < export_rva + export_size)) + printf ("%s is a forward to %s\n", funcname, forward_name); + } } /* Discard expdata. */ do_cleanups (back_to); } + +CORE_ADDR +pe_text_section_offset (struct bfd *abfd) + +{ + bfd *dll = abfd; + unsigned long pe_header_offset, opthdr_ofs, num_entries, i; + unsigned long export_rva, export_size, nsections, secptr, expptr; + unsigned long exp_funcbase; + unsigned char *expdata, *erva; + unsigned long name_rvas, ordinals, nexp, ordbase; + char *dll_name; + int is_pe64 = 0; + int is_pe32 = 0; + + char const *target = bfd_get_target (dll); + + is_pe64 = (strcmp (target, "pe-x86-64") == 0 + || strcmp (target, "pei-x86-64") == 0); + is_pe32 = (strcmp (target, "pe-i386") == 0 + || strcmp (target, "pei-i386") == 0 + || strcmp (target, "pe-arm-wince-little") == 0 + || strcmp (target, "pei-arm-wince-little") == 0); + + if (!is_pe32 && !is_pe64) + { + /* This is not a recognized PE format file. Abort now, because + the code is untested on anything else. *FIXME* test on + further architectures and loosen or remove this test. */ + return 0; + } + + /* Get pe_header, optional header and numbers of export entries. */ + pe_header_offset = pe_get32 (dll, 0x3c); + opthdr_ofs = pe_header_offset + 4 + 20; + if (is_pe64) + num_entries = pe_get32 (dll, opthdr_ofs + 108); + else + num_entries = pe_get32 (dll, opthdr_ofs + 92); + + if (num_entries < 1) /* No exports. */ + { + return 0; + } + + if (is_pe64) + { + export_rva = pe_get32 (dll, opthdr_ofs + 112); + export_size = pe_get32 (dll, opthdr_ofs + 116); + } + else + { + 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; + + /* Get the rva and size of the export section. */ + 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, (file_ptr) secptr1, SEEK_SET); + bfd_bread (sname, (bfd_size_type) 8, dll); + if (strcmp (sname, ".text") == 0) + return vaddr; + } + + return 0; +} Index: src/gdb/windows-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/windows-tdep.c,v retrieving revision 1.16 diff -u -p -r1.16 windows-tdep.c --- src/gdb/windows-tdep.c 5 Jun 2012 13:50:57 -0000 1.16 +++ src/gdb/windows-tdep.c 15 Oct 2012 12:36:49 -0000 @@ -27,6 +27,9 @@ #include "gdbcmd.h" #include "gdbthread.h" #include "objfiles.h" +#include "symfile.h" +#include "coff-pe-read.h" +#include "gdb_bfd.h" struct cmd_list_element *info_w32_cmdlist; @@ -387,6 +390,9 @@ windows_xfer_shared_library (const char* struct gdbarch *gdbarch, struct obstack *obstack) { char *p; + struct bfd * dll; + CORE_ADDR text_offset; + CORE_ADDR default_text_offset = 0x1000; obstack_grow_str (obstack, ""); }