2007-07-17 Pedro Alves <pedro_alves@portugalmail.pt>

Daniel Jacobowitz  <dan@codesourcery.com>

	* config/i386/cygwin.mt (TDEPFILES): Add solib-target.o.
	* coff-pe-read.c (read_pe_exported_syms): Delete verbose
	printf.
	* NEWS: Mention gdbserver DLL support.

	* gdb.base/unload.c (dlopen, dlsym, dlclose, dlerror): Define
	for __WIN32__.
	(SHLIB_NAME): Delete definition.  Always pass dlerror to fprintf.
	* gdb.base/unload.exp: Use shared library test routines.

	* inferiors.c (all_dlls, dlls_changed, get_dll): New.
	(add_thread): Minor cleanups.
	(clear_inferiors): Move lower in the file.  Clear the DLL
	list.
	(free_one_dll, match_dll, loaded_dll, unloaded_dll, clear_list): New.
	* remote-utils.c (prepare_resume_reply): Check dlls_changed.
	(xml_escape_text): New.
	* server.c (handle_query): Handle qXfer:libraries:read.  Report it
	for qSupported.
	(handle_v_cont): Report errors.
	(gdbserver_version): Update.
	(main): Correct size of own_buf.  Do not report initial DLL events.
	* server.h (struct dll_info, all_dlls, dlls_changed, loaded_dll)
	(unloaded_dll, xml_escape_text): New.
	* win32-low.c (enum target_waitkind): Update comments.
	(win32_add_one_solib, get_image_name, winapi_EnumProcessModules)
	(winapi_GetModuleInformation, winapi_GetModuleFileNameExA)
	(win32_EnumProcessModules, win32_GetModuleInformation)
	(win32_GetModuleFileNameExA, load_psapi, psapi_get_dll_name)
	(winapi_CreateToolhelp32Snapshot, winapi_Module32First)
	(winapi_Module32Next, win32_CreateToolhelp32Snapshot)
	(win32_Module32First, win32_Module32Next, load_toolhelp)
	(toolhelp_get_dll_name, handle_load_dll, handle_unload_dll): New.
	(get_child_debug_event): Handle DLL events.
	(win32_wait): Likewise.
This commit is contained in:
Daniel Jacobowitz 2007-07-17 12:51:41 +00:00
parent a8c50c1f55
commit 255e7678a9
13 changed files with 636 additions and 43 deletions

View file

@ -1,3 +1,11 @@
2007-07-17 Pedro Alves <pedro_alves@portugalmail.pt>
Daniel Jacobowitz <dan@codesourcery.com>
* config/i386/cygwin.mt (TDEPFILES): Add solib-target.o.
* coff-pe-read.c (read_pe_exported_syms): Delete verbose
printf.
* NEWS: Mention gdbserver DLL support.
2007-07-17 Daniel Jacobowitz <dan@codesourcery.com>
* dwarf2read.c (dwarf_decode_lines): Detect address size mismatches.

View file

@ -54,6 +54,9 @@ packet, this response allows GDB to debug shared libraries on targets
where the operating system manages the list of loaded libraries (e.g.
Windows and SymbianOS).
* The GDB remote stub, gdbserver, now supports dynamic link libraries
(DLLs) on Windows and Windows CE targets.
* New commands
set remoteflow

View file

@ -309,9 +309,6 @@ read_pe_exported_syms (struct objfile *objfile)
+= ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
}
printf_filtered (_("Minimal symbols from %s..."), dll_name);
wrap_here ("");
/* Truncate name at first dot. Should maybe also convert to all
lower case for convenience on Windows. */
read_pe_truncate_name (dll_name);

View file

@ -1,2 +1,3 @@
# Target: Intel 386 run win32
TDEPFILES= i386-tdep.o i386-cygwin-tdep.o i387-tdep.o
TDEPFILES= i386-tdep.o i386-cygwin-tdep.o i387-tdep.o \
solib-target.o

View file

