projecttype:gdb
revision:HEAD
email:muller@ics.u-strasbg.fr

2012-10-15  Pierre Muller  <muller@ics.u-strasbg.fr>

	* 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, "<library name=\"");
   p = xml_escape_text (so_name);
   obstack_grow_str (obstack, p);
@@ -395,7 +401,19 @@ windows_xfer_shared_library (const char*
   /* The symbols in a dll are offset by 0x1000, which is the
      offset from 0 of the first byte in an image - because of the file
      header and the section alignment.  */
-  obstack_grow_str (obstack, paddress (gdbarch, load_addr + 0x1000));
+  dll = gdb_bfd_open_maybe_remote (so_name);
+  if (dll != NULL)
+    {
+      text_offset = pe_text_section_offset (dll);
+      if (text_offset != default_text_offset)
+        warning (_("DLL %s has .text section at offset %s\n"),so_name,
+		 core_addr_to_string (text_offset));
+      gdb_bfd_unref (dll);
+    }
+  else
+    text_offset = default_text_offset;
+
+  obstack_grow_str (obstack, paddress (gdbarch, load_addr + text_offset));
   obstack_grow_str (obstack, "\"/></library>");
 }
 
