1130803Smarcel/* Target-vector operations for controlling win32 child processes, for GDB. 2130803Smarcel 3130803Smarcel Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free 4130803Smarcel Software Foundation, Inc. 5130803Smarcel 6130803Smarcel Contributed by Cygnus Solutions, A Red Hat Company. 7130803Smarcel 8130803Smarcel This file is part of GDB. 9130803Smarcel 10130803Smarcel This program is free software; you can redistribute it and/or modify 11130803Smarcel it under the terms of the GNU General Public License as published by 12130803Smarcel the Free Software Foundation; either version 2 of the License, or 13130803Smarcel (at your option) any later version. 14130803Smarcel 15130803Smarcel This program is distributed in the hope that it will be useful, 16130803Smarcel but WITHOUT ANY WARRANTY; without eve nthe implied warranty of 17130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18130803Smarcel GNU General Public License for more details. 19130803Smarcel 20130803Smarcel You should have received a copy of the GNU General Public License 21130803Smarcel along with this program; if not, write to the Free Software 22130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 23130803Smarcel Boston, MA 02111-1307, USA. */ 24130803Smarcel 25130803Smarcel/* Originally by Steve Chamberlain, sac@cygnus.com */ 26130803Smarcel 27130803Smarcel/* We assume we're being built with and will be used for cygwin. */ 28130803Smarcel 29130803Smarcel#include "defs.h" 30130803Smarcel#include "frame.h" /* required by inferior.h */ 31130803Smarcel#include "inferior.h" 32130803Smarcel#include "target.h" 33130803Smarcel#include "gdbcore.h" 34130803Smarcel#include "command.h" 35130803Smarcel#include "completer.h" 36130803Smarcel#include "regcache.h" 37130803Smarcel#include "top.h" 38130803Smarcel#include <signal.h> 39130803Smarcel#include <sys/types.h> 40130803Smarcel#include <fcntl.h> 41130803Smarcel#include <stdlib.h> 42130803Smarcel#include <windows.h> 43130803Smarcel#include <imagehlp.h> 44130803Smarcel#include <sys/cygwin.h> 45130803Smarcel 46130803Smarcel#include "buildsym.h" 47130803Smarcel#include "symfile.h" 48130803Smarcel#include "objfiles.h" 49130803Smarcel#include "gdb_string.h" 50130803Smarcel#include "gdbthread.h" 51130803Smarcel#include "gdbcmd.h" 52130803Smarcel#include <sys/param.h> 53130803Smarcel#include <unistd.h> 54130803Smarcel#include "exec.h" 55130803Smarcel 56130803Smarcel#include "i386-tdep.h" 57130803Smarcel#include "i387-tdep.h" 58130803Smarcel 59130803Smarcel/* The ui's event loop. */ 60130803Smarcelextern int (*ui_loop_hook) (int signo); 61130803Smarcel 62130803Smarcel/* If we're not using the old Cygwin header file set, define the 63130803Smarcel following which never should have been in the generic Win32 API 64130803Smarcel headers in the first place since they were our own invention... */ 65130803Smarcel#ifndef _GNU_H_WINDOWS_H 66130803Smarcelenum 67130803Smarcel { 68130803Smarcel FLAG_TRACE_BIT = 0x100, 69130803Smarcel CONTEXT_DEBUGGER = (CONTEXT_FULL | CONTEXT_FLOATING_POINT) 70130803Smarcel }; 71130803Smarcel#endif 72130803Smarcel#include <sys/procfs.h> 73130803Smarcel#include <psapi.h> 74130803Smarcel 75130803Smarcel#define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS \ 76130803Smarcel | CONTEXT_EXTENDED_REGISTERS 77130803Smarcel 78130803Smarcelstatic unsigned dr[8]; 79130803Smarcelstatic int debug_registers_changed; 80130803Smarcelstatic int debug_registers_used; 81130803Smarcel 82130803Smarcel/* The string sent by cygwin when it processes a signal. 83130803Smarcel FIXME: This should be in a cygwin include file. */ 84130803Smarcel#define CYGWIN_SIGNAL_STRING "cygwin: signal" 85130803Smarcel 86130803Smarcel#define CHECK(x) check (x, __FILE__,__LINE__) 87130803Smarcel#define DEBUG_EXEC(x) if (debug_exec) printf_unfiltered x 88130803Smarcel#define DEBUG_EVENTS(x) if (debug_events) printf_unfiltered x 89130803Smarcel#define DEBUG_MEM(x) if (debug_memory) printf_unfiltered x 90130803Smarcel#define DEBUG_EXCEPT(x) if (debug_exceptions) printf_unfiltered x 91130803Smarcel 92130803Smarcel/* Forward declaration */ 93130803Smarcelextern struct target_ops child_ops; 94130803Smarcel 95130803Smarcelstatic void child_stop (void); 96130803Smarcelstatic int win32_child_thread_alive (ptid_t); 97130803Smarcelvoid child_kill_inferior (void); 98130803Smarcel 99130803Smarcelstatic enum target_signal last_sig = TARGET_SIGNAL_0; 100130803Smarcel/* Set if a signal was received from the debugged process */ 101130803Smarcel 102130803Smarcel/* Thread information structure used to track information that is 103130803Smarcel not available in gdb's thread structure. */ 104130803Smarceltypedef struct thread_info_struct 105130803Smarcel { 106130803Smarcel struct thread_info_struct *next; 107130803Smarcel DWORD id; 108130803Smarcel HANDLE h; 109130803Smarcel char *name; 110130803Smarcel int suspend_count; 111130803Smarcel int reload_context; 112130803Smarcel CONTEXT context; 113130803Smarcel STACKFRAME sf; 114130803Smarcel } 115130803Smarcelthread_info; 116130803Smarcel 117130803Smarcelstatic thread_info thread_head; 118130803Smarcel 119130803Smarcel/* The process and thread handles for the above context. */ 120130803Smarcel 121130803Smarcelstatic DEBUG_EVENT current_event; /* The current debug event from 122130803Smarcel WaitForDebugEvent */ 123130803Smarcelstatic HANDLE current_process_handle; /* Currently executing process */ 124130803Smarcelstatic thread_info *current_thread; /* Info on currently selected thread */ 125130803Smarcelstatic DWORD main_thread_id; /* Thread ID of the main thread */ 126130803Smarcel 127130803Smarcel/* Counts of things. */ 128130803Smarcelstatic int exception_count = 0; 129130803Smarcelstatic int event_count = 0; 130130803Smarcelstatic int saw_create; 131130803Smarcel 132130803Smarcel/* User options. */ 133130803Smarcelstatic int new_console = 0; 134130803Smarcelstatic int new_group = 1; 135130803Smarcelstatic int debug_exec = 0; /* show execution */ 136130803Smarcelstatic int debug_events = 0; /* show events from kernel */ 137130803Smarcelstatic int debug_memory = 0; /* show target memory accesses */ 138130803Smarcelstatic int debug_exceptions = 0; /* show target exceptions */ 139130803Smarcelstatic int useshell = 0; /* use shell for subprocesses */ 140130803Smarcel 141130803Smarcel/* This vector maps GDB's idea of a register's number into an address 142130803Smarcel in the win32 exception context vector. 143130803Smarcel 144130803Smarcel It also contains the bit mask needed to load the register in question. 145130803Smarcel 146130803Smarcel One day we could read a reg, we could inspect the context we 147130803Smarcel already have loaded, if it doesn't have the bit set that we need, 148130803Smarcel we read that set of registers in using GetThreadContext. If the 149130803Smarcel context already contains what we need, we just unpack it. Then to 150130803Smarcel write a register, first we have to ensure that the context contains 151130803Smarcel the other regs of the group, and then we copy the info in and set 152130803Smarcel out bit. */ 153130803Smarcel 154130803Smarcel#define context_offset(x) ((int)&(((CONTEXT *)NULL)->x)) 155130803Smarcelstatic const int mappings[] = 156130803Smarcel{ 157130803Smarcel context_offset (Eax), 158130803Smarcel context_offset (Ecx), 159130803Smarcel context_offset (Edx), 160130803Smarcel context_offset (Ebx), 161130803Smarcel context_offset (Esp), 162130803Smarcel context_offset (Ebp), 163130803Smarcel context_offset (Esi), 164130803Smarcel context_offset (Edi), 165130803Smarcel context_offset (Eip), 166130803Smarcel context_offset (EFlags), 167130803Smarcel context_offset (SegCs), 168130803Smarcel context_offset (SegSs), 169130803Smarcel context_offset (SegDs), 170130803Smarcel context_offset (SegEs), 171130803Smarcel context_offset (SegFs), 172130803Smarcel context_offset (SegGs), 173130803Smarcel context_offset (FloatSave.RegisterArea[0 * 10]), 174130803Smarcel context_offset (FloatSave.RegisterArea[1 * 10]), 175130803Smarcel context_offset (FloatSave.RegisterArea[2 * 10]), 176130803Smarcel context_offset (FloatSave.RegisterArea[3 * 10]), 177130803Smarcel context_offset (FloatSave.RegisterArea[4 * 10]), 178130803Smarcel context_offset (FloatSave.RegisterArea[5 * 10]), 179130803Smarcel context_offset (FloatSave.RegisterArea[6 * 10]), 180130803Smarcel context_offset (FloatSave.RegisterArea[7 * 10]), 181130803Smarcel context_offset (FloatSave.ControlWord), 182130803Smarcel context_offset (FloatSave.StatusWord), 183130803Smarcel context_offset (FloatSave.TagWord), 184130803Smarcel context_offset (FloatSave.ErrorSelector), 185130803Smarcel context_offset (FloatSave.ErrorOffset), 186130803Smarcel context_offset (FloatSave.DataSelector), 187130803Smarcel context_offset (FloatSave.DataOffset), 188130803Smarcel context_offset (FloatSave.ErrorSelector) 189130803Smarcel /* XMM0-7 */ , 190130803Smarcel context_offset (ExtendedRegisters[10*16]), 191130803Smarcel context_offset (ExtendedRegisters[11*16]), 192130803Smarcel context_offset (ExtendedRegisters[12*16]), 193130803Smarcel context_offset (ExtendedRegisters[13*16]), 194130803Smarcel context_offset (ExtendedRegisters[14*16]), 195130803Smarcel context_offset (ExtendedRegisters[15*16]), 196130803Smarcel context_offset (ExtendedRegisters[16*16]), 197130803Smarcel context_offset (ExtendedRegisters[17*16]), 198130803Smarcel /* MXCSR */ 199130803Smarcel context_offset (ExtendedRegisters[24]) 200130803Smarcel}; 201130803Smarcel 202130803Smarcel#undef context_offset 203130803Smarcel 204130803Smarcel/* This vector maps the target's idea of an exception (extracted 205130803Smarcel from the DEBUG_EVENT structure) to GDB's idea. */ 206130803Smarcel 207130803Smarcelstruct xlate_exception 208130803Smarcel { 209130803Smarcel int them; 210130803Smarcel enum target_signal us; 211130803Smarcel }; 212130803Smarcel 213130803Smarcelstatic const struct xlate_exception 214130803Smarcel xlate[] = 215130803Smarcel{ 216130803Smarcel {EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV}, 217130803Smarcel {STATUS_STACK_OVERFLOW, TARGET_SIGNAL_SEGV}, 218130803Smarcel {EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP}, 219130803Smarcel {DBG_CONTROL_C, TARGET_SIGNAL_INT}, 220130803Smarcel {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP}, 221130803Smarcel {STATUS_FLOAT_DIVIDE_BY_ZERO, TARGET_SIGNAL_FPE}, 222130803Smarcel {-1, -1}}; 223130803Smarcel 224130803Smarcelstatic void 225130803Smarcelcheck (BOOL ok, const char *file, int line) 226130803Smarcel{ 227130803Smarcel if (!ok) 228130803Smarcel printf_filtered ("error return %s:%d was %lu\n", file, line, 229130803Smarcel GetLastError ()); 230130803Smarcel} 231130803Smarcel 232130803Smarcel/* Find a thread record given a thread id. 233130803Smarcel If get_context then also retrieve the context for this 234130803Smarcel thread. */ 235130803Smarcelstatic thread_info * 236130803Smarcelthread_rec (DWORD id, int get_context) 237130803Smarcel{ 238130803Smarcel thread_info *th; 239130803Smarcel 240130803Smarcel for (th = &thread_head; (th = th->next) != NULL;) 241130803Smarcel if (th->id == id) 242130803Smarcel { 243130803Smarcel if (!th->suspend_count && get_context) 244130803Smarcel { 245130803Smarcel if (get_context > 0 && id != current_event.dwThreadId) 246130803Smarcel th->suspend_count = SuspendThread (th->h) + 1; 247130803Smarcel else if (get_context < 0) 248130803Smarcel th->suspend_count = -1; 249130803Smarcel th->reload_context = 1; 250130803Smarcel } 251130803Smarcel return th; 252130803Smarcel } 253130803Smarcel 254130803Smarcel return NULL; 255130803Smarcel} 256130803Smarcel 257130803Smarcel/* Add a thread to the thread list */ 258130803Smarcelstatic thread_info * 259130803Smarcelchild_add_thread (DWORD id, HANDLE h) 260130803Smarcel{ 261130803Smarcel thread_info *th; 262130803Smarcel 263130803Smarcel if ((th = thread_rec (id, FALSE))) 264130803Smarcel return th; 265130803Smarcel 266130803Smarcel th = (thread_info *) xmalloc (sizeof (*th)); 267130803Smarcel memset (th, 0, sizeof (*th)); 268130803Smarcel th->id = id; 269130803Smarcel th->h = h; 270130803Smarcel th->next = thread_head.next; 271130803Smarcel thread_head.next = th; 272130803Smarcel add_thread (pid_to_ptid (id)); 273130803Smarcel /* Set the debug registers for the new thread in they are used. */ 274130803Smarcel if (debug_registers_used) 275130803Smarcel { 276130803Smarcel /* Only change the value of the debug registers. */ 277130803Smarcel th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS; 278130803Smarcel CHECK (GetThreadContext (th->h, &th->context)); 279130803Smarcel th->context.Dr0 = dr[0]; 280130803Smarcel th->context.Dr1 = dr[1]; 281130803Smarcel th->context.Dr2 = dr[2]; 282130803Smarcel th->context.Dr3 = dr[3]; 283130803Smarcel /* th->context.Dr6 = dr[6]; 284130803Smarcel FIXME: should we set dr6 also ?? */ 285130803Smarcel th->context.Dr7 = dr[7]; 286130803Smarcel CHECK (SetThreadContext (th->h, &th->context)); 287130803Smarcel th->context.ContextFlags = 0; 288130803Smarcel } 289130803Smarcel return th; 290130803Smarcel} 291130803Smarcel 292130803Smarcel/* Clear out any old thread list and reintialize it to a 293130803Smarcel pristine state. */ 294130803Smarcelstatic void 295130803Smarcelchild_init_thread_list (void) 296130803Smarcel{ 297130803Smarcel thread_info *th = &thread_head; 298130803Smarcel 299130803Smarcel DEBUG_EVENTS (("gdb: child_init_thread_list\n")); 300130803Smarcel init_thread_list (); 301130803Smarcel while (th->next != NULL) 302130803Smarcel { 303130803Smarcel thread_info *here = th->next; 304130803Smarcel th->next = here->next; 305130803Smarcel (void) CloseHandle (here->h); 306130803Smarcel xfree (here); 307130803Smarcel } 308130803Smarcel} 309130803Smarcel 310130803Smarcel/* Delete a thread from the list of threads */ 311130803Smarcelstatic void 312130803Smarcelchild_delete_thread (DWORD id) 313130803Smarcel{ 314130803Smarcel thread_info *th; 315130803Smarcel 316130803Smarcel if (info_verbose) 317130803Smarcel printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (pid_to_ptid (id))); 318130803Smarcel delete_thread (pid_to_ptid (id)); 319130803Smarcel 320130803Smarcel for (th = &thread_head; 321130803Smarcel th->next != NULL && th->next->id != id; 322130803Smarcel th = th->next) 323130803Smarcel continue; 324130803Smarcel 325130803Smarcel if (th->next != NULL) 326130803Smarcel { 327130803Smarcel thread_info *here = th->next; 328130803Smarcel th->next = here->next; 329130803Smarcel CloseHandle (here->h); 330130803Smarcel xfree (here); 331130803Smarcel } 332130803Smarcel} 333130803Smarcel 334130803Smarcelstatic void 335130803Smarceldo_child_fetch_inferior_registers (int r) 336130803Smarcel{ 337130803Smarcel char *context_offset = ((char *) ¤t_thread->context) + mappings[r]; 338130803Smarcel long l; 339130803Smarcel 340130803Smarcel if (!current_thread) 341130803Smarcel return; /* Windows sometimes uses a non-existent thread id in its 342130803Smarcel events */ 343130803Smarcel 344130803Smarcel if (current_thread->reload_context) 345130803Smarcel { 346130803Smarcel thread_info *th = current_thread; 347130803Smarcel th->context.ContextFlags = CONTEXT_DEBUGGER_DR; 348130803Smarcel GetThreadContext (th->h, &th->context); 349130803Smarcel /* Copy dr values from that thread. */ 350130803Smarcel dr[0] = th->context.Dr0; 351130803Smarcel dr[1] = th->context.Dr1; 352130803Smarcel dr[2] = th->context.Dr2; 353130803Smarcel dr[3] = th->context.Dr3; 354130803Smarcel dr[6] = th->context.Dr6; 355130803Smarcel dr[7] = th->context.Dr7; 356130803Smarcel current_thread->reload_context = 0; 357130803Smarcel } 358130803Smarcel 359130803Smarcel#define I387_ST0_REGNUM I386_ST0_REGNUM 360130803Smarcel 361130803Smarcel if (r == I387_FISEG_REGNUM) 362130803Smarcel { 363130803Smarcel l = *((long *) context_offset) & 0xffff; 364130803Smarcel supply_register (r, (char *) &l); 365130803Smarcel } 366130803Smarcel else if (r == I387_FOP_REGNUM) 367130803Smarcel { 368130803Smarcel l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1); 369130803Smarcel supply_register (r, (char *) &l); 370130803Smarcel } 371130803Smarcel else if (r >= 0) 372130803Smarcel supply_register (r, context_offset); 373130803Smarcel else 374130803Smarcel { 375130803Smarcel for (r = 0; r < NUM_REGS; r++) 376130803Smarcel do_child_fetch_inferior_registers (r); 377130803Smarcel } 378130803Smarcel 379130803Smarcel#undef I387_ST0_REGNUM 380130803Smarcel} 381130803Smarcel 382130803Smarcelstatic void 383130803Smarcelchild_fetch_inferior_registers (int r) 384130803Smarcel{ 385130803Smarcel current_thread = thread_rec (PIDGET (inferior_ptid), TRUE); 386130803Smarcel /* Check if current_thread exists. Windows sometimes uses a non-existent 387130803Smarcel thread id in its events */ 388130803Smarcel if (current_thread) 389130803Smarcel do_child_fetch_inferior_registers (r); 390130803Smarcel} 391130803Smarcel 392130803Smarcelstatic void 393130803Smarceldo_child_store_inferior_registers (int r) 394130803Smarcel{ 395130803Smarcel if (!current_thread) 396130803Smarcel /* Windows sometimes uses a non-existent thread id in its events */; 397130803Smarcel else if (r >= 0) 398130803Smarcel regcache_collect (r, ((char *) ¤t_thread->context) + mappings[r]); 399130803Smarcel else 400130803Smarcel { 401130803Smarcel for (r = 0; r < NUM_REGS; r++) 402130803Smarcel do_child_store_inferior_registers (r); 403130803Smarcel } 404130803Smarcel} 405130803Smarcel 406130803Smarcel/* Store a new register value into the current thread context */ 407130803Smarcelstatic void 408130803Smarcelchild_store_inferior_registers (int r) 409130803Smarcel{ 410130803Smarcel current_thread = thread_rec (PIDGET (inferior_ptid), TRUE); 411130803Smarcel /* Check if current_thread exists. Windows sometimes uses a non-existent 412130803Smarcel thread id in its events */ 413130803Smarcel if (current_thread) 414130803Smarcel do_child_store_inferior_registers (r); 415130803Smarcel} 416130803Smarcel 417130803Smarcelstatic int psapi_loaded = 0; 418130803Smarcelstatic HMODULE psapi_module_handle = NULL; 419130803Smarcelstatic BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD, LPDWORD) = NULL; 420130803Smarcelstatic BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO, DWORD) = NULL; 421130803Smarcelstatic DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD) = NULL; 422130803Smarcel 423130803Smarcelint 424130803Smarcelpsapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret) 425130803Smarcel{ 426130803Smarcel DWORD len; 427130803Smarcel MODULEINFO mi; 428130803Smarcel int i; 429130803Smarcel HMODULE dh_buf[1]; 430130803Smarcel HMODULE *DllHandle = dh_buf; 431130803Smarcel DWORD cbNeeded; 432130803Smarcel BOOL ok; 433130803Smarcel 434130803Smarcel if (!psapi_loaded || 435130803Smarcel psapi_EnumProcessModules == NULL || 436130803Smarcel psapi_GetModuleInformation == NULL || 437130803Smarcel psapi_GetModuleFileNameExA == NULL) 438130803Smarcel { 439130803Smarcel if (psapi_loaded) 440130803Smarcel goto failed; 441130803Smarcel psapi_loaded = 1; 442130803Smarcel psapi_module_handle = LoadLibrary ("psapi.dll"); 443130803Smarcel if (!psapi_module_handle) 444130803Smarcel { 445130803Smarcel /* printf_unfiltered ("error loading psapi.dll: %u", GetLastError ()); */ 446130803Smarcel goto failed; 447130803Smarcel } 448130803Smarcel psapi_EnumProcessModules = GetProcAddress (psapi_module_handle, "EnumProcessModules"); 449130803Smarcel psapi_GetModuleInformation = GetProcAddress (psapi_module_handle, "GetModuleInformation"); 450130803Smarcel psapi_GetModuleFileNameExA = (void *) GetProcAddress (psapi_module_handle, 451130803Smarcel "GetModuleFileNameExA"); 452130803Smarcel if (psapi_EnumProcessModules == NULL || 453130803Smarcel psapi_GetModuleInformation == NULL || 454130803Smarcel psapi_GetModuleFileNameExA == NULL) 455130803Smarcel goto failed; 456130803Smarcel } 457130803Smarcel 458130803Smarcel cbNeeded = 0; 459130803Smarcel ok = (*psapi_EnumProcessModules) (current_process_handle, 460130803Smarcel DllHandle, 461130803Smarcel sizeof (HMODULE), 462130803Smarcel &cbNeeded); 463130803Smarcel 464130803Smarcel if (!ok || !cbNeeded) 465130803Smarcel goto failed; 466130803Smarcel 467130803Smarcel DllHandle = (HMODULE *) alloca (cbNeeded); 468130803Smarcel if (!DllHandle) 469130803Smarcel goto failed; 470130803Smarcel 471130803Smarcel ok = (*psapi_EnumProcessModules) (current_process_handle, 472130803Smarcel DllHandle, 473130803Smarcel cbNeeded, 474130803Smarcel &cbNeeded); 475130803Smarcel if (!ok) 476130803Smarcel goto failed; 477130803Smarcel 478130803Smarcel for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++) 479130803Smarcel { 480130803Smarcel if (!(*psapi_GetModuleInformation) (current_process_handle, 481130803Smarcel DllHandle[i], 482130803Smarcel &mi, 483130803Smarcel sizeof (mi))) 484130803Smarcel error ("Can't get module info"); 485130803Smarcel 486130803Smarcel len = (*psapi_GetModuleFileNameExA) (current_process_handle, 487130803Smarcel DllHandle[i], 488130803Smarcel dll_name_ret, 489130803Smarcel MAX_PATH); 490130803Smarcel if (len == 0) 491130803Smarcel error ("Error getting dll name: %u\n", (unsigned) GetLastError ()); 492130803Smarcel 493130803Smarcel if ((DWORD) (mi.lpBaseOfDll) == BaseAddress) 494130803Smarcel return 1; 495130803Smarcel } 496130803Smarcel 497130803Smarcelfailed: 498130803Smarcel dll_name_ret[0] = '\0'; 499130803Smarcel return 0; 500130803Smarcel} 501130803Smarcel 502130803Smarcel/* Encapsulate the information required in a call to 503130803Smarcel symbol_file_add_args */ 504130803Smarcelstruct safe_symbol_file_add_args 505130803Smarcel{ 506130803Smarcel char *name; 507130803Smarcel int from_tty; 508130803Smarcel struct section_addr_info *addrs; 509130803Smarcel int mainline; 510130803Smarcel int flags; 511130803Smarcel struct ui_file *err, *out; 512130803Smarcel struct objfile *ret; 513130803Smarcel}; 514130803Smarcel 515130803Smarcel/* Maintain a linked list of "so" information. */ 516130803Smarcelstruct so_stuff 517130803Smarcel{ 518130803Smarcel struct so_stuff *next; 519130803Smarcel DWORD load_addr; 520130803Smarcel DWORD end_addr; 521130803Smarcel int loaded; 522130803Smarcel struct objfile *objfile; 523130803Smarcel char name[1]; 524130803Smarcel} solib_start, *solib_end; 525130803Smarcel 526130803Smarcel/* Call symbol_file_add with stderr redirected. We don't care if there 527130803Smarcel are errors. */ 528130803Smarcelstatic int 529130803Smarcelsafe_symbol_file_add_stub (void *argv) 530130803Smarcel{ 531130803Smarcel#define p ((struct safe_symbol_file_add_args *)argv) 532130803Smarcel struct so_stuff *so = &solib_start; 533130803Smarcel 534130803Smarcel while ((so = so->next)) 535130803Smarcel if (so->loaded && strcasecmp (so->name, p->name) == 0) 536130803Smarcel return 0; 537130803Smarcel p->ret = symbol_file_add (p->name, p->from_tty, p->addrs, p->mainline, p->flags); 538130803Smarcel return !!p->ret; 539130803Smarcel#undef p 540130803Smarcel} 541130803Smarcel 542130803Smarcel/* Restore gdb's stderr after calling symbol_file_add */ 543130803Smarcelstatic void 544130803Smarcelsafe_symbol_file_add_cleanup (void *p) 545130803Smarcel{ 546130803Smarcel#define sp ((struct safe_symbol_file_add_args *)p) 547130803Smarcel gdb_flush (gdb_stderr); 548130803Smarcel gdb_flush (gdb_stdout); 549130803Smarcel ui_file_delete (gdb_stderr); 550130803Smarcel ui_file_delete (gdb_stdout); 551130803Smarcel gdb_stderr = sp->err; 552130803Smarcel gdb_stdout = sp->out; 553130803Smarcel#undef sp 554130803Smarcel} 555130803Smarcel 556130803Smarcel/* symbol_file_add wrapper that prevents errors from being displayed. */ 557130803Smarcelstatic struct objfile * 558130803Smarcelsafe_symbol_file_add (char *name, int from_tty, 559130803Smarcel struct section_addr_info *addrs, 560130803Smarcel int mainline, int flags) 561130803Smarcel{ 562130803Smarcel struct safe_symbol_file_add_args p; 563130803Smarcel struct cleanup *cleanup; 564130803Smarcel 565130803Smarcel cleanup = make_cleanup (safe_symbol_file_add_cleanup, &p); 566130803Smarcel 567130803Smarcel p.err = gdb_stderr; 568130803Smarcel p.out = gdb_stdout; 569130803Smarcel gdb_flush (gdb_stderr); 570130803Smarcel gdb_flush (gdb_stdout); 571130803Smarcel gdb_stderr = ui_file_new (); 572130803Smarcel gdb_stdout = ui_file_new (); 573130803Smarcel p.name = name; 574130803Smarcel p.from_tty = from_tty; 575130803Smarcel p.addrs = addrs; 576130803Smarcel p.mainline = mainline; 577130803Smarcel p.flags = flags; 578130803Smarcel catch_errors (safe_symbol_file_add_stub, &p, "", RETURN_MASK_ERROR); 579130803Smarcel 580130803Smarcel do_cleanups (cleanup); 581130803Smarcel return p.ret; 582130803Smarcel} 583130803Smarcel 584130803Smarcel/* Remember the maximum DLL length for printing in info dll command. */ 585130803Smarcelint max_dll_name_len; 586130803Smarcel 587130803Smarcelstatic void 588130803Smarcelregister_loaded_dll (const char *name, DWORD load_addr) 589130803Smarcel{ 590130803Smarcel struct so_stuff *so; 591130803Smarcel char ppath[MAX_PATH + 1]; 592130803Smarcel char buf[MAX_PATH + 1]; 593130803Smarcel char cwd[MAX_PATH + 1]; 594130803Smarcel char *p; 595130803Smarcel WIN32_FIND_DATA w32_fd; 596130803Smarcel HANDLE h = FindFirstFile(name, &w32_fd); 597130803Smarcel MEMORY_BASIC_INFORMATION m; 598130803Smarcel size_t len; 599130803Smarcel 600130803Smarcel if (h == INVALID_HANDLE_VALUE) 601130803Smarcel strcpy (buf, name); 602130803Smarcel else 603130803Smarcel { 604130803Smarcel FindClose (h); 605130803Smarcel strcpy (buf, name); 606130803Smarcel if (GetCurrentDirectory (MAX_PATH + 1, cwd)) 607130803Smarcel { 608130803Smarcel p = strrchr (buf, '\\'); 609130803Smarcel if (p) 610130803Smarcel p[1] = '\0'; 611130803Smarcel SetCurrentDirectory (buf); 612130803Smarcel GetFullPathName (w32_fd.cFileName, MAX_PATH, buf, &p); 613130803Smarcel SetCurrentDirectory (cwd); 614130803Smarcel } 615130803Smarcel } 616130803Smarcel 617130803Smarcel cygwin_conv_to_posix_path (buf, ppath); 618130803Smarcel so = (struct so_stuff *) xmalloc (sizeof (struct so_stuff) + strlen (ppath) + 8 + 1); 619130803Smarcel so->loaded = 0; 620130803Smarcel so->load_addr = load_addr; 621130803Smarcel if (VirtualQueryEx (current_process_handle, (void *) load_addr, &m, 622130803Smarcel sizeof (m))) 623130803Smarcel so->end_addr = (DWORD) m.AllocationBase + m.RegionSize; 624130803Smarcel else 625130803Smarcel so->end_addr = load_addr + 0x2000; /* completely arbitrary */ 626130803Smarcel 627130803Smarcel so->next = NULL; 628130803Smarcel so->objfile = NULL; 629130803Smarcel strcpy (so->name, ppath); 630130803Smarcel 631130803Smarcel solib_end->next = so; 632130803Smarcel solib_end = so; 633130803Smarcel len = strlen (ppath); 634130803Smarcel if (len > max_dll_name_len) 635130803Smarcel max_dll_name_len = len; 636130803Smarcel} 637130803Smarcel 638130803Smarcelchar * 639130803Smarcelget_image_name (HANDLE h, void *address, int unicode) 640130803Smarcel{ 641130803Smarcel static char buf[(2 * MAX_PATH) + 1]; 642130803Smarcel DWORD size = unicode ? sizeof (WCHAR) : sizeof (char); 643130803Smarcel char *address_ptr; 644130803Smarcel int len = 0; 645130803Smarcel char b[2]; 646130803Smarcel DWORD done; 647130803Smarcel 648130803Smarcel /* Attempt to read the name of the dll that was detected. 649130803Smarcel This is documented to work only when actively debugging 650130803Smarcel a program. It will not work for attached processes. */ 651130803Smarcel if (address == NULL) 652130803Smarcel return NULL; 653130803Smarcel 654130803Smarcel /* See if we could read the address of a string, and that the 655130803Smarcel address isn't null. */ 656130803Smarcel if (!ReadProcessMemory (h, address, &address_ptr, sizeof (address_ptr), &done) 657130803Smarcel || done != sizeof (address_ptr) || !address_ptr) 658130803Smarcel return NULL; 659130803Smarcel 660130803Smarcel /* Find the length of the string */ 661130803Smarcel while (ReadProcessMemory (h, address_ptr + len++ * size, &b, size, &done) 662130803Smarcel && (b[0] != 0 || b[size - 1] != 0) && done == size) 663130803Smarcel continue; 664130803Smarcel 665130803Smarcel if (!unicode) 666130803Smarcel ReadProcessMemory (h, address_ptr, buf, len, &done); 667130803Smarcel else 668130803Smarcel { 669130803Smarcel WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR)); 670130803Smarcel ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR), 671130803Smarcel &done); 672130803Smarcel 673130803Smarcel WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, len, 0, 0); 674130803Smarcel } 675130803Smarcel 676130803Smarcel return buf; 677130803Smarcel} 678130803Smarcel 679130803Smarcel/* Wait for child to do something. Return pid of child, or -1 in case 680130803Smarcel of error; store status through argument pointer OURSTATUS. */ 681130803Smarcelstatic int 682130803Smarcelhandle_load_dll (void *dummy) 683130803Smarcel{ 684130803Smarcel LOAD_DLL_DEBUG_INFO *event = ¤t_event.u.LoadDll; 685130803Smarcel char dll_buf[MAX_PATH + 1]; 686130803Smarcel char *dll_name = NULL; 687130803Smarcel char *p; 688130803Smarcel 689130803Smarcel dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0'; 690130803Smarcel 691130803Smarcel if (!psapi_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf)) 692130803Smarcel dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0'; 693130803Smarcel 694130803Smarcel dll_name = dll_buf; 695130803Smarcel 696130803Smarcel if (*dll_name == '\0') 697130803Smarcel dll_name = get_image_name (current_process_handle, event->lpImageName, event->fUnicode); 698130803Smarcel if (!dll_name) 699130803Smarcel return 1; 700130803Smarcel 701130803Smarcel register_loaded_dll (dll_name, (DWORD) event->lpBaseOfDll + 0x1000); 702130803Smarcel 703130803Smarcel return 1; 704130803Smarcel} 705130803Smarcel 706130803Smarcelstatic int 707130803Smarcelhandle_unload_dll (void *dummy) 708130803Smarcel{ 709130803Smarcel DWORD lpBaseOfDll = (DWORD) current_event.u.UnloadDll.lpBaseOfDll + 0x1000; 710130803Smarcel struct so_stuff *so; 711130803Smarcel 712130803Smarcel for (so = &solib_start; so->next != NULL; so = so->next) 713130803Smarcel if (so->next->load_addr == lpBaseOfDll) 714130803Smarcel { 715130803Smarcel struct so_stuff *sodel = so->next; 716130803Smarcel so->next = sodel->next; 717130803Smarcel if (!so->next) 718130803Smarcel solib_end = so; 719130803Smarcel if (sodel->objfile) 720130803Smarcel free_objfile (sodel->objfile); 721130803Smarcel xfree(sodel); 722130803Smarcel return 1; 723130803Smarcel } 724130803Smarcel error ("Error: dll starting at 0x%lx not found.\n", (DWORD) lpBaseOfDll); 725130803Smarcel 726130803Smarcel return 0; 727130803Smarcel} 728130803Smarcel 729130803Smarcelchar * 730130803Smarcelsolib_address (CORE_ADDR address) 731130803Smarcel{ 732130803Smarcel struct so_stuff *so; 733130803Smarcel for (so = &solib_start; so->next != NULL; so = so->next) 734130803Smarcel if (address >= so->load_addr && address <= so->end_addr) 735130803Smarcel return so->name; 736130803Smarcel return NULL; 737130803Smarcel} 738130803Smarcel 739130803Smarcel/* Return name of last loaded DLL. */ 740130803Smarcelchar * 741130803Smarcelchild_solib_loaded_library_pathname (int pid) 742130803Smarcel{ 743130803Smarcel return !solib_end || !solib_end->name[0] ? NULL : solib_end->name; 744130803Smarcel} 745130803Smarcel 746130803Smarcel/* Clear list of loaded DLLs. */ 747130803Smarcelvoid 748130803Smarcelchild_clear_solibs (void) 749130803Smarcel{ 750130803Smarcel struct so_stuff *so, *so1 = solib_start.next; 751130803Smarcel 752130803Smarcel while ((so = so1) != NULL) 753130803Smarcel { 754130803Smarcel so1 = so->next; 755130803Smarcel xfree (so); 756130803Smarcel } 757130803Smarcel 758130803Smarcel solib_start.next = NULL; 759130803Smarcel solib_start.objfile = NULL; 760130803Smarcel solib_end = &solib_start; 761130803Smarcel max_dll_name_len = sizeof ("DLL Name") - 1; 762130803Smarcel} 763130803Smarcel 764130803Smarcel/* Get the loaded address of all sections, given that .text was loaded 765130803Smarcel at text_load. Assumes that all sections are subject to the same 766130803Smarcel relocation offset. Returns NULL if problems occur or if the 767130803Smarcel sections were not relocated. */ 768130803Smarcel 769130803Smarcelstatic struct section_addr_info * 770130803Smarcelget_relocated_section_addrs (bfd *abfd, CORE_ADDR text_load) 771130803Smarcel{ 772130803Smarcel struct section_addr_info *result = NULL; 773130803Smarcel int section_count = bfd_count_sections (abfd); 774130803Smarcel asection *text_section = bfd_get_section_by_name (abfd, ".text"); 775130803Smarcel CORE_ADDR text_vma; 776130803Smarcel 777130803Smarcel if (!text_section) 778130803Smarcel { 779130803Smarcel /* Couldn't get the .text section. Weird. */ 780130803Smarcel } 781130803Smarcel 782130803Smarcel else if (text_load == (text_vma = bfd_get_section_vma (abfd, text_section))) 783130803Smarcel { 784130803Smarcel /* DLL wasn't relocated. */ 785130803Smarcel } 786130803Smarcel 787130803Smarcel else 788130803Smarcel { 789130803Smarcel /* Figure out all sections' loaded addresses. The offset here is 790130803Smarcel such that taking a bfd_get_section_vma() result and adding 791130803Smarcel offset will give the real load address of the section. */ 792130803Smarcel 793130803Smarcel CORE_ADDR offset = text_load - text_vma; 794130803Smarcel 795130803Smarcel struct section_table *table_start = NULL; 796130803Smarcel struct section_table *table_end = NULL; 797130803Smarcel struct section_table *iter = NULL; 798130803Smarcel 799130803Smarcel build_section_table (abfd, &table_start, &table_end); 800130803Smarcel 801130803Smarcel for (iter = table_start; iter < table_end; ++iter) 802130803Smarcel { 803130803Smarcel /* Relocated addresses. */ 804130803Smarcel iter->addr += offset; 805130803Smarcel iter->endaddr += offset; 806130803Smarcel } 807130803Smarcel 808130803Smarcel result = build_section_addr_info_from_section_table (table_start, 809130803Smarcel table_end); 810130803Smarcel 811130803Smarcel xfree (table_start); 812130803Smarcel } 813130803Smarcel 814130803Smarcel return result; 815130803Smarcel} 816130803Smarcel 817130803Smarcel/* Add DLL symbol information. */ 818130803Smarcelstatic struct objfile * 819130803Smarcelsolib_symbols_add (char *name, int from_tty, CORE_ADDR load_addr) 820130803Smarcel{ 821130803Smarcel struct section_addr_info *addrs = NULL; 822130803Smarcel static struct objfile *result = NULL; 823130803Smarcel bfd *abfd = NULL; 824130803Smarcel 825130803Smarcel /* The symbols in a dll are offset by 0x1000, which is the 826130803Smarcel the offset from 0 of the first byte in an image - because 827130803Smarcel of the file header and the section alignment. */ 828130803Smarcel 829130803Smarcel if (!name || !name[0]) 830130803Smarcel return NULL; 831130803Smarcel 832130803Smarcel abfd = bfd_openr (name, "pei-i386"); 833130803Smarcel 834130803Smarcel if (!abfd) 835130803Smarcel { 836130803Smarcel /* pei failed - try pe */ 837130803Smarcel abfd = bfd_openr (name, "pe-i386"); 838130803Smarcel } 839130803Smarcel 840130803Smarcel if (abfd) 841130803Smarcel { 842130803Smarcel if (bfd_check_format (abfd, bfd_object)) 843130803Smarcel { 844130803Smarcel addrs = get_relocated_section_addrs (abfd, load_addr); 845130803Smarcel } 846130803Smarcel 847130803Smarcel bfd_close (abfd); 848130803Smarcel } 849130803Smarcel 850130803Smarcel if (addrs) 851130803Smarcel { 852130803Smarcel result = safe_symbol_file_add (name, from_tty, addrs, 0, OBJF_SHARED); 853130803Smarcel free_section_addr_info (addrs); 854130803Smarcel } 855130803Smarcel else 856130803Smarcel { 857130803Smarcel /* Fallback on handling just the .text section. */ 858130803Smarcel struct cleanup *my_cleanups; 859130803Smarcel 860130803Smarcel addrs = alloc_section_addr_info (1); 861130803Smarcel my_cleanups = make_cleanup (xfree, addrs); 862130803Smarcel addrs->other[0].name = ".text"; 863130803Smarcel addrs->other[0].addr = load_addr; 864130803Smarcel 865130803Smarcel result = safe_symbol_file_add (name, from_tty, addrs, 0, OBJF_SHARED); 866130803Smarcel do_cleanups (my_cleanups); 867130803Smarcel } 868130803Smarcel 869130803Smarcel return result; 870130803Smarcel} 871130803Smarcel 872130803Smarcel/* Load DLL symbol info. */ 873130803Smarcelvoid 874130803Smarceldll_symbol_command (char *args, int from_tty) 875130803Smarcel{ 876130803Smarcel int n; 877130803Smarcel dont_repeat (); 878130803Smarcel 879130803Smarcel if (args == NULL) 880130803Smarcel error ("dll-symbols requires a file name"); 881130803Smarcel 882130803Smarcel n = strlen (args); 883130803Smarcel if (n > 4 && strcasecmp (args + n - 4, ".dll") != 0) 884130803Smarcel { 885130803Smarcel char *newargs = (char *) alloca (n + 4 + 1); 886130803Smarcel strcpy (newargs, args); 887130803Smarcel strcat (newargs, ".dll"); 888130803Smarcel args = newargs; 889130803Smarcel } 890130803Smarcel 891130803Smarcel safe_symbol_file_add (args, from_tty, NULL, 0, OBJF_SHARED | OBJF_USERLOADED); 892130803Smarcel} 893130803Smarcel 894130803Smarcel/* List currently loaded DLLs. */ 895130803Smarcelvoid 896130803Smarcelinfo_dll_command (char *ignore, int from_tty) 897130803Smarcel{ 898130803Smarcel struct so_stuff *so = &solib_start; 899130803Smarcel 900130803Smarcel if (!so->next) 901130803Smarcel return; 902130803Smarcel 903130803Smarcel printf_filtered ("%*s Load Address\n", -max_dll_name_len, "DLL Name"); 904130803Smarcel while ((so = so->next) != NULL) 905130803Smarcel printf_filtered ("%*s %08lx\n", -max_dll_name_len, so->name, so->load_addr); 906130803Smarcel 907130803Smarcel return; 908130803Smarcel} 909130803Smarcel 910130803Smarcel/* Handle DEBUG_STRING output from child process. 911130803Smarcel Cygwin prepends its messages with a "cygwin:". Interpret this as 912130803Smarcel a Cygwin signal. Otherwise just print the string as a warning. */ 913130803Smarcelstatic int 914130803Smarcelhandle_output_debug_string (struct target_waitstatus *ourstatus) 915130803Smarcel{ 916130803Smarcel char *s; 917130803Smarcel int gotasig = FALSE; 918130803Smarcel 919130803Smarcel if (!target_read_string 920130803Smarcel ((CORE_ADDR) current_event.u.DebugString.lpDebugStringData, &s, 1024, 0) 921130803Smarcel || !s || !*s) 922130803Smarcel return gotasig; 923130803Smarcel 924130803Smarcel if (strncmp (s, CYGWIN_SIGNAL_STRING, sizeof (CYGWIN_SIGNAL_STRING) - 1) != 0) 925130803Smarcel { 926130803Smarcel if (strncmp (s, "cYg", 3) != 0) 927130803Smarcel warning ("%s", s); 928130803Smarcel } 929130803Smarcel else 930130803Smarcel { 931130803Smarcel char *p; 932130803Smarcel int sig = strtol (s + sizeof (CYGWIN_SIGNAL_STRING) - 1, &p, 0); 933130803Smarcel gotasig = target_signal_from_host (sig); 934130803Smarcel ourstatus->value.sig = gotasig; 935130803Smarcel if (gotasig) 936130803Smarcel ourstatus->kind = TARGET_WAITKIND_STOPPED; 937130803Smarcel } 938130803Smarcel 939130803Smarcel xfree (s); 940130803Smarcel return gotasig; 941130803Smarcel} 942130803Smarcel 943130803Smarcelstatic int 944130803Smarceldisplay_selector (HANDLE thread, DWORD sel) 945130803Smarcel{ 946130803Smarcel LDT_ENTRY info; 947130803Smarcel if (GetThreadSelectorEntry (thread, sel, &info)) 948130803Smarcel { 949130803Smarcel int base, limit; 950130803Smarcel printf_filtered ("0x%03lx: ", sel); 951130803Smarcel if (!info.HighWord.Bits.Pres) 952130803Smarcel { 953130803Smarcel puts_filtered ("Segment not present\n"); 954130803Smarcel return 0; 955130803Smarcel } 956130803Smarcel base = (info.HighWord.Bits.BaseHi << 24) + 957130803Smarcel (info.HighWord.Bits.BaseMid << 16) 958130803Smarcel + info.BaseLow; 959130803Smarcel limit = (info.HighWord.Bits.LimitHi << 16) + info.LimitLow; 960130803Smarcel if (info.HighWord.Bits.Granularity) 961130803Smarcel limit = (limit << 12) | 0xfff; 962130803Smarcel printf_filtered ("base=0x%08x limit=0x%08x", base, limit); 963130803Smarcel if (info.HighWord.Bits.Default_Big) 964130803Smarcel puts_filtered(" 32-bit "); 965130803Smarcel else 966130803Smarcel puts_filtered(" 16-bit "); 967130803Smarcel switch ((info.HighWord.Bits.Type & 0xf) >> 1) 968130803Smarcel { 969130803Smarcel case 0: 970130803Smarcel puts_filtered ("Data (Read-Only, Exp-up"); 971130803Smarcel break; 972130803Smarcel case 1: 973130803Smarcel puts_filtered ("Data (Read/Write, Exp-up"); 974130803Smarcel break; 975130803Smarcel case 2: 976130803Smarcel puts_filtered ("Unused segment ("); 977130803Smarcel break; 978130803Smarcel case 3: 979130803Smarcel puts_filtered ("Data (Read/Write, Exp-down"); 980130803Smarcel break; 981130803Smarcel case 4: 982130803Smarcel puts_filtered ("Code (Exec-Only, N.Conf"); 983130803Smarcel break; 984130803Smarcel case 5: 985130803Smarcel puts_filtered ("Code (Exec/Read, N.Conf"); 986130803Smarcel break; 987130803Smarcel case 6: 988130803Smarcel puts_filtered ("Code (Exec-Only, Conf"); 989130803Smarcel break; 990130803Smarcel case 7: 991130803Smarcel puts_filtered ("Code (Exec/Read, Conf"); 992130803Smarcel break; 993130803Smarcel default: 994130803Smarcel printf_filtered ("Unknown type 0x%x",info.HighWord.Bits.Type); 995130803Smarcel } 996130803Smarcel if ((info.HighWord.Bits.Type & 0x1) == 0) 997130803Smarcel puts_filtered(", N.Acc"); 998130803Smarcel puts_filtered (")\n"); 999130803Smarcel if ((info.HighWord.Bits.Type & 0x10) == 0) 1000130803Smarcel puts_filtered("System selector "); 1001130803Smarcel printf_filtered ("Priviledge level = %d. ", info.HighWord.Bits.Dpl); 1002130803Smarcel if (info.HighWord.Bits.Granularity) 1003130803Smarcel puts_filtered ("Page granular.\n"); 1004130803Smarcel else 1005130803Smarcel puts_filtered ("Byte granular.\n"); 1006130803Smarcel return 1; 1007130803Smarcel } 1008130803Smarcel else 1009130803Smarcel { 1010130803Smarcel printf_filtered ("Invalid selector 0x%lx.\n",sel); 1011130803Smarcel return 0; 1012130803Smarcel } 1013130803Smarcel} 1014130803Smarcel 1015130803Smarcelstatic void 1016130803Smarceldisplay_selectors (char * args, int from_tty) 1017130803Smarcel{ 1018130803Smarcel if (!current_thread) 1019130803Smarcel { 1020130803Smarcel puts_filtered ("Impossible to display selectors now.\n"); 1021130803Smarcel return; 1022130803Smarcel } 1023130803Smarcel if (!args) 1024130803Smarcel { 1025130803Smarcel 1026130803Smarcel puts_filtered ("Selector $cs\n"); 1027130803Smarcel display_selector (current_thread->h, 1028130803Smarcel current_thread->context.SegCs); 1029130803Smarcel puts_filtered ("Selector $ds\n"); 1030130803Smarcel display_selector (current_thread->h, 1031130803Smarcel current_thread->context.SegDs); 1032130803Smarcel puts_filtered ("Selector $es\n"); 1033130803Smarcel display_selector (current_thread->h, 1034130803Smarcel current_thread->context.SegEs); 1035130803Smarcel puts_filtered ("Selector $ss\n"); 1036130803Smarcel display_selector (current_thread->h, 1037130803Smarcel current_thread->context.SegSs); 1038130803Smarcel puts_filtered ("Selector $fs\n"); 1039130803Smarcel display_selector (current_thread->h, 1040130803Smarcel current_thread->context.SegFs); 1041130803Smarcel puts_filtered ("Selector $gs\n"); 1042130803Smarcel display_selector (current_thread->h, 1043130803Smarcel current_thread->context.SegGs); 1044130803Smarcel } 1045130803Smarcel else 1046130803Smarcel { 1047130803Smarcel int sel; 1048130803Smarcel sel = parse_and_eval_long (args); 1049130803Smarcel printf_filtered ("Selector \"%s\"\n",args); 1050130803Smarcel display_selector (current_thread->h, sel); 1051130803Smarcel } 1052130803Smarcel} 1053130803Smarcel 1054130803Smarcelstatic struct cmd_list_element *info_w32_cmdlist = NULL; 1055130803Smarcel 1056130803Smarcelstatic void 1057130803Smarcelinfo_w32_command (char *args, int from_tty) 1058130803Smarcel{ 1059130803Smarcel help_list (info_w32_cmdlist, "info w32 ", class_info, gdb_stdout); 1060130803Smarcel} 1061130803Smarcel 1062130803Smarcel 1063130803Smarcel#define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \ 1064130803Smarcel printf_unfiltered ("gdb: Target exception %s at 0x%08lx\n", x, \ 1065130803Smarcel (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress) 1066130803Smarcel 1067130803Smarcelstatic int 1068130803Smarcelhandle_exception (struct target_waitstatus *ourstatus) 1069130803Smarcel{ 1070130803Smarcel thread_info *th; 1071130803Smarcel DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode; 1072130803Smarcel 1073130803Smarcel ourstatus->kind = TARGET_WAITKIND_STOPPED; 1074130803Smarcel 1075130803Smarcel /* Record the context of the current thread */ 1076130803Smarcel th = thread_rec (current_event.dwThreadId, -1); 1077130803Smarcel 1078130803Smarcel switch (code) 1079130803Smarcel { 1080130803Smarcel case EXCEPTION_ACCESS_VIOLATION: 1081130803Smarcel DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION"); 1082130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_SEGV; 1083130803Smarcel break; 1084130803Smarcel case STATUS_STACK_OVERFLOW: 1085130803Smarcel DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW"); 1086130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_SEGV; 1087130803Smarcel break; 1088130803Smarcel case STATUS_FLOAT_DENORMAL_OPERAND: 1089130803Smarcel DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND"); 1090130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_FPE; 1091130803Smarcel break; 1092130803Smarcel case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: 1093130803Smarcel DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED"); 1094130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_FPE; 1095130803Smarcel break; 1096130803Smarcel case STATUS_FLOAT_INEXACT_RESULT: 1097130803Smarcel DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT"); 1098130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_FPE; 1099130803Smarcel break; 1100130803Smarcel case STATUS_FLOAT_INVALID_OPERATION: 1101130803Smarcel DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION"); 1102130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_FPE; 1103130803Smarcel break; 1104130803Smarcel case STATUS_FLOAT_OVERFLOW: 1105130803Smarcel DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW"); 1106130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_FPE; 1107130803Smarcel break; 1108130803Smarcel case STATUS_FLOAT_STACK_CHECK: 1109130803Smarcel DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK"); 1110130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_FPE; 1111130803Smarcel break; 1112130803Smarcel case STATUS_FLOAT_UNDERFLOW: 1113130803Smarcel DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW"); 1114130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_FPE; 1115130803Smarcel break; 1116130803Smarcel case STATUS_FLOAT_DIVIDE_BY_ZERO: 1117130803Smarcel DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO"); 1118130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_FPE; 1119130803Smarcel break; 1120130803Smarcel case STATUS_INTEGER_DIVIDE_BY_ZERO: 1121130803Smarcel DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO"); 1122130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_FPE; 1123130803Smarcel break; 1124130803Smarcel case STATUS_INTEGER_OVERFLOW: 1125130803Smarcel DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW"); 1126130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_FPE; 1127130803Smarcel break; 1128130803Smarcel case EXCEPTION_BREAKPOINT: 1129130803Smarcel DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT"); 1130130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_TRAP; 1131130803Smarcel break; 1132130803Smarcel case DBG_CONTROL_C: 1133130803Smarcel DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C"); 1134130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_INT; 1135130803Smarcel break; 1136130803Smarcel case DBG_CONTROL_BREAK: 1137130803Smarcel DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK"); 1138130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_INT; 1139130803Smarcel break; 1140130803Smarcel case EXCEPTION_SINGLE_STEP: 1141130803Smarcel DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP"); 1142130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_TRAP; 1143130803Smarcel break; 1144130803Smarcel case EXCEPTION_ILLEGAL_INSTRUCTION: 1145130803Smarcel DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION"); 1146130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_ILL; 1147130803Smarcel break; 1148130803Smarcel case EXCEPTION_PRIV_INSTRUCTION: 1149130803Smarcel DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION"); 1150130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_ILL; 1151130803Smarcel break; 1152130803Smarcel case EXCEPTION_NONCONTINUABLE_EXCEPTION: 1153130803Smarcel DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION"); 1154130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_ILL; 1155130803Smarcel break; 1156130803Smarcel default: 1157130803Smarcel if (current_event.u.Exception.dwFirstChance) 1158130803Smarcel return 0; 1159130803Smarcel printf_unfiltered ("gdb: unknown target exception 0x%08lx at 0x%08lx\n", 1160130803Smarcel current_event.u.Exception.ExceptionRecord.ExceptionCode, 1161130803Smarcel (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress); 1162130803Smarcel ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN; 1163130803Smarcel break; 1164130803Smarcel } 1165130803Smarcel exception_count++; 1166130803Smarcel last_sig = ourstatus->value.sig; 1167130803Smarcel return 1; 1168130803Smarcel} 1169130803Smarcel 1170130803Smarcel/* Resume all artificially suspended threads if we are continuing 1171130803Smarcel execution */ 1172130803Smarcelstatic BOOL 1173130803Smarcelchild_continue (DWORD continue_status, int id) 1174130803Smarcel{ 1175130803Smarcel int i; 1176130803Smarcel thread_info *th; 1177130803Smarcel BOOL res; 1178130803Smarcel 1179130803Smarcel DEBUG_EVENTS (("ContinueDebugEvent (cpid=%ld, ctid=%ld, %s);\n", 1180130803Smarcel current_event.dwProcessId, current_event.dwThreadId, 1181130803Smarcel continue_status == DBG_CONTINUE ? 1182130803Smarcel "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED")); 1183130803Smarcel res = ContinueDebugEvent (current_event.dwProcessId, 1184130803Smarcel current_event.dwThreadId, 1185130803Smarcel continue_status); 1186130803Smarcel continue_status = 0; 1187130803Smarcel if (res) 1188130803Smarcel for (th = &thread_head; (th = th->next) != NULL;) 1189130803Smarcel if (((id == -1) || (id == (int) th->id)) && th->suspend_count) 1190130803Smarcel { 1191130803Smarcel 1192130803Smarcel for (i = 0; i < th->suspend_count; i++) 1193130803Smarcel (void) ResumeThread (th->h); 1194130803Smarcel th->suspend_count = 0; 1195130803Smarcel if (debug_registers_changed) 1196130803Smarcel { 1197130803Smarcel /* Only change the value of the debug registers */ 1198130803Smarcel th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS; 1199130803Smarcel th->context.Dr0 = dr[0]; 1200130803Smarcel th->context.Dr1 = dr[1]; 1201130803Smarcel th->context.Dr2 = dr[2]; 1202130803Smarcel th->context.Dr3 = dr[3]; 1203130803Smarcel /* th->context.Dr6 = dr[6]; 1204130803Smarcel FIXME: should we set dr6 also ?? */ 1205130803Smarcel th->context.Dr7 = dr[7]; 1206130803Smarcel CHECK (SetThreadContext (th->h, &th->context)); 1207130803Smarcel th->context.ContextFlags = 0; 1208130803Smarcel } 1209130803Smarcel } 1210130803Smarcel 1211130803Smarcel debug_registers_changed = 0; 1212130803Smarcel return res; 1213130803Smarcel} 1214130803Smarcel 1215130803Smarcel/* Called in pathological case where Windows fails to send a 1216130803Smarcel CREATE_PROCESS_DEBUG_EVENT after an attach. */ 1217130803SmarcelDWORD 1218130803Smarcelfake_create_process (void) 1219130803Smarcel{ 1220130803Smarcel current_process_handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE, 1221130803Smarcel current_event.dwProcessId); 1222130803Smarcel main_thread_id = current_event.dwThreadId; 1223130803Smarcel current_thread = child_add_thread (main_thread_id, 1224130803Smarcel current_event.u.CreateThread.hThread); 1225130803Smarcel return main_thread_id; 1226130803Smarcel} 1227130803Smarcel 1228130803Smarcel/* Get the next event from the child. Return 1 if the event requires 1229130803Smarcel handling by WFI (or whatever). 1230130803Smarcel */ 1231130803Smarcelstatic int 1232130803Smarcelget_child_debug_event (int pid, struct target_waitstatus *ourstatus) 1233130803Smarcel{ 1234130803Smarcel BOOL debug_event; 1235130803Smarcel DWORD continue_status, event_code; 1236130803Smarcel thread_info *th; 1237130803Smarcel static thread_info dummy_thread_info; 1238130803Smarcel int retval = 0; 1239130803Smarcel 1240130803Smarcel last_sig = TARGET_SIGNAL_0; 1241130803Smarcel 1242130803Smarcel if (!(debug_event = WaitForDebugEvent (¤t_event, 1000))) 1243130803Smarcel goto out; 1244130803Smarcel 1245130803Smarcel event_count++; 1246130803Smarcel continue_status = DBG_CONTINUE; 1247130803Smarcel 1248130803Smarcel event_code = current_event.dwDebugEventCode; 1249130803Smarcel ourstatus->kind = TARGET_WAITKIND_SPURIOUS; 1250130803Smarcel th = NULL; 1251130803Smarcel 1252130803Smarcel switch (event_code) 1253130803Smarcel { 1254130803Smarcel case CREATE_THREAD_DEBUG_EVENT: 1255130803Smarcel DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n", 1256130803Smarcel (unsigned) current_event.dwProcessId, 1257130803Smarcel (unsigned) current_event.dwThreadId, 1258130803Smarcel "CREATE_THREAD_DEBUG_EVENT")); 1259130803Smarcel if (saw_create != 1) 1260130803Smarcel { 1261130803Smarcel if (!saw_create && attach_flag) 1262130803Smarcel { 1263130803Smarcel /* Kludge around a Windows bug where first event is a create 1264130803Smarcel thread event. Caused when attached process does not have 1265130803Smarcel a main thread. */ 1266130803Smarcel retval = ourstatus->value.related_pid = fake_create_process (); 1267130803Smarcel saw_create++; 1268130803Smarcel } 1269130803Smarcel break; 1270130803Smarcel } 1271130803Smarcel /* Record the existence of this thread */ 1272130803Smarcel th = child_add_thread (current_event.dwThreadId, 1273130803Smarcel current_event.u.CreateThread.hThread); 1274130803Smarcel if (info_verbose) 1275130803Smarcel printf_unfiltered ("[New %s]\n", 1276130803Smarcel target_pid_to_str ( 1277130803Smarcel pid_to_ptid (current_event.dwThreadId))); 1278130803Smarcel retval = current_event.dwThreadId; 1279130803Smarcel break; 1280130803Smarcel 1281130803Smarcel case EXIT_THREAD_DEBUG_EVENT: 1282130803Smarcel DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", 1283130803Smarcel (unsigned) current_event.dwProcessId, 1284130803Smarcel (unsigned) current_event.dwThreadId, 1285130803Smarcel "EXIT_THREAD_DEBUG_EVENT")); 1286130803Smarcel if (current_event.dwThreadId != main_thread_id) 1287130803Smarcel { 1288130803Smarcel child_delete_thread (current_event.dwThreadId); 1289130803Smarcel th = &dummy_thread_info; 1290130803Smarcel } 1291130803Smarcel break; 1292130803Smarcel 1293130803Smarcel case CREATE_PROCESS_DEBUG_EVENT: 1294130803Smarcel DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", 1295130803Smarcel (unsigned) current_event.dwProcessId, 1296130803Smarcel (unsigned) current_event.dwThreadId, 1297130803Smarcel "CREATE_PROCESS_DEBUG_EVENT")); 1298130803Smarcel CloseHandle (current_event.u.CreateProcessInfo.hFile); 1299130803Smarcel if (++saw_create != 1) 1300130803Smarcel { 1301130803Smarcel CloseHandle (current_event.u.CreateProcessInfo.hProcess); 1302130803Smarcel break; 1303130803Smarcel } 1304130803Smarcel 1305130803Smarcel current_process_handle = current_event.u.CreateProcessInfo.hProcess; 1306130803Smarcel if (main_thread_id) 1307130803Smarcel child_delete_thread (main_thread_id); 1308130803Smarcel main_thread_id = current_event.dwThreadId; 1309130803Smarcel /* Add the main thread */ 1310130803Smarcel th = child_add_thread (main_thread_id, 1311130803Smarcel current_event.u.CreateProcessInfo.hThread); 1312130803Smarcel retval = ourstatus->value.related_pid = current_event.dwThreadId; 1313130803Smarcel break; 1314130803Smarcel 1315130803Smarcel case EXIT_PROCESS_DEBUG_EVENT: 1316130803Smarcel DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", 1317130803Smarcel (unsigned) current_event.dwProcessId, 1318130803Smarcel (unsigned) current_event.dwThreadId, 1319130803Smarcel "EXIT_PROCESS_DEBUG_EVENT")); 1320130803Smarcel if (saw_create != 1) 1321130803Smarcel break; 1322130803Smarcel ourstatus->kind = TARGET_WAITKIND_EXITED; 1323130803Smarcel ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode; 1324130803Smarcel CloseHandle (current_process_handle); 1325130803Smarcel retval = main_thread_id; 1326130803Smarcel break; 1327130803Smarcel 1328130803Smarcel case LOAD_DLL_DEBUG_EVENT: 1329130803Smarcel DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", 1330130803Smarcel (unsigned) current_event.dwProcessId, 1331130803Smarcel (unsigned) current_event.dwThreadId, 1332130803Smarcel "LOAD_DLL_DEBUG_EVENT")); 1333130803Smarcel CloseHandle (current_event.u.LoadDll.hFile); 1334130803Smarcel if (saw_create != 1) 1335130803Smarcel break; 1336130803Smarcel catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL); 1337130803Smarcel registers_changed (); /* mark all regs invalid */ 1338130803Smarcel ourstatus->kind = TARGET_WAITKIND_LOADED; 1339130803Smarcel ourstatus->value.integer = 0; 1340130803Smarcel retval = main_thread_id; 1341130803Smarcel re_enable_breakpoints_in_shlibs (); 1342130803Smarcel break; 1343130803Smarcel 1344130803Smarcel case UNLOAD_DLL_DEBUG_EVENT: 1345130803Smarcel DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", 1346130803Smarcel (unsigned) current_event.dwProcessId, 1347130803Smarcel (unsigned) current_event.dwThreadId, 1348130803Smarcel "UNLOAD_DLL_DEBUG_EVENT")); 1349130803Smarcel if (saw_create != 1) 1350130803Smarcel break; 1351130803Smarcel catch_errors (handle_unload_dll, NULL, (char *) "", RETURN_MASK_ALL); 1352130803Smarcel registers_changed (); /* mark all regs invalid */ 1353130803Smarcel /* ourstatus->kind = TARGET_WAITKIND_UNLOADED; 1354130803Smarcel does not exist yet. */ 1355130803Smarcel break; 1356130803Smarcel 1357130803Smarcel case EXCEPTION_DEBUG_EVENT: 1358130803Smarcel DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", 1359130803Smarcel (unsigned) current_event.dwProcessId, 1360130803Smarcel (unsigned) current_event.dwThreadId, 1361130803Smarcel "EXCEPTION_DEBUG_EVENT")); 1362130803Smarcel if (saw_create != 1) 1363130803Smarcel break; 1364130803Smarcel if (handle_exception (ourstatus)) 1365130803Smarcel retval = current_event.dwThreadId; 1366130803Smarcel break; 1367130803Smarcel 1368130803Smarcel case OUTPUT_DEBUG_STRING_EVENT: /* message from the kernel */ 1369130803Smarcel DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", 1370130803Smarcel (unsigned) current_event.dwProcessId, 1371130803Smarcel (unsigned) current_event.dwThreadId, 1372130803Smarcel "OUTPUT_DEBUG_STRING_EVENT")); 1373130803Smarcel if (saw_create != 1) 1374130803Smarcel break; 1375130803Smarcel if (handle_output_debug_string (ourstatus)) 1376130803Smarcel retval = main_thread_id; 1377130803Smarcel break; 1378130803Smarcel 1379130803Smarcel default: 1380130803Smarcel if (saw_create != 1) 1381130803Smarcel break; 1382130803Smarcel printf_unfiltered ("gdb: kernel event for pid=%ld tid=%ld\n", 1383130803Smarcel (DWORD) current_event.dwProcessId, 1384130803Smarcel (DWORD) current_event.dwThreadId); 1385130803Smarcel printf_unfiltered (" unknown event code %ld\n", 1386130803Smarcel current_event.dwDebugEventCode); 1387130803Smarcel break; 1388130803Smarcel } 1389130803Smarcel 1390130803Smarcel if (!retval || saw_create != 1) 1391130803Smarcel CHECK (child_continue (continue_status, -1)); 1392130803Smarcel else 1393130803Smarcel { 1394130803Smarcel inferior_ptid = pid_to_ptid (retval); 1395130803Smarcel current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE); 1396130803Smarcel } 1397130803Smarcel 1398130803Smarcelout: 1399130803Smarcel return retval; 1400130803Smarcel} 1401130803Smarcel 1402130803Smarcel/* Wait for interesting events to occur in the target process. */ 1403130803Smarcelstatic ptid_t 1404130803Smarcelchild_wait (ptid_t ptid, struct target_waitstatus *ourstatus) 1405130803Smarcel{ 1406130803Smarcel int pid = PIDGET (ptid); 1407130803Smarcel 1408130803Smarcel /* We loop when we get a non-standard exception rather than return 1409130803Smarcel with a SPURIOUS because resume can try and step or modify things, 1410130803Smarcel which needs a current_thread->h. But some of these exceptions mark 1411130803Smarcel the birth or death of threads, which mean that the current thread 1412130803Smarcel isn't necessarily what you think it is. */ 1413130803Smarcel 1414130803Smarcel while (1) 1415130803Smarcel { 1416130803Smarcel int retval = get_child_debug_event (pid, ourstatus); 1417130803Smarcel if (retval) 1418130803Smarcel return pid_to_ptid (retval); 1419130803Smarcel else 1420130803Smarcel { 1421130803Smarcel int detach = 0; 1422130803Smarcel 1423130803Smarcel if (ui_loop_hook != NULL) 1424130803Smarcel detach = ui_loop_hook (0); 1425130803Smarcel 1426130803Smarcel if (detach) 1427130803Smarcel child_kill_inferior (); 1428130803Smarcel } 1429130803Smarcel } 1430130803Smarcel} 1431130803Smarcel 1432130803Smarcelstatic void 1433130803Smarceldo_initial_child_stuff (DWORD pid) 1434130803Smarcel{ 1435130803Smarcel extern int stop_after_trap; 1436130803Smarcel int i; 1437130803Smarcel 1438130803Smarcel last_sig = TARGET_SIGNAL_0; 1439130803Smarcel event_count = 0; 1440130803Smarcel exception_count = 0; 1441130803Smarcel debug_registers_changed = 0; 1442130803Smarcel debug_registers_used = 0; 1443130803Smarcel for (i = 0; i < sizeof (dr) / sizeof (dr[0]); i++) 1444130803Smarcel dr[i] = 0; 1445130803Smarcel current_event.dwProcessId = pid; 1446130803Smarcel memset (¤t_event, 0, sizeof (current_event)); 1447130803Smarcel push_target (&child_ops); 1448130803Smarcel child_init_thread_list (); 1449130803Smarcel disable_breakpoints_in_shlibs (1); 1450130803Smarcel child_clear_solibs (); 1451130803Smarcel clear_proceed_status (); 1452130803Smarcel init_wait_for_inferior (); 1453130803Smarcel 1454130803Smarcel target_terminal_init (); 1455130803Smarcel target_terminal_inferior (); 1456130803Smarcel 1457130803Smarcel while (1) 1458130803Smarcel { 1459130803Smarcel stop_after_trap = 1; 1460130803Smarcel wait_for_inferior (); 1461130803Smarcel if (stop_signal != TARGET_SIGNAL_TRAP) 1462130803Smarcel resume (0, stop_signal); 1463130803Smarcel else 1464130803Smarcel break; 1465130803Smarcel } 1466130803Smarcel stop_after_trap = 0; 1467130803Smarcel return; 1468130803Smarcel} 1469130803Smarcel 1470130803Smarcel/* Since Windows XP, detaching from a process is supported by Windows. 1471130803Smarcel The following code tries loading the appropriate functions dynamically. 1472130803Smarcel If loading these functions succeeds use them to actually detach from 1473130803Smarcel the inferior process, otherwise behave as usual, pretending that 1474130803Smarcel detach has worked. */ 1475130803Smarcelstatic BOOL WINAPI (*DebugSetProcessKillOnExit)(BOOL); 1476130803Smarcelstatic BOOL WINAPI (*DebugActiveProcessStop)(DWORD); 1477130803Smarcel 1478130803Smarcelstatic int 1479130803Smarcelhas_detach_ability (void) 1480130803Smarcel{ 1481130803Smarcel static HMODULE kernel32 = NULL; 1482130803Smarcel 1483130803Smarcel if (!kernel32) 1484130803Smarcel kernel32 = LoadLibrary ("kernel32.dll"); 1485130803Smarcel if (kernel32) 1486130803Smarcel { 1487130803Smarcel if (!DebugSetProcessKillOnExit) 1488130803Smarcel DebugSetProcessKillOnExit = GetProcAddress (kernel32, 1489130803Smarcel "DebugSetProcessKillOnExit"); 1490130803Smarcel if (!DebugActiveProcessStop) 1491130803Smarcel DebugActiveProcessStop = GetProcAddress (kernel32, 1492130803Smarcel "DebugActiveProcessStop"); 1493130803Smarcel if (DebugSetProcessKillOnExit && DebugActiveProcessStop) 1494130803Smarcel return 1; 1495130803Smarcel } 1496130803Smarcel return 0; 1497130803Smarcel} 1498130803Smarcel 1499130803Smarcel/* Try to set or remove a user privilege to the current process. Return -1 1500130803Smarcel if that fails, the previous setting of that privilege otherwise. 1501130803Smarcel 1502130803Smarcel This code is copied from the Cygwin source code and rearranged to allow 1503130803Smarcel dynamically loading of the needed symbols from advapi32 which is only 1504130803Smarcel available on NT/2K/XP. */ 1505130803Smarcelstatic int 1506130803Smarcelset_process_privilege (const char *privilege, BOOL enable) 1507130803Smarcel{ 1508130803Smarcel static HMODULE advapi32 = NULL; 1509130803Smarcel static BOOL WINAPI (*OpenProcessToken)(HANDLE, DWORD, PHANDLE); 1510130803Smarcel static BOOL WINAPI (*LookupPrivilegeValue)(LPCSTR, LPCSTR, PLUID); 1511130803Smarcel static BOOL WINAPI (*AdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES, 1512130803Smarcel DWORD, PTOKEN_PRIVILEGES, PDWORD); 1513130803Smarcel 1514130803Smarcel HANDLE token_hdl = NULL; 1515130803Smarcel LUID restore_priv; 1516130803Smarcel TOKEN_PRIVILEGES new_priv, orig_priv; 1517130803Smarcel int ret = -1; 1518130803Smarcel DWORD size; 1519130803Smarcel 1520130803Smarcel if (GetVersion () >= 0x80000000) /* No security availbale on 9x/Me */ 1521130803Smarcel return 0; 1522130803Smarcel 1523130803Smarcel if (!advapi32) 1524130803Smarcel { 1525130803Smarcel if (!(advapi32 = LoadLibrary ("advapi32.dll"))) 1526130803Smarcel goto out; 1527130803Smarcel if (!OpenProcessToken) 1528130803Smarcel OpenProcessToken = GetProcAddress (advapi32, "OpenProcessToken"); 1529130803Smarcel if (!LookupPrivilegeValue) 1530130803Smarcel LookupPrivilegeValue = GetProcAddress (advapi32, 1531130803Smarcel "LookupPrivilegeValueA"); 1532130803Smarcel if (!AdjustTokenPrivileges) 1533130803Smarcel AdjustTokenPrivileges = GetProcAddress (advapi32, 1534130803Smarcel "AdjustTokenPrivileges"); 1535130803Smarcel if (!OpenProcessToken || !LookupPrivilegeValue || !AdjustTokenPrivileges) 1536130803Smarcel { 1537130803Smarcel advapi32 = NULL; 1538130803Smarcel goto out; 1539130803Smarcel } 1540130803Smarcel } 1541130803Smarcel 1542130803Smarcel if (!OpenProcessToken (GetCurrentProcess (), 1543130803Smarcel TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, 1544130803Smarcel &token_hdl)) 1545130803Smarcel goto out; 1546130803Smarcel 1547130803Smarcel if (!LookupPrivilegeValue (NULL, privilege, &restore_priv)) 1548130803Smarcel goto out; 1549130803Smarcel 1550130803Smarcel new_priv.PrivilegeCount = 1; 1551130803Smarcel new_priv.Privileges[0].Luid = restore_priv; 1552130803Smarcel new_priv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; 1553130803Smarcel 1554130803Smarcel if (!AdjustTokenPrivileges (token_hdl, FALSE, &new_priv, 1555130803Smarcel sizeof orig_priv, &orig_priv, &size)) 1556130803Smarcel goto out; 1557130803Smarcel#if 0 1558130803Smarcel /* Disabled, otherwise every `attach' in an unprivileged user session 1559130803Smarcel would raise the "Failed to get SE_DEBUG_NAME privilege" warning in 1560130803Smarcel child_attach(). */ 1561130803Smarcel /* AdjustTokenPrivileges returns TRUE even if the privilege could not 1562130803Smarcel be enabled. GetLastError () returns an correct error code, though. */ 1563130803Smarcel if (enable && GetLastError () == ERROR_NOT_ALL_ASSIGNED) 1564130803Smarcel goto out; 1565130803Smarcel#endif 1566130803Smarcel 1567130803Smarcel ret = orig_priv.Privileges[0].Attributes == SE_PRIVILEGE_ENABLED ? 1 : 0; 1568130803Smarcel 1569130803Smarcelout: 1570130803Smarcel if (token_hdl) 1571130803Smarcel CloseHandle (token_hdl); 1572130803Smarcel 1573130803Smarcel return ret; 1574130803Smarcel} 1575130803Smarcel 1576130803Smarcel/* Attach to process PID, then initialize for debugging it. */ 1577130803Smarcelstatic void 1578130803Smarcelchild_attach (char *args, int from_tty) 1579130803Smarcel{ 1580130803Smarcel BOOL ok; 1581130803Smarcel DWORD pid; 1582130803Smarcel 1583130803Smarcel if (!args) 1584130803Smarcel error_no_arg ("process-id to attach"); 1585130803Smarcel 1586130803Smarcel if (set_process_privilege (SE_DEBUG_NAME, TRUE) < 0) 1587130803Smarcel { 1588130803Smarcel printf_unfiltered ("Warning: Failed to get SE_DEBUG_NAME privilege\n"); 1589130803Smarcel printf_unfiltered ("This can cause attach to fail on Windows NT/2K/XP\n"); 1590130803Smarcel } 1591130803Smarcel 1592130803Smarcel pid = strtoul (args, 0, 0); /* Windows pid */ 1593130803Smarcel 1594130803Smarcel ok = DebugActiveProcess (pid); 1595130803Smarcel saw_create = 0; 1596130803Smarcel 1597130803Smarcel if (!ok) 1598130803Smarcel { 1599130803Smarcel /* Try fall back to Cygwin pid */ 1600130803Smarcel pid = cygwin_internal (CW_CYGWIN_PID_TO_WINPID, pid); 1601130803Smarcel 1602130803Smarcel if (pid > 0) 1603130803Smarcel ok = DebugActiveProcess (pid); 1604130803Smarcel 1605130803Smarcel if (!ok) 1606130803Smarcel error ("Can't attach to process."); 1607130803Smarcel } 1608130803Smarcel 1609130803Smarcel if (has_detach_ability ()) 1610130803Smarcel DebugSetProcessKillOnExit (FALSE); 1611130803Smarcel 1612130803Smarcel attach_flag = 1; 1613130803Smarcel 1614130803Smarcel if (from_tty) 1615130803Smarcel { 1616130803Smarcel char *exec_file = (char *) get_exec_file (0); 1617130803Smarcel 1618130803Smarcel if (exec_file) 1619130803Smarcel printf_unfiltered ("Attaching to program `%s', %s\n", exec_file, 1620130803Smarcel target_pid_to_str (pid_to_ptid (pid))); 1621130803Smarcel else 1622130803Smarcel printf_unfiltered ("Attaching to %s\n", 1623130803Smarcel target_pid_to_str (pid_to_ptid (pid))); 1624130803Smarcel 1625130803Smarcel gdb_flush (gdb_stdout); 1626130803Smarcel } 1627130803Smarcel 1628130803Smarcel do_initial_child_stuff (pid); 1629130803Smarcel target_terminal_ours (); 1630130803Smarcel} 1631130803Smarcel 1632130803Smarcelstatic void 1633130803Smarcelchild_detach (char *args, int from_tty) 1634130803Smarcel{ 1635130803Smarcel int detached = 1; 1636130803Smarcel 1637130803Smarcel if (has_detach_ability ()) 1638130803Smarcel { 1639130803Smarcel delete_command (NULL, 0); 1640130803Smarcel child_continue (DBG_CONTINUE, -1); 1641130803Smarcel if (!DebugActiveProcessStop (current_event.dwProcessId)) 1642130803Smarcel { 1643130803Smarcel error ("Can't detach process %lu (error %lu)", 1644130803Smarcel current_event.dwProcessId, GetLastError ()); 1645130803Smarcel detached = 0; 1646130803Smarcel } 1647130803Smarcel DebugSetProcessKillOnExit (FALSE); 1648130803Smarcel } 1649130803Smarcel if (detached && from_tty) 1650130803Smarcel { 1651130803Smarcel char *exec_file = get_exec_file (0); 1652130803Smarcel if (exec_file == 0) 1653130803Smarcel exec_file = ""; 1654130803Smarcel printf_unfiltered ("Detaching from program: %s, Pid %lu\n", exec_file, 1655130803Smarcel current_event.dwProcessId); 1656130803Smarcel gdb_flush (gdb_stdout); 1657130803Smarcel } 1658130803Smarcel inferior_ptid = null_ptid; 1659130803Smarcel unpush_target (&child_ops); 1660130803Smarcel} 1661130803Smarcel 1662130803Smarcel/* Print status information about what we're accessing. */ 1663130803Smarcel 1664130803Smarcelstatic void 1665130803Smarcelchild_files_info (struct target_ops *ignore) 1666130803Smarcel{ 1667130803Smarcel printf_unfiltered ("\tUsing the running image of %s %s.\n", 1668130803Smarcel attach_flag ? "attached" : "child", target_pid_to_str (inferior_ptid)); 1669130803Smarcel} 1670130803Smarcel 1671130803Smarcelstatic void 1672130803Smarcelchild_open (char *arg, int from_tty) 1673130803Smarcel{ 1674130803Smarcel error ("Use the \"run\" command to start a Unix child process."); 1675130803Smarcel} 1676130803Smarcel 1677130803Smarcel/* Start an inferior win32 child process and sets inferior_ptid to its pid. 1678130803Smarcel EXEC_FILE is the file to run. 1679130803Smarcel ALLARGS is a string containing the arguments to the program. 1680130803Smarcel ENV is the environment vector to pass. Errors reported with error(). */ 1681130803Smarcel 1682130803Smarcelstatic void 1683130803Smarcelchild_create_inferior (char *exec_file, char *allargs, char **env) 1684130803Smarcel{ 1685130803Smarcel char *winenv; 1686130803Smarcel char *temp; 1687130803Smarcel int envlen; 1688130803Smarcel int i; 1689130803Smarcel STARTUPINFO si; 1690130803Smarcel PROCESS_INFORMATION pi; 1691130803Smarcel BOOL ret; 1692130803Smarcel DWORD flags; 1693130803Smarcel char *args; 1694130803Smarcel char real_path[MAXPATHLEN]; 1695130803Smarcel char *toexec; 1696130803Smarcel char shell[MAX_PATH + 1]; /* Path to shell */ 1697130803Smarcel const char *sh; 1698130803Smarcel int tty; 1699130803Smarcel int ostdin, ostdout, ostderr; 1700130803Smarcel 1701130803Smarcel if (!exec_file) 1702130803Smarcel error ("No executable specified, use `target exec'.\n"); 1703130803Smarcel 1704130803Smarcel memset (&si, 0, sizeof (si)); 1705130803Smarcel si.cb = sizeof (si); 1706130803Smarcel 1707130803Smarcel if (!useshell) 1708130803Smarcel { 1709130803Smarcel flags = DEBUG_ONLY_THIS_PROCESS; 1710130803Smarcel cygwin_conv_to_win32_path (exec_file, real_path); 1711130803Smarcel toexec = real_path; 1712130803Smarcel } 1713130803Smarcel else 1714130803Smarcel { 1715130803Smarcel char *newallargs; 1716130803Smarcel sh = getenv ("SHELL"); 1717130803Smarcel if (!sh) 1718130803Smarcel sh = "/bin/sh"; 1719130803Smarcel cygwin_conv_to_win32_path (sh, shell); 1720130803Smarcel newallargs = alloca (sizeof (" -c 'exec '") + strlen (exec_file) 1721130803Smarcel + strlen (allargs) + 2); 1722130803Smarcel sprintf (newallargs, " -c 'exec %s %s'", exec_file, allargs); 1723130803Smarcel allargs = newallargs; 1724130803Smarcel toexec = shell; 1725130803Smarcel flags = DEBUG_PROCESS; 1726130803Smarcel } 1727130803Smarcel 1728130803Smarcel if (new_group) 1729130803Smarcel flags |= CREATE_NEW_PROCESS_GROUP; 1730130803Smarcel 1731130803Smarcel if (new_console) 1732130803Smarcel flags |= CREATE_NEW_CONSOLE; 1733130803Smarcel 1734130803Smarcel attach_flag = 0; 1735130803Smarcel 1736130803Smarcel args = alloca (strlen (toexec) + strlen (allargs) + 2); 1737130803Smarcel strcpy (args, toexec); 1738130803Smarcel strcat (args, " "); 1739130803Smarcel strcat (args, allargs); 1740130803Smarcel 1741130803Smarcel /* Prepare the environment vars for CreateProcess. */ 1742130803Smarcel { 1743130803Smarcel /* This code used to assume all env vars were file names and would 1744130803Smarcel translate them all to win32 style. That obviously doesn't work in the 1745130803Smarcel general case. The current rule is that we only translate PATH. 1746130803Smarcel We need to handle PATH because we're about to call CreateProcess and 1747130803Smarcel it uses PATH to find DLL's. Fortunately PATH has a well-defined value 1748130803Smarcel in both posix and win32 environments. cygwin.dll will change it back 1749130803Smarcel to posix style if necessary. */ 1750130803Smarcel 1751130803Smarcel static const char *conv_path_names[] = 1752130803Smarcel { 1753130803Smarcel "PATH=", 1754130803Smarcel 0 1755130803Smarcel }; 1756130803Smarcel 1757130803Smarcel /* CreateProcess takes the environment list as a null terminated set of 1758130803Smarcel strings (i.e. two nulls terminate the list). */ 1759130803Smarcel 1760130803Smarcel /* Get total size for env strings. */ 1761130803Smarcel for (envlen = 0, i = 0; env[i] && *env[i]; i++) 1762130803Smarcel { 1763130803Smarcel int j, len; 1764130803Smarcel 1765130803Smarcel for (j = 0; conv_path_names[j]; j++) 1766130803Smarcel { 1767130803Smarcel len = strlen (conv_path_names[j]); 1768130803Smarcel if (strncmp (conv_path_names[j], env[i], len) == 0) 1769130803Smarcel { 1770130803Smarcel if (cygwin_posix_path_list_p (env[i] + len)) 1771130803Smarcel envlen += len 1772130803Smarcel + cygwin_posix_to_win32_path_list_buf_size (env[i] + len); 1773130803Smarcel else 1774130803Smarcel envlen += strlen (env[i]) + 1; 1775130803Smarcel break; 1776130803Smarcel } 1777130803Smarcel } 1778130803Smarcel if (conv_path_names[j] == NULL) 1779130803Smarcel envlen += strlen (env[i]) + 1; 1780130803Smarcel } 1781130803Smarcel 1782130803Smarcel winenv = alloca (envlen + 1); 1783130803Smarcel 1784130803Smarcel /* Copy env strings into new buffer. */ 1785130803Smarcel for (temp = winenv, i = 0; env[i] && *env[i]; i++) 1786130803Smarcel { 1787130803Smarcel int j, len; 1788130803Smarcel 1789130803Smarcel for (j = 0; conv_path_names[j]; j++) 1790130803Smarcel { 1791130803Smarcel len = strlen (conv_path_names[j]); 1792130803Smarcel if (strncmp (conv_path_names[j], env[i], len) == 0) 1793130803Smarcel { 1794130803Smarcel if (cygwin_posix_path_list_p (env[i] + len)) 1795130803Smarcel { 1796130803Smarcel memcpy (temp, env[i], len); 1797130803Smarcel cygwin_posix_to_win32_path_list (env[i] + len, temp + len); 1798130803Smarcel } 1799130803Smarcel else 1800130803Smarcel strcpy (temp, env[i]); 1801130803Smarcel break; 1802130803Smarcel } 1803130803Smarcel } 1804130803Smarcel if (conv_path_names[j] == NULL) 1805130803Smarcel strcpy (temp, env[i]); 1806130803Smarcel 1807130803Smarcel temp += strlen (temp) + 1; 1808130803Smarcel } 1809130803Smarcel 1810130803Smarcel /* Final nil string to terminate new env. */ 1811130803Smarcel *temp = 0; 1812130803Smarcel } 1813130803Smarcel 1814130803Smarcel if (!inferior_io_terminal) 1815130803Smarcel tty = ostdin = ostdout = ostderr = -1; 1816130803Smarcel else 1817130803Smarcel { 1818130803Smarcel tty = open (inferior_io_terminal, O_RDWR | O_NOCTTY); 1819130803Smarcel if (tty < 0) 1820130803Smarcel { 1821130803Smarcel print_sys_errmsg (inferior_io_terminal, errno); 1822130803Smarcel ostdin = ostdout = ostderr = -1; 1823130803Smarcel } 1824130803Smarcel else 1825130803Smarcel { 1826130803Smarcel ostdin = dup (0); 1827130803Smarcel ostdout = dup (1); 1828130803Smarcel ostderr = dup (2); 1829130803Smarcel dup2 (tty, 0); 1830130803Smarcel dup2 (tty, 1); 1831130803Smarcel dup2 (tty, 2); 1832130803Smarcel } 1833130803Smarcel } 1834130803Smarcel 1835130803Smarcel ret = CreateProcess (0, 1836130803Smarcel args, /* command line */ 1837130803Smarcel NULL, /* Security */ 1838130803Smarcel NULL, /* thread */ 1839130803Smarcel TRUE, /* inherit handles */ 1840130803Smarcel flags, /* start flags */ 1841130803Smarcel winenv, 1842130803Smarcel NULL, /* current directory */ 1843130803Smarcel &si, 1844130803Smarcel &pi); 1845130803Smarcel if (tty >= 0) 1846130803Smarcel { 1847130803Smarcel close (tty); 1848130803Smarcel dup2 (ostdin, 0); 1849130803Smarcel dup2 (ostdout, 1); 1850130803Smarcel dup2 (ostderr, 2); 1851130803Smarcel close (ostdin); 1852130803Smarcel close (ostdout); 1853130803Smarcel close (ostderr); 1854130803Smarcel } 1855130803Smarcel 1856130803Smarcel if (!ret) 1857130803Smarcel error ("Error creating process %s, (error %d)\n", exec_file, (unsigned) GetLastError ()); 1858130803Smarcel 1859130803Smarcel CloseHandle (pi.hThread); 1860130803Smarcel CloseHandle (pi.hProcess); 1861130803Smarcel 1862130803Smarcel if (useshell && shell[0] != '\0') 1863130803Smarcel saw_create = -1; 1864130803Smarcel else 1865130803Smarcel saw_create = 0; 1866130803Smarcel 1867130803Smarcel do_initial_child_stuff (pi.dwProcessId); 1868130803Smarcel 1869130803Smarcel /* child_continue (DBG_CONTINUE, -1); */ 1870130803Smarcel proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0); 1871130803Smarcel} 1872130803Smarcel 1873130803Smarcelstatic void 1874130803Smarcelchild_mourn_inferior (void) 1875130803Smarcel{ 1876130803Smarcel (void) child_continue (DBG_CONTINUE, -1); 1877130803Smarcel i386_cleanup_dregs(); 1878130803Smarcel unpush_target (&child_ops); 1879130803Smarcel generic_mourn_inferior (); 1880130803Smarcel} 1881130803Smarcel 1882130803Smarcel/* Send a SIGINT to the process group. This acts just like the user typed a 1883130803Smarcel ^C on the controlling terminal. */ 1884130803Smarcel 1885130803Smarcelstatic void 1886130803Smarcelchild_stop (void) 1887130803Smarcel{ 1888130803Smarcel DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n")); 1889130803Smarcel CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId)); 1890130803Smarcel registers_changed (); /* refresh register state */ 1891130803Smarcel} 1892130803Smarcel 1893130803Smarcelint 1894130803Smarcelchild_xfer_memory (CORE_ADDR memaddr, char *our, int len, 1895130803Smarcel int write, struct mem_attrib *mem, 1896130803Smarcel struct target_ops *target) 1897130803Smarcel{ 1898130803Smarcel DWORD done = 0; 1899130803Smarcel if (write) 1900130803Smarcel { 1901130803Smarcel DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08lx\n", 1902130803Smarcel len, (DWORD) memaddr)); 1903130803Smarcel if (!WriteProcessMemory (current_process_handle, (LPVOID) memaddr, our, 1904130803Smarcel len, &done)) 1905130803Smarcel done = 0; 1906130803Smarcel FlushInstructionCache (current_process_handle, (LPCVOID) memaddr, len); 1907130803Smarcel } 1908130803Smarcel else 1909130803Smarcel { 1910130803Smarcel DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08lx\n", 1911130803Smarcel len, (DWORD) memaddr)); 1912130803Smarcel if (!ReadProcessMemory (current_process_handle, (LPCVOID) memaddr, our, 1913130803Smarcel len, &done)) 1914130803Smarcel done = 0; 1915130803Smarcel } 1916130803Smarcel return done; 1917130803Smarcel} 1918130803Smarcel 1919130803Smarcelvoid 1920130803Smarcelchild_kill_inferior (void) 1921130803Smarcel{ 1922130803Smarcel CHECK (TerminateProcess (current_process_handle, 0)); 1923130803Smarcel 1924130803Smarcel for (;;) 1925130803Smarcel { 1926130803Smarcel if (!child_continue (DBG_CONTINUE, -1)) 1927130803Smarcel break; 1928130803Smarcel if (!WaitForDebugEvent (¤t_event, INFINITE)) 1929130803Smarcel break; 1930130803Smarcel if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) 1931130803Smarcel break; 1932130803Smarcel } 1933130803Smarcel 1934130803Smarcel CHECK (CloseHandle (current_process_handle)); 1935130803Smarcel 1936130803Smarcel /* this may fail in an attached process so don't check. */ 1937130803Smarcel if (current_thread && current_thread->h) 1938130803Smarcel (void) CloseHandle (current_thread->h); 1939130803Smarcel target_mourn_inferior (); /* or just child_mourn_inferior? */ 1940130803Smarcel} 1941130803Smarcel 1942130803Smarcelvoid 1943130803Smarcelchild_resume (ptid_t ptid, int step, enum target_signal sig) 1944130803Smarcel{ 1945130803Smarcel thread_info *th; 1946130803Smarcel DWORD continue_status = DBG_CONTINUE; 1947130803Smarcel 1948130803Smarcel int pid = PIDGET (ptid); 1949130803Smarcel 1950130803Smarcel if (sig != TARGET_SIGNAL_0) 1951130803Smarcel { 1952130803Smarcel if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT) 1953130803Smarcel { 1954130803Smarcel DEBUG_EXCEPT(("Cannot continue with signal %d here.\n",sig)); 1955130803Smarcel } 1956130803Smarcel else if (sig == last_sig) 1957130803Smarcel continue_status = DBG_EXCEPTION_NOT_HANDLED; 1958130803Smarcel else 1959130803Smarcel#if 0 1960130803Smarcel/* This code does not seem to work, because 1961130803Smarcel the kernel does probably not consider changes in the ExceptionRecord 1962130803Smarcel structure when passing the exception to the inferior. 1963130803Smarcel Note that this seems possible in the exception handler itself. */ 1964130803Smarcel { 1965130803Smarcel int i; 1966130803Smarcel for (i = 0; xlate[i].them != -1; i++) 1967130803Smarcel if (xlate[i].us == sig) 1968130803Smarcel { 1969130803Smarcel current_event.u.Exception.ExceptionRecord.ExceptionCode = 1970130803Smarcel xlate[i].them; 1971130803Smarcel continue_status = DBG_EXCEPTION_NOT_HANDLED; 1972130803Smarcel break; 1973130803Smarcel } 1974130803Smarcel if (continue_status == DBG_CONTINUE) 1975130803Smarcel { 1976130803Smarcel DEBUG_EXCEPT(("Cannot continue with signal %d.\n",sig)); 1977130803Smarcel } 1978130803Smarcel } 1979130803Smarcel#endif 1980130803Smarcel DEBUG_EXCEPT(("Can only continue with recieved signal %d.\n", 1981130803Smarcel last_sig)); 1982130803Smarcel } 1983130803Smarcel 1984130803Smarcel last_sig = TARGET_SIGNAL_0; 1985130803Smarcel 1986130803Smarcel DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, sig=%d);\n", 1987130803Smarcel pid, step, sig)); 1988130803Smarcel 1989130803Smarcel /* Get context for currently selected thread */ 1990130803Smarcel th = thread_rec (current_event.dwThreadId, FALSE); 1991130803Smarcel if (th) 1992130803Smarcel { 1993130803Smarcel if (step) 1994130803Smarcel { 1995130803Smarcel /* Single step by setting t bit */ 1996130803Smarcel child_fetch_inferior_registers (PS_REGNUM); 1997130803Smarcel th->context.EFlags |= FLAG_TRACE_BIT; 1998130803Smarcel } 1999130803Smarcel 2000130803Smarcel if (th->context.ContextFlags) 2001130803Smarcel { 2002130803Smarcel if (debug_registers_changed) 2003130803Smarcel { 2004130803Smarcel th->context.Dr0 = dr[0]; 2005130803Smarcel th->context.Dr1 = dr[1]; 2006130803Smarcel th->context.Dr2 = dr[2]; 2007130803Smarcel th->context.Dr3 = dr[3]; 2008130803Smarcel /* th->context.Dr6 = dr[6]; 2009130803Smarcel FIXME: should we set dr6 also ?? */ 2010130803Smarcel th->context.Dr7 = dr[7]; 2011130803Smarcel } 2012130803Smarcel CHECK (SetThreadContext (th->h, &th->context)); 2013130803Smarcel th->context.ContextFlags = 0; 2014130803Smarcel } 2015130803Smarcel } 2016130803Smarcel 2017130803Smarcel /* Allow continuing with the same signal that interrupted us. 2018130803Smarcel Otherwise complain. */ 2019130803Smarcel 2020130803Smarcel child_continue (continue_status, pid); 2021130803Smarcel} 2022130803Smarcel 2023130803Smarcelstatic void 2024130803Smarcelchild_prepare_to_store (void) 2025130803Smarcel{ 2026130803Smarcel /* Do nothing, since we can store individual regs */ 2027130803Smarcel} 2028130803Smarcel 2029130803Smarcelstatic int 2030130803Smarcelchild_can_run (void) 2031130803Smarcel{ 2032130803Smarcel return 1; 2033130803Smarcel} 2034130803Smarcel 2035130803Smarcelstatic void 2036130803Smarcelchild_close (int x) 2037130803Smarcel{ 2038130803Smarcel DEBUG_EVENTS (("gdb: child_close, inferior_ptid=%d\n", 2039130803Smarcel PIDGET (inferior_ptid))); 2040130803Smarcel} 2041130803Smarcel 2042130803Smarcelstruct target_ops child_ops; 2043130803Smarcel 2044130803Smarcelstatic void 2045130803Smarcelinit_child_ops (void) 2046130803Smarcel{ 2047130803Smarcel child_ops.to_shortname = "child"; 2048130803Smarcel child_ops.to_longname = "Win32 child process"; 2049130803Smarcel child_ops.to_doc = "Win32 child process (started by the \"run\" command)."; 2050130803Smarcel child_ops.to_open = child_open; 2051130803Smarcel child_ops.to_close = child_close; 2052130803Smarcel child_ops.to_attach = child_attach; 2053130803Smarcel child_ops.to_detach = child_detach; 2054130803Smarcel child_ops.to_resume = child_resume; 2055130803Smarcel child_ops.to_wait = child_wait; 2056130803Smarcel child_ops.to_fetch_registers = child_fetch_inferior_registers; 2057130803Smarcel child_ops.to_store_registers = child_store_inferior_registers; 2058130803Smarcel child_ops.to_prepare_to_store = child_prepare_to_store; 2059130803Smarcel child_ops.to_xfer_memory = child_xfer_memory; 2060130803Smarcel child_ops.to_files_info = child_files_info; 2061130803Smarcel child_ops.to_insert_breakpoint = memory_insert_breakpoint; 2062130803Smarcel child_ops.to_remove_breakpoint = memory_remove_breakpoint; 2063130803Smarcel child_ops.to_terminal_init = terminal_init_inferior; 2064130803Smarcel child_ops.to_terminal_inferior = terminal_inferior; 2065130803Smarcel child_ops.to_terminal_ours_for_output = terminal_ours_for_output; 2066130803Smarcel child_ops.to_terminal_ours = terminal_ours; 2067130803Smarcel child_ops.to_terminal_save_ours = terminal_save_ours; 2068130803Smarcel child_ops.to_terminal_info = child_terminal_info; 2069130803Smarcel child_ops.to_kill = child_kill_inferior; 2070130803Smarcel child_ops.to_create_inferior = child_create_inferior; 2071130803Smarcel child_ops.to_mourn_inferior = child_mourn_inferior; 2072130803Smarcel child_ops.to_can_run = child_can_run; 2073130803Smarcel child_ops.to_thread_alive = win32_child_thread_alive; 2074130803Smarcel child_ops.to_pid_to_str = cygwin_pid_to_str; 2075130803Smarcel child_ops.to_stop = child_stop; 2076130803Smarcel child_ops.to_stratum = process_stratum; 2077130803Smarcel child_ops.to_has_all_memory = 1; 2078130803Smarcel child_ops.to_has_memory = 1; 2079130803Smarcel child_ops.to_has_stack = 1; 2080130803Smarcel child_ops.to_has_registers = 1; 2081130803Smarcel child_ops.to_has_execution = 1; 2082130803Smarcel child_ops.to_magic = OPS_MAGIC; 2083130803Smarcel} 2084130803Smarcel 2085130803Smarcelvoid 2086130803Smarcel_initialize_win32_nat (void) 2087130803Smarcel{ 2088130803Smarcel struct cmd_list_element *c; 2089130803Smarcel 2090130803Smarcel init_child_ops (); 2091130803Smarcel 2092130803Smarcel c = add_com ("dll-symbols", class_files, dll_symbol_command, 2093130803Smarcel "Load dll library symbols from FILE."); 2094130803Smarcel set_cmd_completer (c, filename_completer); 2095130803Smarcel 2096130803Smarcel add_com_alias ("sharedlibrary", "dll-symbols", class_alias, 1); 2097130803Smarcel 2098130803Smarcel add_show_from_set (add_set_cmd ("shell", class_support, var_boolean, 2099130803Smarcel (char *) &useshell, 2100130803Smarcel "Set use of shell to start subprocess.", 2101130803Smarcel &setlist), 2102130803Smarcel &showlist); 2103130803Smarcel 2104130803Smarcel add_show_from_set (add_set_cmd ("new-console", class_support, var_boolean, 2105130803Smarcel (char *) &new_console, 2106130803Smarcel "Set creation of new console when creating child process.", 2107130803Smarcel &setlist), 2108130803Smarcel &showlist); 2109130803Smarcel 2110130803Smarcel add_show_from_set (add_set_cmd ("new-group", class_support, var_boolean, 2111130803Smarcel (char *) &new_group, 2112130803Smarcel "Set creation of new group when creating child process.", 2113130803Smarcel &setlist), 2114130803Smarcel &showlist); 2115130803Smarcel 2116130803Smarcel add_show_from_set (add_set_cmd ("debugexec", class_support, var_boolean, 2117130803Smarcel (char *) &debug_exec, 2118130803Smarcel "Set whether to display execution in child process.", 2119130803Smarcel &setlist), 2120130803Smarcel &showlist); 2121130803Smarcel 2122130803Smarcel add_show_from_set (add_set_cmd ("debugevents", class_support, var_boolean, 2123130803Smarcel (char *) &debug_events, 2124130803Smarcel "Set whether to display kernel events in child process.", 2125130803Smarcel &setlist), 2126130803Smarcel &showlist); 2127130803Smarcel 2128130803Smarcel add_show_from_set (add_set_cmd ("debugmemory", class_support, var_boolean, 2129130803Smarcel (char *) &debug_memory, 2130130803Smarcel "Set whether to display memory accesses in child process.", 2131130803Smarcel &setlist), 2132130803Smarcel &showlist); 2133130803Smarcel 2134130803Smarcel add_show_from_set (add_set_cmd ("debugexceptions", class_support, var_boolean, 2135130803Smarcel (char *) &debug_exceptions, 2136130803Smarcel "Set whether to display kernel exceptions in child process.", 2137130803Smarcel &setlist), 2138130803Smarcel &showlist); 2139130803Smarcel 2140130803Smarcel add_info ("dll", info_dll_command, "Status of loaded DLLs."); 2141130803Smarcel add_info_alias ("sharedlibrary", "dll", 1); 2142130803Smarcel 2143130803Smarcel add_prefix_cmd ("w32", class_info, info_w32_command, 2144130803Smarcel "Print information specific to Win32 debugging.", 2145130803Smarcel &info_w32_cmdlist, "info w32 ", 0, &infolist); 2146130803Smarcel 2147130803Smarcel add_cmd ("selector", class_info, display_selectors, 2148130803Smarcel "Display selectors infos.", 2149130803Smarcel &info_w32_cmdlist); 2150130803Smarcel 2151130803Smarcel add_target (&child_ops); 2152130803Smarcel} 2153130803Smarcel 2154130803Smarcel/* Hardware watchpoint support, adapted from go32-nat.c code. */ 2155130803Smarcel 2156130803Smarcel/* Pass the address ADDR to the inferior in the I'th debug register. 2157130803Smarcel Here we just store the address in dr array, the registers will be 2158130803Smarcel actually set up when child_continue is called. */ 2159130803Smarcelvoid 2160130803Smarcelcygwin_set_dr (int i, CORE_ADDR addr) 2161130803Smarcel{ 2162130803Smarcel if (i < 0 || i > 3) 2163130803Smarcel internal_error (__FILE__, __LINE__, 2164130803Smarcel "Invalid register %d in cygwin_set_dr.\n", i); 2165130803Smarcel dr[i] = (unsigned) addr; 2166130803Smarcel debug_registers_changed = 1; 2167130803Smarcel debug_registers_used = 1; 2168130803Smarcel} 2169130803Smarcel 2170130803Smarcel/* Pass the value VAL to the inferior in the DR7 debug control 2171130803Smarcel register. Here we just store the address in D_REGS, the watchpoint 2172130803Smarcel will be actually set up in child_wait. */ 2173130803Smarcelvoid 2174130803Smarcelcygwin_set_dr7 (unsigned val) 2175130803Smarcel{ 2176130803Smarcel dr[7] = val; 2177130803Smarcel debug_registers_changed = 1; 2178130803Smarcel debug_registers_used = 1; 2179130803Smarcel} 2180130803Smarcel 2181130803Smarcel/* Get the value of the DR6 debug status register from the inferior. 2182130803Smarcel Here we just return the value stored in dr[6] 2183130803Smarcel by the last call to thread_rec for current_event.dwThreadId id. */ 2184130803Smarcelunsigned 2185130803Smarcelcygwin_get_dr6 (void) 2186130803Smarcel{ 2187130803Smarcel return dr[6]; 2188130803Smarcel} 2189130803Smarcel 2190130803Smarcel/* Determine if the thread referenced by "pid" is alive 2191130803Smarcel by "polling" it. If WaitForSingleObject returns WAIT_OBJECT_0 2192130803Smarcel it means that the pid has died. Otherwise it is assumed to be alive. */ 2193130803Smarcelstatic int 2194130803Smarcelwin32_child_thread_alive (ptid_t ptid) 2195130803Smarcel{ 2196130803Smarcel int pid = PIDGET (ptid); 2197130803Smarcel 2198130803Smarcel return WaitForSingleObject (thread_rec (pid, FALSE)->h, 0) == WAIT_OBJECT_0 ? 2199130803Smarcel FALSE : TRUE; 2200130803Smarcel} 2201130803Smarcel 2202130803Smarcel/* Convert pid to printable format. */ 2203130803Smarcelchar * 2204130803Smarcelcygwin_pid_to_str (ptid_t ptid) 2205130803Smarcel{ 2206130803Smarcel static char buf[80]; 2207130803Smarcel int pid = PIDGET (ptid); 2208130803Smarcel 2209130803Smarcel if ((DWORD) pid == current_event.dwProcessId) 2210130803Smarcel sprintf (buf, "process %d", pid); 2211130803Smarcel else 2212130803Smarcel sprintf (buf, "thread %ld.0x%x", current_event.dwProcessId, pid); 2213130803Smarcel return buf; 2214130803Smarcel} 2215130803Smarcel 2216130803Smarcelstatic int 2217130803Smarcelcore_dll_symbols_add (char *dll_name, DWORD base_addr) 2218130803Smarcel{ 2219130803Smarcel struct objfile *objfile; 2220130803Smarcel char *objfile_basename; 2221130803Smarcel const char *dll_basename; 2222130803Smarcel 2223130803Smarcel if (!(dll_basename = strrchr (dll_name, '/'))) 2224130803Smarcel dll_basename = dll_name; 2225130803Smarcel else 2226130803Smarcel dll_basename++; 2227130803Smarcel 2228130803Smarcel ALL_OBJFILES (objfile) 2229130803Smarcel { 2230130803Smarcel objfile_basename = strrchr (objfile->name, '/'); 2231130803Smarcel 2232130803Smarcel if (objfile_basename && 2233130803Smarcel strcmp (dll_basename, objfile_basename + 1) == 0) 2234130803Smarcel { 2235130803Smarcel printf_unfiltered ("%08lx:%s (symbols previously loaded)\n", 2236130803Smarcel base_addr, dll_name); 2237130803Smarcel goto out; 2238130803Smarcel } 2239130803Smarcel } 2240130803Smarcel 2241130803Smarcel register_loaded_dll (dll_name, base_addr + 0x1000); 2242130803Smarcel solib_symbols_add (dll_name, 0, (CORE_ADDR) base_addr + 0x1000); 2243130803Smarcel 2244130803Smarcel out: 2245130803Smarcel return 1; 2246130803Smarcel } 2247130803Smarcel 2248130803Smarcel typedef struct 2249130803Smarcel { 2250130803Smarcel struct target_ops *target; 2251130803Smarcel bfd_vma addr; 2252130803Smarcel } map_code_section_args; 2253130803Smarcel 2254130803Smarcel static void 2255130803Smarcel map_single_dll_code_section (bfd * abfd, asection * sect, void *obj) 2256130803Smarcel { 2257130803Smarcel int old; 2258130803Smarcel int update_coreops; 2259130803Smarcel struct section_table *new_target_sect_ptr; 2260130803Smarcel 2261130803Smarcel map_code_section_args *args = (map_code_section_args *) obj; 2262130803Smarcel struct target_ops *target = args->target; 2263130803Smarcel if (sect->flags & SEC_CODE) 2264130803Smarcel { 2265130803Smarcel update_coreops = core_ops.to_sections == target->to_sections; 2266130803Smarcel 2267130803Smarcel if (target->to_sections) 2268130803Smarcel { 2269130803Smarcel old = target->to_sections_end - target->to_sections; 2270130803Smarcel target->to_sections = (struct section_table *) 2271130803Smarcel xrealloc ((char *) target->to_sections, 2272130803Smarcel (sizeof (struct section_table)) * (1 + old)); 2273130803Smarcel } 2274130803Smarcel else 2275130803Smarcel { 2276130803Smarcel old = 0; 2277130803Smarcel target->to_sections = (struct section_table *) 2278130803Smarcel xmalloc ((sizeof (struct section_table))); 2279130803Smarcel } 2280130803Smarcel target->to_sections_end = target->to_sections + (1 + old); 2281130803Smarcel 2282130803Smarcel /* Update the to_sections field in the core_ops structure 2283130803Smarcel if needed. */ 2284130803Smarcel if (update_coreops) 2285130803Smarcel { 2286130803Smarcel core_ops.to_sections = target->to_sections; 2287130803Smarcel core_ops.to_sections_end = target->to_sections_end; 2288130803Smarcel } 2289130803Smarcel new_target_sect_ptr = target->to_sections + old; 2290130803Smarcel new_target_sect_ptr->addr = args->addr + bfd_section_vma (abfd, sect); 2291130803Smarcel new_target_sect_ptr->endaddr = args->addr + bfd_section_vma (abfd, sect) + 2292130803Smarcel bfd_section_size (abfd, sect);; 2293130803Smarcel new_target_sect_ptr->the_bfd_section = sect; 2294130803Smarcel new_target_sect_ptr->bfd = abfd; 2295130803Smarcel } 2296130803Smarcel } 2297130803Smarcel 2298130803Smarcel static int 2299130803Smarcel dll_code_sections_add (const char *dll_name, int base_addr, struct target_ops *target) 2300130803Smarcel{ 2301130803Smarcel bfd *dll_bfd; 2302130803Smarcel map_code_section_args map_args; 2303130803Smarcel asection *lowest_sect; 2304130803Smarcel char *name; 2305130803Smarcel if (dll_name == NULL || target == NULL) 2306130803Smarcel return 0; 2307130803Smarcel name = xstrdup (dll_name); 2308130803Smarcel dll_bfd = bfd_openr (name, "pei-i386"); 2309130803Smarcel if (dll_bfd == NULL) 2310130803Smarcel return 0; 2311130803Smarcel 2312130803Smarcel if (bfd_check_format (dll_bfd, bfd_object)) 2313130803Smarcel { 2314130803Smarcel lowest_sect = bfd_get_section_by_name (dll_bfd, ".text"); 2315130803Smarcel if (lowest_sect == NULL) 2316130803Smarcel return 0; 2317130803Smarcel map_args.target = target; 2318130803Smarcel map_args.addr = base_addr - bfd_section_vma (dll_bfd, lowest_sect); 2319130803Smarcel 2320130803Smarcel bfd_map_over_sections (dll_bfd, &map_single_dll_code_section, (void *) (&map_args)); 2321130803Smarcel } 2322130803Smarcel 2323130803Smarcel return 1; 2324130803Smarcel} 2325130803Smarcel 2326130803Smarcelstatic void 2327130803Smarcelcore_section_load_dll_symbols (bfd * abfd, asection * sect, void *obj) 2328130803Smarcel{ 2329130803Smarcel struct target_ops *target = (struct target_ops *) obj; 2330130803Smarcel 2331130803Smarcel DWORD base_addr; 2332130803Smarcel 2333130803Smarcel int dll_name_size; 2334130803Smarcel char *dll_name = NULL; 2335130803Smarcel char *buf = NULL; 2336130803Smarcel struct win32_pstatus *pstatus; 2337130803Smarcel char *p; 2338130803Smarcel 2339130803Smarcel if (strncmp (sect->name, ".module", 7)) 2340130803Smarcel return; 2341130803Smarcel 2342130803Smarcel buf = (char *) xmalloc (sect->_raw_size + 1); 2343130803Smarcel if (!buf) 2344130803Smarcel { 2345130803Smarcel printf_unfiltered ("memory allocation failed for %s\n", sect->name); 2346130803Smarcel goto out; 2347130803Smarcel } 2348130803Smarcel if (!bfd_get_section_contents (abfd, sect, buf, 0, sect->_raw_size)) 2349130803Smarcel goto out; 2350130803Smarcel 2351130803Smarcel pstatus = (struct win32_pstatus *) buf; 2352130803Smarcel 2353130803Smarcel memmove (&base_addr, &(pstatus->data.module_info.base_address), sizeof (base_addr)); 2354130803Smarcel dll_name_size = pstatus->data.module_info.module_name_size; 2355130803Smarcel if (offsetof (struct win32_pstatus, data.module_info.module_name) + dll_name_size > sect->_raw_size) 2356130803Smarcel goto out; 2357130803Smarcel 2358130803Smarcel dll_name = (char *) xmalloc (dll_name_size + 1); 2359130803Smarcel if (!dll_name) 2360130803Smarcel { 2361130803Smarcel printf_unfiltered ("memory allocation failed for %s\n", sect->name); 2362130803Smarcel goto out; 2363130803Smarcel } 2364130803Smarcel strncpy (dll_name, pstatus->data.module_info.module_name, dll_name_size); 2365130803Smarcel 2366130803Smarcel while ((p = strchr (dll_name, '\\'))) 2367130803Smarcel *p = '/'; 2368130803Smarcel 2369130803Smarcel if (!core_dll_symbols_add (dll_name, (DWORD) base_addr)) 2370130803Smarcel printf_unfiltered ("%s: Failed to load dll symbols.\n", dll_name); 2371130803Smarcel 2372130803Smarcel if (!dll_code_sections_add (dll_name, (DWORD) base_addr + 0x1000, target)) 2373130803Smarcel printf_unfiltered ("%s: Failed to map dll code sections.\n", dll_name); 2374130803Smarcel 2375130803Smarcelout: 2376130803Smarcel if (buf) 2377130803Smarcel xfree (buf); 2378130803Smarcel if (dll_name) 2379130803Smarcel xfree (dll_name); 2380130803Smarcel return; 2381130803Smarcel} 2382130803Smarcel 2383130803Smarcelvoid 2384130803Smarcelchild_solib_add (char *filename, int from_tty, struct target_ops *target, 2385130803Smarcel int readsyms) 2386130803Smarcel{ 2387130803Smarcel if (!readsyms) 2388130803Smarcel return; 2389130803Smarcel if (core_bfd) 2390130803Smarcel { 2391130803Smarcel child_clear_solibs (); 2392130803Smarcel bfd_map_over_sections (core_bfd, &core_section_load_dll_symbols, target); 2393130803Smarcel } 2394130803Smarcel else 2395130803Smarcel { 2396130803Smarcel if (solib_end && solib_end->name) 2397130803Smarcel solib_end->objfile = solib_symbols_add (solib_end->name, from_tty, 2398130803Smarcel solib_end->load_addr); 2399130803Smarcel } 2400130803Smarcel} 2401130803Smarcel 2402130803Smarcelstatic void 2403130803Smarcelfetch_elf_core_registers (char *core_reg_sect, 2404130803Smarcel unsigned core_reg_size, 2405130803Smarcel int which, 2406130803Smarcel CORE_ADDR reg_addr) 2407130803Smarcel{ 2408130803Smarcel int r; 2409130803Smarcel if (core_reg_size < sizeof (CONTEXT)) 2410130803Smarcel { 2411130803Smarcel error ("Core file register section too small (%u bytes).", core_reg_size); 2412130803Smarcel return; 2413130803Smarcel } 2414130803Smarcel for (r = 0; r < NUM_REGS; r++) 2415130803Smarcel supply_register (r, core_reg_sect + mappings[r]); 2416130803Smarcel} 2417130803Smarcel 2418130803Smarcelstatic struct core_fns win32_elf_core_fns = 2419130803Smarcel{ 2420130803Smarcel bfd_target_elf_flavour, 2421130803Smarcel default_check_format, 2422130803Smarcel default_core_sniffer, 2423130803Smarcel fetch_elf_core_registers, 2424130803Smarcel NULL 2425130803Smarcel}; 2426130803Smarcel 2427130803Smarcelvoid 2428130803Smarcel_initialize_core_win32 (void) 2429130803Smarcel{ 2430130803Smarcel add_core_fns (&win32_elf_core_fns); 2431130803Smarcel} 2432130803Smarcel 2433130803Smarcelvoid 2434130803Smarcel_initialize_check_for_gdb_ini (void) 2435130803Smarcel{ 2436130803Smarcel char *homedir; 2437130803Smarcel if (inhibit_gdbinit) 2438130803Smarcel return; 2439130803Smarcel 2440130803Smarcel homedir = getenv ("HOME"); 2441130803Smarcel if (homedir) 2442130803Smarcel { 2443130803Smarcel char *p; 2444130803Smarcel char *oldini = (char *) alloca (strlen (homedir) + 2445130803Smarcel sizeof ("/gdb.ini")); 2446130803Smarcel strcpy (oldini, homedir); 2447130803Smarcel p = strchr (oldini, '\0'); 2448130803Smarcel if (p > oldini && p[-1] != '/') 2449130803Smarcel *p++ = '/'; 2450130803Smarcel strcpy (p, "gdb.ini"); 2451130803Smarcel if (access (oldini, 0) == 0) 2452130803Smarcel { 2453130803Smarcel int len = strlen (oldini); 2454130803Smarcel char *newini = alloca (len + 1); 2455130803Smarcel sprintf (newini, "%.*s.gdbinit", 2456130803Smarcel (int) (len - (sizeof ("gdb.ini") - 1)), oldini); 2457130803Smarcel warning ("obsolete '%s' found. Rename to '%s'.", oldini, newini); 2458130803Smarcel } 2459130803Smarcel } 2460130803Smarcel} 2461