@ -1,3 +1,32 @@
2007-07-17 Pedro Alves <pedro_alves@portugalmail.pt>
Daniel Jacobowitz <dan@codesourcery.com>
* inferiors.c (all_dlls, dlls_changed, get_dll): New.
(add_thread): Minor cleanups.
(clear_inferiors): Move lower in the file. Clear the DLL
list.
(free_one_dll, match_dll, loaded_dll, unloaded_dll, clear_list): New.
* remote-utils.c (prepare_resume_reply): Check dlls_changed.
(xml_escape_text): New.
* server.c (handle_query): Handle qXfer:libraries:read. Report it
for qSupported.
(handle_v_cont): Report errors.
(gdbserver_version): Update.
(main): Correct size of own_buf. Do not report initial DLL events.
* server.h (struct dll_info, all_dlls, dlls_changed, loaded_dll)
(unloaded_dll, xml_escape_text): New.
* win32-low.c (enum target_waitkind): Update comments.
(win32_add_one_solib, get_image_name, winapi_EnumProcessModules)
(winapi_GetModuleInformation, winapi_GetModuleFileNameExA)
(win32_EnumProcessModules, win32_GetModuleInformation)
(win32_GetModuleFileNameExA, load_psapi, psapi_get_dll_name)
(winapi_CreateToolhelp32Snapshot, winapi_Module32First)
(winapi_Module32Next, win32_CreateToolhelp32Snapshot)
(win32_Module32First, win32_Module32Next, load_toolhelp)
(toolhelp_get_dll_name, handle_load_dll, handle_unload_dll): New.
(get_child_debug_event): Handle DLL events.
(win32_wait): Likewise.
2007-07-12 Daniel Jacobowitz <dan@codesourcery.com>
* configure.srv: Set srv_linux_regsets for sh*-*-linux*.

View file

@ -33,10 +33,13 @@ struct thread_info
};
struct inferior_list all_threads;
struct inferior_list all_dlls;
int dlls_changed;
struct thread_info *current_inferior;
#define get_thread(inf) ((struct thread_info *)(inf))
#define get_dll(inf) ((struct dll_info *)(inf))
void
add_inferior_to_list (struct inferior_list *list,
@ -109,15 +112,14 @@ remove_inferior (struct inferior_list *list,
void
add_thread (unsigned long thread_id, void *target_data, unsigned int gdb_id)
{
struct thread_info *new_thread
= (struct thread_info *) malloc (sizeof (*new_thread));
struct thread_info *new_thread = malloc (sizeof (*new_thread));
memset (new_thread, 0, sizeof (*new_thread));
new_thread->entry.id = thread_id;
add_inferior_to_list (&all_threads, & new_thread->entry);
if (current_inferior == NULL)
current_inferior = new_thread;
@ -187,14 +189,6 @@ remove_thread (struct thread_info *thread)
free_one_thread (&thread->entry);
}
void
clear_inferiors (void)
{
for_each_inferior (&all_threads, free_one_thread);
all_threads.head = all_threads.tail = NULL;
}
struct inferior_list_entry *
find_inferior (struct inferior_list *list,
int (*func) (struct inferior_list_entry *, void *), void *arg)
@ -249,3 +243,80 @@ set_inferior_regcache_data (struct thread_info *inferior, void *data)
{
inferior->regcache_data = data;
}
static void
free_one_dll (struct inferior_list_entry *inf)
{
struct dll_info *dll = get_dll (inf);
if (dll->name != NULL)
free (dll->name);
free (dll);
}
/* Find a DLL with the same name and/or base address. A NULL name in
the key is ignored; so is an all-ones base address. */
static int
match_dll (struct inferior_list_entry *inf, void *arg)
{
struct dll_info *iter = (void *) inf;
struct dll_info *key = arg;
if (key->base_addr != ~(CORE_ADDR) 0
&& iter->base_addr == key->base_addr)
return 1;
else if (key->name != NULL
&& iter->name != NULL
&& strcmp (key->name, iter->name) == 0)
return 1;
return 0;
}
/* Record a newly loaded DLL at BASE_ADDR. */
void
loaded_dll (const char *name, CORE_ADDR base_addr)
{
struct dll_info *new_dll = malloc (sizeof (*new_dll));
memset (new_dll, 0, sizeof (*new_dll));
new_dll->entry.id = -1;
new_dll->name = strdup (name);
new_dll->base_addr = base_addr;
add_inferior_to_list (&all_dlls, &new_dll->entry);
dlls_changed = 1;
}
/* Record that the DLL with NAME and BASE_ADDR has been unloaded. */
void
unloaded_dll (const char *name, CORE_ADDR base_addr)
{
struct dll_info *dll;
struct dll_info key_dll;
/* Be careful not to put the key DLL in any list. */
key_dll.name = (char *) name;
key_dll.base_addr = base_addr;
dll = (void *) find_inferior (&all_dlls, match_dll, &key_dll);
remove_inferior (&all_dlls, &dll->entry);
free_one_dll (&dll->entry);
dlls_changed = 1;
}
#define clear_list(LIST) \
do { (LIST)->head = (LIST)->tail = NULL; } while (0)
void
clear_inferiors (void)
{
for_each_inferior (&all_threads, free_one_thread);
for_each_inferior (&all_dlls, free_one_dll);
clear_list (&all_threads);
clear_list (&all_dlls);
}

View file

@ -965,6 +965,13 @@ prepare_resume_reply (char *buf, char status, unsigned char sig)
old_thread_from_wait = thread_from_wait;
}
}
if (dlls_changed)
{
strcpy (buf, "library:;");
buf += strlen (buf);
dlls_changed = 0;
}
}
/* For W and X, we're done. */
*buf++ = 0;
@ -1172,3 +1179,65 @@ monitor_output (const char *msg)
putpkt (buf);
free (buf);
}
/* Return a malloc allocated string with special characters from TEXT
replaced by entity references. */
char *
xml_escape_text (const char *text)
{
char *result;
int i, special;
/* Compute the length of the result. */
for (i = 0, special = 0; text[i] != '\0'; i++)
switch (text[i])
{
case '\'':
case '\"':
special += 5;
break;
case '&':
special += 4;
break;
case '<':
case '>':
special += 3;
break;
default:
break;
}
/* Expand the result. */
result = malloc (i + special + 1);
for (i = 0, special = 0; text[i] != '\0'; i++)
switch (text[i])
{
case '\'':
strcpy (result + i + special, "&apos;");
special += 5;
break;
case '\"':
strcpy (result + i + special, "&quot;");
special += 5;
break;
case '&':
strcpy (result + i + special, "&amp;");
special += 4;
break;
case '<':
strcpy (result + i + special, "&lt;");
special += 3;
break;
case '>':
strcpy (result + i + special, "&gt;");
special += 3;
break;
default:
result[i + special] = text[i];
break;
}
result[i + special] = '\0';
return result;
}

