diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
index 449ed5f462..d453b89cdd 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -74,6 +74,7 @@ static int attaching = 0;
 static HANDLE current_process_handle = NULL;
 static DWORD current_process_id = 0;
 static DWORD main_thread_id = 0;
+static CORE_ADDR current_exec_base;	/* Executable base address */
 static enum gdb_signal last_sig = GDB_SIGNAL_0;
 
 /* The current debug event from WaitForDebugEvent.  */
@@ -1485,6 +1486,8 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
 
       current_process_handle = current_event.u.CreateProcessInfo.hProcess;
       main_thread_id = current_event.dwThreadId;
+      current_exec_base =
+	(CORE_ADDR) current_event.u.CreateProcessInfo.lpBaseOfImage;
 
       /* Add the main thread.  */
       child_add_thread (current_event.dwProcessId,
@@ -1695,6 +1698,33 @@ win32_request_interrupt (void)
   soft_interrupt_requested = 1;
 }
 
+static int
+win32_read_auxv (CORE_ADDR offset, unsigned char *myaddr, unsigned int len)
+{
+  size_t buf[4];
+
+  if (!myaddr)
+    return -1;
+
+  if (offset > sizeof (buf))
+    return -1;
+
+  if (offset == sizeof (buf))
+    return 0;
+
+  if (offset + len > sizeof (buf))
+    len = sizeof (buf) - offset;
+
+  buf[0] = 9; /* AT_ENTRY */
+  buf[1] = current_exec_base;
+  buf[2] = 0; /* AT_NULL */
+  buf[3] = 0;
+
+  memcpy (myaddr, (char *) buf + offset, len);
+
+  return len;
+}
+
 #ifdef _WIN32_WCE
 int
 win32_error_to_fileio_error (DWORD err)
@@ -1796,7 +1826,7 @@ static struct target_ops win32_target_ops = {
   win32_write_inferior_memory,
   NULL, /* lookup_symbols */
   win32_request_interrupt,
-  NULL, /* read_auxv */
+  win32_read_auxv,
   win32_supports_z_point_type,
   win32_insert_point,
   win32_remove_point,
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 10d5c95d09..4a5d9230cc 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -235,6 +235,7 @@ static DEBUG_EVENT current_event;	/* The current debug event from
 					   WaitForDebugEvent */
 static HANDLE current_process_handle;	/* Currently executing process */
 static windows_thread_info *current_thread;	/* Info on currently selected thread */
+static CORE_ADDR current_exec_base;	/* Executable base address */
 
 /* Counts of things.  */
 static int exception_count = 0;
@@ -1593,6 +1594,8 @@ get_windows_debug_event (struct target_ops *ops,
 	break;
 
       current_process_handle = current_event.u.CreateProcessInfo.hProcess;
+      current_exec_base =
+	(CORE_ADDR) current_event.u.CreateProcessInfo.lpBaseOfImage;
       /* Add the main thread.  */
       th = windows_add_thread
         (ptid_t (current_event.dwProcessId, 0,
@@ -2969,6 +2972,35 @@ windows_xfer_shared_libraries (struct target_ops *ops,
   return len != 0 ? TARGET_XFER_OK : TARGET_XFER_EOF;
 }
 
+static enum target_xfer_status
+windows_xfer_auxv (gdb_byte *readbuf, ULONGEST offset, ULONGEST len,
+		   ULONGEST *xfered_len)
+{
+  CORE_ADDR buf[4];
+
+  if (!readbuf)
+    return TARGET_XFER_E_IO;
+
+  if (offset > sizeof (buf))
+    return TARGET_XFER_E_IO;
+
+  if (offset == sizeof (buf))
+    return TARGET_XFER_EOF;
+
+  if (offset + len > sizeof (buf))
+    len = sizeof (buf) - offset;
+
+  buf[0] = 9; /* AT_ENTRY */
+  buf[1] = current_exec_base;
+  buf[2] = 0; /* AT_NULL */
+  buf[3] = 0;
+
+  memcpy (readbuf, (char *) buf + offset, len);
+  *xfered_len = len;
+
+  return TARGET_XFER_OK;
+}
+
 enum target_xfer_status
 windows_nat_target::xfer_partial (enum target_object object,
 				  const char *annex, gdb_byte *readbuf,
@@ -2984,6 +3016,9 @@ windows_nat_target::xfer_partial (enum target_object object,
       return windows_xfer_shared_libraries (this, object, annex, readbuf,
 					    writebuf, offset, len, xfered_len);
 
+    case TARGET_OBJECT_AUXV:
+      return windows_xfer_auxv (readbuf, offset, len, xfered_len);
+
     default:
       if (beneath () == NULL)
 	{
diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
index bb69a79996..03b69464db 100644
--- a/gdb/windows-tdep.c
+++ b/gdb/windows-tdep.c
@@ -34,6 +34,10 @@
 #include "solib.h"
 #include "solib-target.h"
 #include "gdbcore.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+#include "solist.h"
+#include "auxv.h"
 
 struct cmd_list_element *info_w32_cmdlist;
 
@@ -461,6 +465,20 @@ init_w32_command_list (void)
     }
 }
 
+static void
+windows_solib_create_inferior_hook (int from_tty)
+{
+  CORE_ADDR exec_base;
+  /* 9 -> AT_ENTRY */
+  if (target_auxv_search (current_top_target (), 9, &exec_base) == 1
+      && exec_base && symfile_objfile)
+    {
+      CORE_ADDR vmaddr = pe_data (exec_bfd)->pe_opthdr.ImageBase;
+      if (vmaddr != exec_base)
+	objfile_rebase (symfile_objfile, exec_base - vmaddr);
+    }
+}
+
 /* To be called from the various GDB_OSABI_CYGWIN handlers for the
    various Windows architectures and machine types.  */
 
@@ -477,6 +495,8 @@ windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_iterate_over_objfiles_in_search_order
     (gdbarch, windows_iterate_over_objfiles_in_search_order);
 
+  solib_target_so_ops.solib_create_inferior_hook =
+    windows_solib_create_inferior_hook;
   set_solib_ops (gdbarch, &solib_target_so_ops);
 }
 
