From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12883 invoked by alias); 16 Aug 2007 00:44:34 -0000 Received: (qmail 11929 invoked by uid 22791); 16 Aug 2007 00:44:28 -0000 X-Spam-Check-By: sourceware.org Received: from ug-out-1314.google.com (HELO ug-out-1314.google.com) (66.249.92.169) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 16 Aug 2007 00:44:18 +0000 Received: by ug-out-1314.google.com with SMTP id s2so258590uge for ; Wed, 15 Aug 2007 17:44:15 -0700 (PDT) Received: by 10.67.119.9 with SMTP id w9mr1788589ugm.1187225055173; Wed, 15 Aug 2007 17:44:15 -0700 (PDT) Received: from ?88.210.64.47? ( [88.210.64.47]) by mx.google.com with ESMTPS id i4sm1153061nfh.2007.08.15.17.44.07 (version=TLSv1/SSLv3 cipher=RC4-MD5); Wed, 15 Aug 2007 17:44:12 -0700 (PDT) Message-ID: <46C39D10.3020001@portugalmail.pt> Date: Thu, 16 Aug 2007 00:44:00 -0000 From: Pedro Alves User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR; rv:1.8.0.12) Gecko/20070509 Thunderbird/1.5.0.12 Mnenhy/0.7.4.0 MIME-Version: 1.0 To: gdb-patches@sourceware.org Subject: Re: Windows DLL support update. References: <46C0F600.5010607@portugalmail.pt> <20070814121008.GA18838@ednor.casa.cgf.cx> In-Reply-To: <20070814121008.GA18838@ednor.casa.cgf.cx> Content-Type: multipart/mixed; boundary="------------070702000702000002000800" X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2007-08/txt/msg00324.txt.bz2 This is a multi-part message in MIME format. --------------070702000702000002000800 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 2156 Christopher Faylor wrote: > On Tue, Aug 14, 2007 at 01:23:28AM +0100, Pedro Alves wrote: >> Here is the new version of the patch that converts native win32 >> debugging to use the new solib-target.c. > > I have a few of questions/observations wrt the win32-nat.c changes. > Thanks for such a quick review. > 1) Does it still properly handle the "exceptions" that are thrown by > cygwin which must be ignored? I believe that the most populr source > of complaints about those came from people who were using pthreads > functions. > Yes. I tried with this: http://www.cygwin.com/ml/cygwin/2006-05/msg00650.html 'set cygwin-exceptions 1' shows the SEGV, 'set cygwin-exceptions 0' doesn't. > 2) Is there some reason you didn't record the cygwin load/start address > in win32_make_so? Isn't all of the information you need available when > that function is called? > I could open a bfd and look for .text like old solib_symbols_add does, but the so_list of the main list will have one open, so we can use that instead. I'll want to move these bits of cygwin detection and exception ignoring into a win32-tdep.c file that can be reused when remote debugging. This is step in that direction, but I'll understand if you still prefer the old way. > 3) If the answer to the above question is no, then it seems like > cygwin_load_start and cygwin_load_end should be static variables local > to ignore_access_violation_p. Storing the cygwin1.dll addresses and reusing it across runs should be ok if we assume that we are always debugging cygwin apps, but it could mask an access exception in a non-cygwin app that happened to occur in a dll loaded in that range by coincidence. I was going to leave it for later, but since you've asked, I'm now clearing the start/end addresses in do_initial_win32_stuff. This shows why they can't be local static. > I wonder if that logic should even be > further broken out into its own inside_cygwin(addr) function. Wonder no more. Done. > 4) I'd prefer it if you dropped the _p from "ignore_access_violation". > Done. I gave it another testsuite spin, and it looks good. -- Cheers, Pedro Alves --------------070702000702000002000800 Content-Type: text/x-diff; name="solib_target_cygwin.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="solib_target_cygwin.diff" Content-length: 33167 2007-07-02 Pedro Alves Daniel Jacobowitz * corelow.c (core_xfer_partial): Pass writebuf to deprecated_xfer_memory in TARGET_OBJECT_MEMORY case. Add TARGET_OBJECT_LIBRARIES handling. * gdb_obstack.h (obstack_grow_str, obstack_grow_str0): New. * gdbcore.h: Include target.h. (struct core_fns): Add xfer_shared_libraries. * infcmd.c (post_create_inferior): Update comment. (run_command_1): Always call post_create_inferior with 0 as from_tty. * win32-nat.c: Include gdb_obstack.h and xml-support.h. (win32_so_ops): Delete. (get_relocated_section_addrs): Delete. (solib_symbols_add): Delete. (register_loaded_dll): Delete. (win32_make_so): New. (handle_load_dll): Use win32_make_so. (win32_free_so): Free the passed in so. (win32_relocate_section_addresses): Delete. (win32_solib_create_inferior_hook): Delete. (handle_unload_dll): Don't add PE offset here. Free so with win32_free_so instead of free_so. (win32_special_symbol_handling): Delete. (inside_cygwin): New. (ignore_access_violation_p): New. (handle_exception): Use ignore_access_violation_p. (get_win32_debug_event): Remove unneeded calls. Set state to TARGET_WAITKIND_LOADED on a dll unload. (map_code_section_args): Delete. (solib_to_xml): New. (dll_code_sections_add): Delete. (struct cspm_data): New. (core_section_load_dll_symbols): Delete. (core_section_process_module): New. (win32_current_sos): Delete. (win32_core_xfer_shared_libraries): New. (win32_xfer_shared_libraries): New. (win32_xfer_partial): New. (fetch_elf_core_registers): Rename to ... (win32_fetch_elf_core_registers): ... this. (open_symbol_file_object): Delete. (in_dynsym_resolve_code): Delete. (init_win32_ops): Set win32_xfer_partial as to_xfer_partial member of win32_ops. Remove win32_so_ops settings. Don't set current_target_so_ops here. (win32_elf_core_fn): The fetch_elf_core_registers function was renamed to win32_fetch_elf_core_registers - update. Add win32_core_get_shared_libraries. * xml-support.c (gdb_xml_parse): Debug tweaks. (xml_escape_text): New. * xml-support.h (xml_escape_text): Declare. --- gdb/corelow.c | 10 gdb/gdb_obstack.h | 5 gdb/gdbcore.h | 9 gdb/infcmd.c | 8 gdb/win32-nat.c | 553 +++++++++++++++++++++--------------------------------- gdb/xml-support.c | 67 ++++++ gdb/xml-support.h | 42 ++-- 7 files changed, 341 insertions(+), 353 deletions(-) Index: src/gdb/corelow.c =================================================================== --- src.orig/gdb/corelow.c 2007-08-13 22:33:58.000000000 +0100 +++ src/gdb/corelow.c 2007-08-13 22:34:42.000000000 +0100 @@ -526,8 +526,8 @@ core_xfer_partial (struct target_ops *op return (*ops->deprecated_xfer_memory) (offset, readbuf, len, 0/*write*/, NULL, ops); if (writebuf) - return (*ops->deprecated_xfer_memory) (offset, readbuf, len, - 1/*write*/, NULL, ops); + return (*ops->deprecated_xfer_memory) (offset, (gdb_byte *) writebuf, + len, 1/*write*/, NULL, ops); return -1; case TARGET_OBJECT_AUXV: @@ -594,6 +594,12 @@ core_xfer_partial (struct target_ops *op } return -1; + case TARGET_OBJECT_LIBRARIES: + if (core_vec->xfer_shared_libraries != NULL) + return core_vec->xfer_shared_libraries (ops, object, annex, readbuf, + writebuf, offset, len); + /* FALL THROUGH */ + default: if (ops->beneath != NULL) return ops->beneath->to_xfer_partial (ops->beneath, object, annex, Index: src/gdb/gdb_obstack.h =================================================================== --- src.orig/gdb/gdb_obstack.h 2007-08-13 22:33:52.000000000 +0100 +++ src/gdb/gdb_obstack.h 2007-08-13 22:34:10.000000000 +0100 @@ -42,4 +42,9 @@ #define obstack_chunk_alloc xmalloc #define obstack_chunk_free xfree +#define obstack_grow_str(OBSTACK,STRING) \ + obstack_grow (OBSTACK, STRING, strlen (STRING)) +#define obstack_grow_str0(OBSTACK,STRING) \ + obstack_grow0 (OBSTACK, STRING, strlen (STRING)) + #endif Index: src/gdb/gdbcore.h =================================================================== --- src.orig/gdb/gdbcore.h 2007-08-13 22:33:52.000000000 +0100 +++ src/gdb/gdbcore.h 2007-08-13 22:34:10.000000000 +0100 @@ -29,6 +29,7 @@ struct type; struct regcache; #include "bfd.h" +#include "target.h" /* Return the name of the executable file as a string. ERR nonzero means get error if there is none specified; @@ -193,6 +194,14 @@ struct core_fns unsigned core_reg_size, int which, CORE_ADDR reg_addr); + /* Refresh the list of shared libraries. */ + LONGEST (*xfer_shared_libraries) (struct target_ops *ops, + enum target_object object, + const char *annex, + gdb_byte *readbuf, + const gdb_byte *writebuf, + ULONGEST offset, LONGEST len); + /* Finds the next struct core_fns. They are allocated and initialized in whatever module implements the functions pointed to; an initializer calls deprecated_add_core_fns to add them to Index: src/gdb/infcmd.c =================================================================== --- src.orig/gdb/infcmd.c 2007-08-13 22:33:52.000000000 +0100 +++ src/gdb/infcmd.c 2007-08-13 22:34:10.000000000 +0100 @@ -419,7 +419,9 @@ post_create_inferior (struct target_ops { /* Sometimes the platform-specific hook loads initial shared libraries, and sometimes it doesn't. Try to do so first, so - that we can add them with the correct value for FROM_TTY. */ + that we can add them with the correct value for FROM_TTY. + If we made all the inferior hook methods consistent, + this call could be removed. */ #ifdef SOLIB_ADD SOLIB_ADD (NULL, from_tty, target, auto_solib_add); #else @@ -560,7 +562,9 @@ run_command_1 (char *args, int from_tty, target_create_inferior (exec_file, get_inferior_args (), environ_vector (inferior_environ), from_tty); - post_create_inferior (¤t_target, from_tty); + /* Pass zero for FROM_TTY, because at this point the "run" command + has done its thing; now we are setting up the running program. */ + post_create_inferior (¤t_target, 0); /* Start the target running. */ proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0); Index: src/gdb/win32-nat.c =================================================================== --- src.orig/gdb/win32-nat.c 2007-08-13 22:33:52.000000000 +0100 +++ src/gdb/win32-nat.c 2007-08-16 01:08:48.000000000 +0100 @@ -48,6 +48,7 @@ #include "buildsym.h" #include "symfile.h" #include "objfiles.h" +#include "gdb_obstack.h" #include "gdb_string.h" #include "gdbthread.h" #include "gdbcmd.h" @@ -56,12 +57,12 @@ #include "exec.h" #include "solist.h" #include "solib.h" +#include "xml-support.h" #include "i386-tdep.h" #include "i387-tdep.h" static struct target_ops win32_ops; -static struct target_so_ops win32_so_ops; /* The starting and ending address of the cygwin1.dll text segment. */ static bfd_vma cygwin_load_start; @@ -600,123 +601,8 @@ safe_symbol_file_add (char *name, int fr return p.ret; } -/* Get the loaded address of all sections, given that .text was loaded - at text_load. Assumes that all sections are subject to the same - relocation offset. Returns NULL if problems occur or if the - sections were not relocated. */ - -static struct section_addr_info * -get_relocated_section_addrs (bfd *abfd, CORE_ADDR text_load) -{ - struct section_addr_info *result = NULL; - int section_count = bfd_count_sections (abfd); - asection *text_section = bfd_get_section_by_name (abfd, ".text"); - CORE_ADDR text_vma; - - if (!text_section) - { - /* Couldn't get the .text section. Weird. */ - } - else if (text_load == (text_vma = bfd_get_section_vma (abfd, text_section))) - { - /* DLL wasn't relocated. */ - } - else - { - /* Figure out all sections' loaded addresses. The offset here is - such that taking a bfd_get_section_vma() result and adding - offset will give the real load address of the section. */ - - CORE_ADDR offset = text_load - text_vma; - - struct section_table *table_start = NULL; - struct section_table *table_end = NULL; - struct section_table *iter = NULL; - - build_section_table (abfd, &table_start, &table_end); - - for (iter = table_start; iter < table_end; ++iter) - { - /* Relocated addresses. */ - iter->addr += offset; - iter->endaddr += offset; - } - - result = build_section_addr_info_from_section_table (table_start, - table_end); - - xfree (table_start); - } - - return result; -} - -/* Add DLL symbol information. */ -static void -solib_symbols_add (struct so_list *so, CORE_ADDR load_addr) -{ - struct section_addr_info *addrs = NULL; - static struct objfile *result = NULL; - char *name = so->so_name; - bfd *abfd = NULL; - char *p; - - /* 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. */ - - if (!name || !name[0]) - return; - - abfd = bfd_openr (name, "pei-i386"); - - if (!abfd) - { - /* pei failed - try pe */ - abfd = bfd_openr (name, "pe-i386"); - } - - if (abfd) - { - if (bfd_check_format (abfd, bfd_object)) - addrs = get_relocated_section_addrs (abfd, load_addr); - } - - if (addrs) - { - result = safe_symbol_file_add (name, 0, addrs, 0, OBJF_SHARED); - free_section_addr_info (addrs); - } - else - { - /* Fallback on handling just the .text section. */ - struct cleanup *my_cleanups; - - addrs = alloc_section_addr_info (1); - my_cleanups = make_cleanup (xfree, addrs); - addrs->other[0].name = ".text"; - addrs->other[0].addr = load_addr; - - result = safe_symbol_file_add (name, 0, addrs, 0, OBJF_SHARED); - do_cleanups (my_cleanups); - } - - p = strchr (so->so_name, '\0') - (sizeof ("/cygwin1.dll") - 1); - if (p >= so->so_name && strcasecmp (p, "/cygwin1.dll") == 0) - { - asection *text = bfd_get_section_by_name (abfd, ".text"); - cygwin_load_start = bfd_section_vma (abfd, text); - cygwin_load_end = cygwin_load_start + bfd_section_size (abfd, text); - } - - bfd_close (abfd); - - so->symbols_loaded = !!result; - return; -} - -static char * -register_loaded_dll (const char *name, DWORD load_addr, int readsyms) +static struct so_list * +win32_make_so (const char *name, DWORD load_addr) { struct so_list *so; char buf[MAX_PATH + 1]; @@ -725,7 +611,6 @@ register_loaded_dll (const char *name, D WIN32_FIND_DATA w32_fd; HANDLE h = FindFirstFile(name, &w32_fd); MEMORY_BASIC_INFORMATION m; - size_t len; if (h == INVALID_HANDLE_VALUE) strcpy (buf, name); @@ -753,15 +638,9 @@ register_loaded_dll (const char *name, D so->lm_info = (struct lm_info *) xmalloc (sizeof (struct lm_info)); so->lm_info->load_addr = load_addr; cygwin_conv_to_posix_path (buf, so->so_name); - strcpy (so->so_original_name, so->so_name); - - solib_end->next = so; - solib_end = so; - len = strlen (so->so_name); - if (readsyms) - solib_symbols_add (so, (CORE_ADDR) load_addr); + strcpy (so->so_original_name, name); - return so->so_name; + return so; } static char * @@ -822,11 +701,13 @@ handle_load_dll (void *dummy) dll_name = dll_buf; if (*dll_name == '\0') - dll_name = get_image_name (current_process_handle, event->lpImageName, event->fUnicode); + dll_name = get_image_name (current_process_handle, + event->lpImageName, event->fUnicode); if (!dll_name) return 1; - register_loaded_dll (dll_name, (DWORD) event->lpBaseOfDll + 0x1000, auto_solib_add); + solib_end->next = win32_make_so (dll_name, (DWORD) event->lpBaseOfDll); + solib_end = solib_end->next; return 1; } @@ -836,27 +717,13 @@ win32_free_so (struct so_list *so) { if (so->lm_info) xfree (so->lm_info); -} - -static void -win32_relocate_section_addresses (struct so_list *so, - struct section_table *sec) -{ - /* FIXME */ - return; -} - -static void -win32_solib_create_inferior_hook (void) -{ - solib_add (NULL, 0, NULL, auto_solib_add); - return; + xfree (so); } static int handle_unload_dll (void *dummy) { - DWORD lpBaseOfDll = (DWORD) current_event.u.UnloadDll.lpBaseOfDll + 0x1000; + DWORD lpBaseOfDll = (DWORD) current_event.u.UnloadDll.lpBaseOfDll; struct so_list *so; for (so = &solib_start; so->next != NULL; so = so->next) @@ -866,7 +733,7 @@ handle_unload_dll (void *dummy) so->next = sodel->next; if (!so->next) solib_end = so; - free_so (sodel); + win32_free_so (sodel); solib_add (NULL, 0, NULL, auto_solib_add); return 1; } @@ -884,12 +751,6 @@ win32_clear_solib (void) solib_end = &solib_start; } -static void -win32_special_symbol_handling (void) -{ - return; -} - /* Load DLL symbol info. */ void dll_symbol_command (char *args, int from_tty) @@ -1084,6 +945,67 @@ info_w32_command (char *args, int from_t help_list (info_w32_cmdlist, "info w32 ", class_info, gdb_stdout); } +/* Returns 1 if ADDR is within the cygwin1.dll text segment, returns 0 + otherwise. */ +static int +inside_cygwin (CORE_ADDR addr) +{ + if (cygwin_load_start == 0) + { + struct so_list *so; + + for (so = master_so_list (); so; so = so->next) + { + char *p; + p = strchr (so->so_name, '\0') - (sizeof ("/cygwin1.dll") - 1); + if (p >= so->so_name && strcasecmp (p, "/cygwin1.dll") == 0) + { + asection *text = bfd_get_section_by_name (so->abfd, ".text"); + if (text) + { + cygwin_load_start = bfd_section_vma (so->abfd, text); + cygwin_load_end = cygwin_load_start + + bfd_section_size (so->abfd, text); + } + break; + } + } + } + + if (cygwin_load_start == 0) + return 0; + + return (cygwin_load_start <= addr && addr < cygwin_load_end); +} + +static int +ignore_access_violation (CORE_ADDR addr) +{ + if (!cygwin_exceptions) + { + /* See if the access violation happened within the cygwin DLL + itself. Cygwin uses a kind of exception handling to deal + with passed-in invalid addresses. gdb should not treat these + as real SEGVs since they will be silently handled by cygwin. + A real SEGV will (theoretically) be caught by cygwin later in + the process and will be sent as a cygwin-specific-signal. + So, ignore SEGVs if they show up within the text segment of + the DLL itself. */ + if (inside_cygwin (addr)) + return 1; + } + + { + /* The IsBadXxxPtr family of Win32 functions triggers an access + violation by design. */ + char *fn; + if (find_pc_partial_function (addr, &fn, NULL, NULL) + && strncmp (fn, "KERNEL32!IsBad", strlen ("KERNEL32!IsBad")) == 0) + return 1; + } + + return 0; +} #define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \ printf_unfiltered ("gdb: Target exception %s at 0x%08lx\n", x, \ @@ -1105,20 +1027,10 @@ handle_exception (struct target_waitstat case EXCEPTION_ACCESS_VIOLATION: DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION"); ourstatus->value.sig = TARGET_SIGNAL_SEGV; - { - /* See if the access violation happened within the cygwin DLL itself. Cygwin uses - a kind of exception handling to deal with passed-in invalid addresses. gdb - should not treat these as real SEGVs since they will be silently handled by - cygwin. A real SEGV will (theoretically) be caught by cygwin later in the process - and will be sent as a cygwin-specific-signal. So, ignore SEGVs if they show up - within the text segment of the DLL itself. */ - char *fn; - bfd_vma addr = (bfd_vma) current_event.u.Exception.ExceptionRecord.ExceptionAddress; - if ((!cygwin_exceptions && (addr >= cygwin_load_start && addr < cygwin_load_end)) - || (find_pc_partial_function (addr, &fn, NULL, NULL) - && strncmp (fn, "KERNEL32!IsBad", strlen ("KERNEL32!IsBad")) == 0)) - return 0; - } + if (ignore_access_violation + ((CORE_ADDR) current_event.u. + Exception.ExceptionRecord.ExceptionAddress)) + return 0; break; case STATUS_STACK_OVERFLOW: DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW"); @@ -1457,11 +1369,9 @@ get_win32_debug_event (int pid, struct t if (saw_create != 1) break; catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL); - registers_changed (); /* mark all regs invalid */ ourstatus->kind = TARGET_WAITKIND_LOADED; ourstatus->value.integer = 0; retval = main_thread_id; - re_enable_breakpoints_in_shlibs (); break; case UNLOAD_DLL_DEBUG_EVENT: @@ -1472,9 +1382,9 @@ get_win32_debug_event (int pid, struct t if (saw_create != 1) break; catch_errors (handle_unload_dll, NULL, (char *) "", RETURN_MASK_ALL); - registers_changed (); /* mark all regs invalid */ - /* ourstatus->kind = TARGET_WAITKIND_UNLOADED; - does not exist yet. */ + ourstatus->kind = TARGET_WAITKIND_LOADED; + ourstatus->value.integer = 0; + retval = main_thread_id; break; case EXCEPTION_DEBUG_EVENT: @@ -1582,6 +1492,7 @@ do_initial_win32_stuff (DWORD pid) debug_registers_used = 0; for (i = 0; i < sizeof (dr) / sizeof (dr[0]); i++) dr[i] = 0; + cygwin_load_start = cygwin_load_end = 0; current_event.dwProcessId = pid; memset (¤t_event, 0, sizeof (current_event)); push_target (&win32_ops); @@ -2072,140 +1983,82 @@ cygwin_pid_to_str (ptid_t ptid) return buf; } -typedef struct -{ - struct target_ops *target; - bfd_vma addr; -} map_code_section_args; - static void -map_single_dll_code_section (bfd *abfd, asection *sect, void *obj) +solib_to_xml (struct so_list *so, struct obstack *obstack) { - int old; - int update_coreops; - struct section_table *new_target_sect_ptr; - - map_code_section_args *args = (map_code_section_args *) obj; - struct target_ops *target = args->target; - if (sect->flags & SEC_CODE) - { - update_coreops = core_ops.to_sections == target->to_sections; - - if (target->to_sections) - { - old = target->to_sections_end - target->to_sections; - target->to_sections = (struct section_table *) - xrealloc ((char *) target->to_sections, - (sizeof (struct section_table)) * (1 + old)); - } - else - { - old = 0; - target->to_sections = (struct section_table *) - xmalloc ((sizeof (struct section_table))); - } - target->to_sections_end = target->to_sections + (1 + old); - - /* Update the to_sections field in the core_ops structure - if needed. */ - if (update_coreops) - { - core_ops.to_sections = target->to_sections; - core_ops.to_sections_end = target->to_sections_end; - } - new_target_sect_ptr = target->to_sections + old; - new_target_sect_ptr->addr = args->addr + bfd_section_vma (abfd, sect); - new_target_sect_ptr->endaddr = args->addr + bfd_section_vma (abfd, sect) + - bfd_section_size (abfd, sect);; - new_target_sect_ptr->the_bfd_section = sect; - new_target_sect_ptr->bfd = abfd; - } + char *p; + obstack_grow_str (obstack, "so_name); + obstack_grow_str (obstack, p); + xfree (p); + obstack_grow_str (obstack, "\">lm_info->load_addr + 0x1000); + obstack_grow_str (obstack, p); + obstack_grow_str (obstack, "\"/>"); } -static int -dll_code_sections_add (const char *dll_name, int base_addr, struct target_ops *target) +struct cspm_data { - bfd *dll_bfd; - map_code_section_args map_args; - asection *lowest_sect; - char *name; - if (dll_name == NULL || target == NULL) - return 0; - name = xstrdup (dll_name); - dll_bfd = bfd_openr (name, "pei-i386"); - if (dll_bfd == NULL) - return 0; - - if (bfd_check_format (dll_bfd, bfd_object)) - { - lowest_sect = bfd_get_section_by_name (dll_bfd, ".text"); - if (lowest_sect == NULL) - return 0; - map_args.target = target; - map_args.addr = base_addr - bfd_section_vma (dll_bfd, lowest_sect); - - bfd_map_over_sections (dll_bfd, &map_single_dll_code_section, (void *) (&map_args)); - } - - return 1; -} + struct target_ops *target; + int module_count; + struct obstack *obstack; +}; static void -core_section_load_dll_symbols (bfd *abfd, asection *sect, void *obj) +core_section_process_module (bfd *abfd, asection *sect, void *obj) { - struct target_ops *target = (struct target_ops *) obj; + struct cspm_data *data = obj; + struct win32_pstatus *pstatus; + char *module_name; + int module_name_offset; + int module_name_size; DWORD base_addr; - int dll_name_size; - struct win32_pstatus *pstatus; - struct so_list *so; - char *dll_name; char *buf = NULL; - char *p; - struct objfile *objfile; - const char *dll_basename; if (strncmp (sect->name, ".module", 7) != 0) return; - buf = (char *) xmalloc (bfd_get_section_size (sect) + 1); + buf = xmalloc (bfd_get_section_size (sect) + 1); if (!buf) { printf_unfiltered ("memory allocation failed for %s\n", sect->name); goto out; } - if (!bfd_get_section_contents (abfd, sect, buf, 0, bfd_get_section_size (sect))) + if (!bfd_get_section_contents (abfd, sect, + buf, 0, bfd_get_section_size (sect))) goto out; pstatus = (struct win32_pstatus *) buf; - memmove (&base_addr, &(pstatus->data.module_info.base_address), sizeof (base_addr)); - dll_name_size = pstatus->data.module_info.module_name_size; - if (offsetof (struct win32_pstatus, data.module_info.module_name) + dll_name_size > bfd_get_section_size (sect)) - goto out; - - dll_name = pstatus->data.module_info.module_name; - - if (!(dll_basename = strrchr (dll_name, '/'))) - dll_basename = dll_name; - else - dll_basename++; - - ALL_OBJFILES (objfile) - { - char *objfile_basename = strrchr (objfile->name, '/'); + memcpy (&base_addr, &pstatus->data.module_info.base_address, + sizeof (base_addr)); - if (objfile_basename && - strcasecmp (dll_basename, objfile_basename + 1) == 0) + module_name_size = pstatus->data.module_info.module_name_size; + module_name = pstatus->data.module_info.module_name; + if (module_name - buf + module_name_size > bfd_get_section_size (sect)) goto out; - } - - base_addr += 0x1000; - dll_name = register_loaded_dll (dll_name, base_addr, 1); - if (!dll_code_sections_add (dll_name, (DWORD) base_addr, target)) - printf_unfiltered ("%s: Failed to map dll code sections.\n", dll_name); + if (data->module_count == 0) + { +#if 0 + /* TODO: What if the user supplied exec and/or + symbol files on the command line? */ + /* The first module is the .exe itself. */ + symbol_file_add_main (module_name, 0); +#endif + } + else + { + struct so_list *so = win32_make_so (module_name, base_addr); + solib_to_xml (so, data->obstack); + win32_free_so (so); + } + data->module_count++; out: if (buf) @@ -2213,39 +2066,103 @@ out: return; } -static struct so_list * -win32_current_sos (void) -{ - struct so_list *sop; - struct so_list *start = NULL; - struct so_list *last = NULL; +static LONGEST +win32_core_xfer_shared_libraries (struct target_ops *ops, + enum target_object object, const char *annex, + gdb_byte *readbuf, const gdb_byte *writebuf, + ULONGEST offset, LONGEST len) +{ + struct obstack obstack; + const char *buf; + LONGEST len_avail; + struct cspm_data data = { ops, 0, &obstack }; + + if (writebuf) + return -1; + + obstack_init (&obstack); + obstack_grow_str (&obstack, "\n"); + bfd_map_over_sections (core_bfd, + &core_section_process_module, + &data); + obstack_grow_str0 (&obstack, "\n"); + + buf = obstack_finish (&obstack); + len_avail = strlen (buf); + if (offset >= len_avail) + return 0; - if (!solib_start.next && core_bfd) - { - win32_clear_solib (); - bfd_map_over_sections (core_bfd, &core_section_load_dll_symbols, - &win32_ops); - } + if (len > len_avail - offset) + len = len_avail - offset; + memcpy (readbuf, buf + offset, len); + + obstack_free (&obstack, NULL); + return len; +} + +static LONGEST +win32_xfer_shared_libraries (struct target_ops *ops, + enum target_object object, const char *annex, + gdb_byte *readbuf, const gdb_byte *writebuf, + ULONGEST offset, LONGEST len) +{ + struct obstack obstack; + const char *buf; + LONGEST len_avail; + struct so_list *so; - for (sop = solib_start.next; sop; sop = sop->next) - { - struct so_list *new = XZALLOC (struct so_list); - strcpy (new->so_name, sop->so_name); - strcpy (new->so_original_name, sop->so_original_name); - if (!start) - last = start = new; - else - { - last->next = new; - last = new; - } - } + if (writebuf) + return -1; + + obstack_init (&obstack); + obstack_grow_str (&obstack, "\n"); + for (so = solib_start.next; so; so = so->next) + solib_to_xml (so, &obstack); + obstack_grow_str0 (&obstack, "\n"); + + buf = obstack_finish (&obstack); + len_avail = strlen (buf); + if (offset >= len_avail) + return 0; - return start; + if (len > len_avail - offset) + len = len_avail - offset; + memcpy (readbuf, buf + offset, len); + + obstack_free (&obstack, NULL); + return len; +} + +static LONGEST +win32_xfer_partial (struct target_ops *ops, enum target_object object, + const char *annex, gdb_byte *readbuf, + const gdb_byte *writebuf, ULONGEST offset, LONGEST len) +{ + switch (object) + { + case TARGET_OBJECT_MEMORY: + if (readbuf) + return (*ops->deprecated_xfer_memory) (offset, readbuf, len, + 0/*write*/, NULL, ops); + if (writebuf) + return (*ops->deprecated_xfer_memory) (offset, (gdb_byte *) writebuf, + len, 1/*write*/, NULL, ops); + return -1; + + case TARGET_OBJECT_LIBRARIES: + return win32_xfer_shared_libraries (ops, object, annex, readbuf, + writebuf, offset, len); + + default: + if (ops->beneath != NULL) + return ops->beneath->to_xfer_partial (ops->beneath, object, annex, + readbuf, writebuf, offset, len); + return -1; + } } static void -fetch_elf_core_registers (struct regcache *regcache, +win32_fetch_elf_core_registers (struct regcache *regcache, char *core_reg_sect, unsigned core_reg_size, int which, @@ -2261,18 +2178,6 @@ fetch_elf_core_registers (struct regcach regcache_raw_supply (regcache, r, core_reg_sect + mappings[r]); } -static int -open_symbol_file_object (void *from_ttyp) -{ - return 0; -} - -static int -in_dynsym_resolve_code (CORE_ADDR pc) -{ - return 0; -} - static void init_win32_ops (void) { @@ -2289,6 +2194,7 @@ init_win32_ops (void) win32_ops.to_store_registers = win32_store_inferior_registers; win32_ops.to_prepare_to_store = win32_prepare_to_store; win32_ops.deprecated_xfer_memory = win32_xfer_memory; + win32_ops.to_xfer_partial = win32_xfer_partial; win32_ops.to_files_info = win32_files_info; win32_ops.to_insert_breakpoint = memory_insert_breakpoint; win32_ops.to_remove_breakpoint = memory_remove_breakpoint; @@ -2313,18 +2219,6 @@ init_win32_ops (void) win32_ops.to_has_execution = 1; win32_ops.to_magic = OPS_MAGIC; win32_ops.to_pid_to_exec_file = win32_pid_to_exec_file; - - win32_so_ops.relocate_section_addresses = win32_relocate_section_addresses; - win32_so_ops.free_so = win32_free_so; - win32_so_ops.clear_solib = win32_clear_solib; - win32_so_ops.solib_create_inferior_hook = win32_solib_create_inferior_hook; - win32_so_ops.special_symbol_handling = win32_special_symbol_handling; - win32_so_ops.current_sos = win32_current_sos; - win32_so_ops.open_symbol_file_object = open_symbol_file_object; - win32_so_ops.in_dynsym_resolve_code = in_dynsym_resolve_code; - - /* FIXME: Don't do this here. *_gdbarch_init() should set so_ops. */ - current_target_so_ops = &win32_so_ops; } static void @@ -2467,7 +2361,8 @@ static struct core_fns win32_elf_core_fn bfd_target_elf_flavour, default_check_format, default_core_sniffer, - fetch_elf_core_registers, + win32_fetch_elf_core_registers, + win32_core_xfer_shared_libraries, NULL }; Index: src/gdb/xml-support.c =================================================================== --- src.orig/gdb/xml-support.c 2007-08-13 22:33:52.000000000 +0100 +++ src/gdb/xml-support.c 2007-08-13 22:34:10.000000000 +0100 @@ -546,6 +546,8 @@ gdb_xml_parse (struct gdb_xml_parser *pa enum XML_Status status; const char *error_string; + gdb_xml_debug (parser, _("Starting:\n%s"), buffer); + status = XML_Parse (parser->expat_parser, buffer, strlen (buffer), 1); if (status == XML_STATUS_OK && parser->error.reason == 0) @@ -871,8 +873,7 @@ xml_process_xincludes (const char *name, result = xstrdup (obstack_finish (&data->obstack)); if (depth == 0) - gdb_xml_debug (parser, _("XInclude processing succeeded:\n%s"), - result); + gdb_xml_debug (parser, _("XInclude processing succeeded.")); } else result = NULL; @@ -936,6 +937,68 @@ show_debug_xml (struct ui_file *file, in fprintf_filtered (file, _("XML debugging is %s.\n"), value); } +/* 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 = xmalloc (i + special + 1); + for (i = 0, special = 0; text[i] != '\0'; i++) + switch (text[i]) + { + case '\'': + strcpy (result + i + special, "'"); + special += 5; + break; + case '\"': + strcpy (result + i + special, """); + special += 5; + break; + case '&': + strcpy (result + i + special, "&"); + special += 4; + break; + case '<': + strcpy (result + i + special, "<"); + special += 3; + break; + case '>': + strcpy (result + i + special, ">"); + special += 3; + break; + default: + result[i + special] = text[i]; + break; + } + result[i + special] = '\0'; + + return result; +} + void _initialize_xml_support (void); void Index: src/gdb/xml-support.h =================================================================== --- src.orig/gdb/xml-support.h 2007-08-13 22:33:52.000000000 +0100 +++ src/gdb/xml-support.h 2007-08-13 22:34:10.000000000 +0100 @@ -30,24 +30,6 @@ struct gdb_xml_parser; struct gdb_xml_element; struct gdb_xml_attribute; -/* Support for XInclude. */ - -/* Callback to fetch a new XML file, based on the provided HREF. */ - -typedef char *(*xml_fetch_another) (const char *href, void *baton); - -/* Return a new string which is the expansion of TEXT after processing - tags. FETCHER will be called (with FETCHER_BATON) to - retrieve any new files. DEPTH should be zero on the initial call. - - On failure, this function uses NAME in a warning and returns NULL. - It may throw an exception, but does not for XML parsing - problems. */ - -char *xml_process_xincludes (const char *name, const char *text, - xml_fetch_another fetcher, void *fetcher_baton, - int depth); - /* Return an XML document which was compiled into GDB, from the given FILENAME, or NULL if the file was not compiled in. */ @@ -64,8 +46,32 @@ LONGEST xml_builtin_xfer_partial (const /* The text of compiled-in XML documents, from xml-builtin.c (generated). */ + extern const char *xml_builtin[][2]; +/* Return a malloc allocated string with special characters from TEXT + replaced by entity references. */ + +char *xml_escape_text (const char *text); + +/* Support for XInclude. */ + +/* Callback to fetch a new XML file, based on the provided HREF. */ + +typedef char *(*xml_fetch_another) (const char *href, void *baton); + +/* Return a new string which is the expansion of TEXT after processing + tags. FETCHER will be called (with FETCHER_BATON) to + retrieve any new files. DEPTH should be zero on the initial call. + + On failure, this function uses NAME in a warning and returns NULL. + It may throw an exception, but does not for XML parsing + problems. */ + +char *xml_process_xincludes (const char *name, const char *text, + xml_fetch_another fetcher, void *fetcher_baton, + int depth); + /* Simplified XML parser infrastructure. */ /* A name and value pair, used to record parsed attributes. */ --------------070702000702000002000800--