View file

@ -458,12 +458,80 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
return;
}
if (strncmp ("qXfer:libraries:read:", own_buf, 21) == 0)
{
CORE_ADDR ofs;
unsigned int len, total_len;
char *document, *p;
struct inferior_list_entry *dll_ptr;
char *annex;
/* Reject any annex; grab the offset and length. */
if (decode_xfer_read (own_buf + 21, &annex, &ofs, &len) < 0
|| annex[0] != '\0')
{
strcpy (own_buf, "E00");
return;
}
/* Over-estimate the necessary memory. Assume that every character
in the library name must be escaped. */
total_len = 64;
for (dll_ptr = all_dlls.head; dll_ptr != NULL; dll_ptr = dll_ptr->next)
total_len += 128 + 6 * strlen (((struct dll_info *) dll_ptr)->name);
document = malloc (total_len);
strcpy (document, "<library-list>\n");
p = document + strlen (document);
for (dll_ptr = all_dlls.head; dll_ptr != NULL; dll_ptr = dll_ptr->next)
{
struct dll_info *dll = (struct dll_info *) dll_ptr;
char *name;
strcpy (p, " <library name=\"");
p = p + strlen (p);
name = xml_escape_text (dll->name);
strcpy (p, name);
free (name);
p = p + strlen (p);
strcpy (p, "\"><segment address=\"");
p = p + strlen (p);
sprintf (p, "0x%lx", (long) dll->base_addr);
p = p + strlen (p);
strcpy (p, "\"/></library>\n");
p = p + strlen (p);
}
strcpy (p, "</library-list>\n");
total_len = strlen (document);
if (len > PBUFSIZ - 2)
len = PBUFSIZ - 2;
if (ofs > total_len)
write_enn (own_buf);
else if (len < total_len - ofs)
*new_packet_len_p = write_qxfer_response (own_buf, document + ofs,
len, 1);
else
*new_packet_len_p = write_qxfer_response (own_buf, document + ofs,
total_len - ofs, 0);
free (document);
return;
}
/* Protocol features query. */
if (strncmp ("qSupported", own_buf, 10) == 0
&& (own_buf[10] == ':' || own_buf[10] == '\0'))
{
sprintf (own_buf, "PacketSize=%x;QPassSignals+", PBUFSIZ - 1);
/* We do not have any hook to indicate whether the target backend
supports qXfer:libraries:read, so always report it. */
strcat (own_buf, ";qXfer:libraries:read+");
if (the_target->read_auxv != NULL)
strcat (own_buf, ";qXfer:auxv:read+");
@ -696,8 +764,7 @@ handle_v_cont (char *own_buf, char *status, int *signal)
return;
err:
/* No other way to report an error... */
strcpy (own_buf, "");
write_enn (own_buf);
free (resume_info);
return;
}
@ -753,7 +820,7 @@ static void
gdbserver_version (void)
{
printf ("GNU gdbserver %s\n"
"Copyright (C) 2006 Free Software Foundation, Inc.\n"
"Copyright (C) 2007 Free Software Foundation, Inc.\n"
"gdbserver is free software, covered by the GNU General Public License.\n"
"This gdbserver was configured as \"%s\"\n",
version, host_name);
@ -824,7 +891,7 @@ main (int argc, char *argv[])
initialize_low ();
own_buf = malloc (PBUFSIZ);
own_buf = malloc (PBUFSIZ + 1);
mem_buf = malloc (PBUFSIZ);
if (pid == 0)
@ -833,6 +900,10 @@ main (int argc, char *argv[])
signal = start_inferior (&argv[2], &status);
/* We are now stopped at the first instruction of the target process */
/* Don't report shared library events on the initial connection,
even if some libraries are preloaded. */
dlls_changed = 0;
}
else
{

View file

@ -91,6 +91,13 @@ struct inferior_list_entry
/* Opaque type for user-visible threads. */
struct thread_info;
struct dll_info
{
struct inferior_list_entry entry;
char *name;
CORE_ADDR base_addr;
};
#include "regcache.h"
#include "gdb/signals.h"
@ -104,6 +111,9 @@ void initialize_low ();
/* From inferiors.c. */
extern struct inferior_list all_threads;
extern struct inferior_list all_dlls;
extern int dlls_changed;
void add_inferior_to_list (struct inferior_list *list,
struct inferior_list_entry *new_inferior);
void for_each_inferior (struct inferior_list *list,
@ -132,6 +142,9 @@ void set_inferior_regcache_data (struct thread_info *, void *);
void change_inferior_id (struct inferior_list *list,
unsigned long new_id);
void loaded_dll (const char *name, CORE_ADDR base_addr);
void unloaded_dll (const char *name, CORE_ADDR base_addr);
/* Public variables in server.c */
extern unsigned long cont_thread;
@ -190,6 +203,8 @@ int look_up_one_symbol (const char *name, CORE_ADDR *addrp);
void monitor_output (const char *msg);
char *xml_escape_text (const char *text);
/* Functions from ``signals.c''. */
enum target_signal target_signal_from_host (int hostsig);
int target_signal_to_host_p (enum target_signal oursig);

View file

@ -29,6 +29,7 @@
#include <windows.h>
#include <winnt.h>
#include <imagehlp.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <sys/param.h>
#include <malloc.h>
@ -202,8 +203,8 @@ enum target_waitkind
value.sig. */
TARGET_WAITKIND_STOPPED,
/* The program is letting us know that it dynamically loaded something
(e.g. it called load(2) on AIX). */
/* The program is letting us know that it dynamically loaded
or unloaded something. */
TARGET_WAITKIND_LOADED,
/* The program has exec'ed a new executable file. The new file's
@ -772,6 +773,316 @@ win32_resume (struct thread_resume *resume_info)
child_continue (continue_status, tid);
}
static void
win32_add_one_solib (const char *name, CORE_ADDR load_addr)
{
char buf[MAX_PATH + 1];
char buf2[MAX_PATH + 1];
#ifdef _WIN32_WCE
WIN32_FIND_DATA w32_fd;
WCHAR wname[MAX_PATH + 1];
mbstowcs (wname, name, MAX_PATH);
HANDLE h = FindFirstFile (wname, &w32_fd);
#else
WIN32_FIND_DATAA w32_fd;
HANDLE h = FindFirstFileA (name, &w32_fd);
#endif
if (h == INVALID_HANDLE_VALUE)
strcpy (buf, name);
else
{
FindClose (h);
strcpy (buf, name);
#ifndef _WIN32_WCE
{
char cwd[MAX_PATH + 1];
char *p;
if (GetCurrentDirectoryA (MAX_PATH + 1, cwd))
{
p = strrchr (buf, '\\');
if (p)
p[1] = '\0';
SetCurrentDirectoryA (buf);
GetFullPathNameA (w32_fd.cFileName, MAX_PATH, buf, &p);
SetCurrentDirectoryA (cwd);
}
}
#endif
}
#ifdef __CYGWIN__
cygwin_conv_to_posix_path (buf, buf2);
#else
strcpy (buf2, buf);
#endif
loaded_dll (buf2, load_addr);
}
static char *
get_image_name (HANDLE h, void *address, int unicode)
{
static char buf[(2 * MAX_PATH) + 1];
DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
char *address_ptr;
int len = 0;
char b[2];
DWORD done;
/* Attempt to read the name of the dll that was detected.
This is documented to work only when actively debugging
a program. It will not work for attached processes. */
if (address == NULL)
return NULL;
#ifdef _WIN32_WCE
/* Windows CE reports the address of the image name,
instead of an address of a pointer into the image name. */
address_ptr = address;
#else
/* See if we could read the address of a string, and that the
address isn't null. */
if (!ReadProcessMemory (h, address, &address_ptr,
sizeof (address_ptr), &done)
|| done != sizeof (address_ptr)
|| !address_ptr)
return NULL;
#endif
/* Find the length of the string */
while (ReadProcessMemory (h, address_ptr + len++ * size, &b, size, &done)
&& (b[0] != 0 || b[size - 1] != 0) && done == size)
continue;
if (!unicode)
ReadProcessMemory (h, address_ptr, buf, len, &done);
else
{
WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR));
ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
&done);
WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, len, 0, 0);
}
return buf;
}
typedef BOOL (WINAPI *winapi_EnumProcessModules) (HANDLE, HMODULE *,
DWORD, LPDWORD);
typedef BOOL (WINAPI *winapi_GetModuleInformation) (HANDLE, HMODULE,
LPMODULEINFO, DWORD);
typedef DWORD (WINAPI *winapi_GetModuleFileNameExA) (HANDLE, HMODULE,
LPSTR, DWORD);
static winapi_EnumProcessModules win32_EnumProcessModules;
static winapi_GetModuleInformation win32_GetModuleInformation;
static winapi_GetModuleFileNameExA win32_GetModuleFileNameExA;
static BOOL
load_psapi (void)
{
static int psapi_loaded = 0;
static HMODULE dll = NULL;
if (!psapi_loaded)
{
psapi_loaded = 1;
dll = LoadLibrary (TEXT("psapi.dll"));
if (!dll)
return FALSE;
win32_EnumProcessModules =
GETPROCADDRESS (dll, EnumProcessModules);
win32_GetModuleInformation =
GETPROCADDRESS (dll, GetModuleInformation);
win32_GetModuleFileNameExA =
GETPROCADDRESS (dll, GetModuleFileNameExA);
}
return (win32_EnumProcessModules != NULL
&& win32_GetModuleInformation != NULL
&& win32_GetModuleFileNameExA != NULL);
}
static int
psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
{
DWORD len;
MODULEINFO mi;
size_t i;
HMODULE dh_buf[1];
HMODULE *DllHandle = dh_buf;
DWORD cbNeeded;
BOOL ok;
if (!load_psapi ())
goto failed;
cbNeeded = 0;
ok = (*win32_EnumProcessModules) (current_process_handle,
DllHandle,
sizeof (HMODULE),
&cbNeeded);
if (!ok || !cbNeeded)
goto failed;
DllHandle = (HMODULE *) alloca (cbNeeded);
if (!DllHandle)
goto failed;
ok = (*win32_EnumProcessModules) (current_process_handle,
DllHandle,
cbNeeded,
&cbNeeded);
if (!ok)
goto failed;
for (i = 0; i < ((size_t) cbNeeded / sizeof (HMODULE)); i++)
{
if (!(*win32_GetModuleInformation) (current_process_handle,
DllHandle[i],
&mi,
sizeof (mi)))
{
DWORD err = GetLastError ();
error ("Can't get module info: (error %d): %s\n",
(int) err, strwinerror (err));
}
if ((DWORD) (mi.lpBaseOfDll) == BaseAddress)
{
len = (*win32_GetModuleFileNameExA) (current_process_handle,
DllHandle[i],
dll_name_ret,
MAX_PATH);
if (len == 0)
{
DWORD err = GetLastError ();
error ("Error getting dll name: (error %d): %s\n",
(int) err, strwinerror (err));
}
return 1;
}
}
failed:
dll_name_ret[0] = '\0';
return 0;
}
typedef HANDLE (WINAPI *winapi_CreateToolhelp32Snapshot) (DWORD, DWORD);
typedef BOOL (WINAPI *winapi_Module32First) (HANDLE, LPMODULEENTRY32);
typedef BOOL (WINAPI *winapi_Module32Next) (HANDLE, LPMODULEENTRY32);
static winapi_CreateToolhelp32Snapshot win32_CreateToolhelp32Snapshot;
static winapi_Module32First win32_Module32First;
static winapi_Module32Next win32_Module32Next;
static BOOL
load_toolhelp (void)
{
static int toolhelp_loaded = 0;
static HMODULE dll = NULL;
if (!toolhelp_loaded)
{
toolhelp_loaded = 1;
#ifndef _WIN32_WCE
dll = GetModuleHandle (_T("KERNEL32.DLL"));
#else
dll = GetModuleHandle (_T("COREDLL.DLL"));
#endif
if (!dll)
return FALSE;
win32_CreateToolhelp32Snapshot =
GETPROCADDRESS (dll, CreateToolhelp32Snapshot);
win32_Module32First = GETPROCADDRESS (dll, Module32First);
win32_Module32Next = GETPROCADDRESS (dll, Module32Next);
}
return (win32_CreateToolhelp32Snapshot != NULL
&& win32_Module32First != NULL
&& win32_Module32Next != NULL);
}
static int
toolhelp_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
{
HANDLE snapshot_module;
MODULEENTRY32 modEntry = { sizeof (MODULEENTRY32) };
if (!load_toolhelp ())
return 0;
snapshot_module = win32_CreateToolhelp32Snapshot (TH32CS_SNAPMODULE,
current_event.dwProcessId);
if (snapshot_module == INVALID_HANDLE_VALUE)
return 0;
/* Ignore the first module, which is the exe. */
if (!win32_Module32First (snapshot_module, &modEntry))
goto failed;
while (win32_Module32Next (snapshot_module, &modEntry))
if ((DWORD) modEntry.modBaseAddr == BaseAddress)
{
#ifdef UNICODE
wcstombs (dll_name_ret, modEntry.szExePath, MAX_PATH + 1);
#else
strcpy (dll_name_ret, modEntry.szExePath);
#endif
CloseHandle (snapshot_module);
return 1;
}
failed:
CloseHandle (snapshot_module);
return 0;
}
static void
handle_load_dll (void)
{
LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
char dll_buf[MAX_PATH + 1];
char *dll_name = NULL;
DWORD load_addr;
dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
if (!psapi_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf)
&& !toolhelp_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf))
dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
dll_name = dll_buf;
if (*dll_name == '\0')
dll_name = get_image_name (current_process_handle,
event->lpImageName, event->fUnicode);
if (!dll_name)
return;
/* The symbols in a dll are offset by 0x1000, which is the
the offset from 0 of the first byte in an image - because
of the file header and the section alignment. */
load_addr = (DWORD) event->lpBaseOfDll + 0x1000;
win32_add_one_solib (dll_name, load_addr);
}
static void
handle_unload_dll (void)
{
CORE_ADDR load_addr =
(CORE_ADDR) (DWORD) current_event.u.UnloadDll.lpBaseOfDll;
load_addr += 0x1000;
unloaded_dll (NULL, load_addr);
}
static void
handle_exception (struct target_waitstatus *ourstatus)
{
@ -963,9 +1274,10 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
(unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId));
CloseHandle (current_event.u.LoadDll.hFile);
handle_load_dll ();
ourstatus->kind = TARGET_WAITKIND_LOADED;
ourstatus->value.integer = 0;
ourstatus->value.sig = TARGET_SIGNAL_TRAP;
break;
case UNLOAD_DLL_DEBUG_EVENT:
@ -973,6 +1285,9 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
"for pid=%d tid=%x\n",
(unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId));
handle_unload_dll ();
ourstatus->kind = TARGET_WAITKIND_LOADED;
ourstatus->value.sig = TARGET_SIGNAL_TRAP;
break;
case EXCEPTION_DEBUG_EVENT:
@ -1035,6 +1350,7 @@ win32_wait (char *status)
return our_status.value.integer;
case TARGET_WAITKIND_STOPPED:
case TARGET_WAITKIND_LOADED:
OUTMSG2 (("Child Stopped with signal = %d \n",
our_status.value.sig));
@ -1042,12 +1358,20 @@ win32_wait (char *status)
child_fetch_inferior_registers (-1);
if (our_status.kind == TARGET_WAITKIND_LOADED
&& !server_waiting)
{
/* When gdb connects, we want to be stopped at the
initial breakpoint, not in some dll load event. */
child_continue (DBG_CONTINUE, -1);
break;
}
return our_status.value.sig;
default:
OUTMSG (("Ignoring unknown internal event, %d\n", our_status.kind));
/* fall-through */
case TARGET_WAITKIND_SPURIOUS:
case TARGET_WAITKIND_LOADED:
case TARGET_WAITKIND_EXECD:
/* do nothing, just continue */
child_continue (DBG_CONTINUE, -1);

View file

@ -1,3 +1,11 @@
2007-07-17 Pedro Alves <pedro_alves@portugalmail.pt>
Daniel Jacobowitz <dan@codesourcery.com>
* gdb.base/unload.c (dlopen, dlsym, dlclose, dlerror): Define
for __WIN32__.
(SHLIB_NAME): Delete definition. Always pass dlerror to fprintf.
* gdb.base/unload.exp: Use shared library test routines.
2007-07-03 Markus Deuling <deuling@de.ibm.com>
* gdb.base/solib-symbol.exp: New file (testcase multiple symbol lookup).

View file

@ -18,12 +18,19 @@
#include <stdio.h>
#include <stdlib.h>
#ifdef __WIN32__
#include <windows.h>
#define dlopen(name, mode) LoadLibrary (name)
#define dlsym(handle, func) GetProcAddress (handle, func)
#define dlclose(handle) FreeLibrary (handle)
#define dlerror() "error %d occurred", GetLastError ()
#else
#include <dlfcn.h>
#endif
int k = 0;
#define SHLIB_NAME SHLIB_DIR "/unloadshr.sl"
int main()
{
void *handle;
@ -32,11 +39,10 @@ int main()
const char *msg;
handle = dlopen (SHLIB_NAME, RTLD_LAZY);
msg = dlerror ();
if (!handle)
{
fprintf (stderr, msg);
fprintf (stderr, dlerror ());
exit (1);
}

View file

@ -30,37 +30,28 @@ if {[skip_shlib_tests]} {
return 0
}
# TODO: Use LoadLibrary on these targets instead of dlopen.
if {([istarget arm*-*-symbianelf*]
|| [istarget *-*-mingw*]
|| [istarget *-*-cygwin*]
|| [istarget *-*-pe*])} {
# TODO: Use LoadLibrary on this target instead of dlopen.
if {[istarget arm*-*-symbianelf*]} {
return 0
}
set testfile "unload"
set libfile "unloadshr"
set libname "${libfile}.sl"
set libsrcfile ${libfile}.c
set srcfile $srcdir/$subdir/$testfile.c
set binfile $objdir/$subdir/$testfile
set shlibdir ${objdir}/${subdir}
set libsrc $srcdir/$subdir/$libfile.c
set lib_sl $objdir/$subdir/$libfile.sl
set lib_opts debug
set exec_opts [list debug additional_flags=-DSHLIB_DIR\=\"${shlibdir}\"]
switch -glob [istarget] {
"hppa*-hp-hpux*" { }
"*-*-linux*" { lappend exec_opts "libs=-ldl" }
"*-*-solaris*" { lappend exec_opts "libs=-ldl" }
default { }
}
set lib_sl $objdir/$subdir/$libname
if [get_compiler_info ${binfile}] {
return -1
}
set lib_opts debug
set exec_opts [list debug shlib_load additional_flags=-DSHLIB_NAME\=\"${libname}\"]
if { [gdb_compile_shlib $libsrc $lib_sl $lib_opts] != ""
|| [gdb_compile $srcfile $binfile executable $exec_opts] != ""} {
untested "Couldn't compile $libsrc or $srcfile."