1 /* 2 * Copyright 2001-2004 Sun Microsystems, Inc. All Rights Reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 * 23 */ 24 25 package sun.jvm.hotspot.debugger.win32; 26 27 import sun.jvm.hotspot.debugger.*; 28 import sun.jvm.hotspot.debugger.x86.*; 29 30 class Win32Thread implements ThreadProxy { 31 private Win32Debugger debugger; 32 private int handle; 33 private boolean mustDuplicate; 34 private boolean gotID; 35 private int id; 36 37 /** The address argument must be the address of the HANDLE of the 38 desired thread in the target process. */ 39 Win32Thread(Win32Debugger debugger, Address addr) { 40 this.debugger = debugger; 41 // FIXME: size of data fetched here should be configurable. 42 // However, making it so would produce a dependency on the "types" 43 // package from the debugger package, which is not desired. 44 this.handle = (int) addr.getCIntegerAt(0, 4, true); 45 // Thread handles in the target process must be duplicated before 46 // fetching their contexts 47 mustDuplicate = true; 48 gotID = false; 49 } 50 51 /** The integer argument must be the value of a HANDLE received from 52 the "threadlist" operation. */ 53 Win32Thread(Win32Debugger debugger, long handle) { 54 this.debugger = debugger; 55 this.handle = (int) handle; 56 mustDuplicate = false; 57 gotID = false; 58 } 59 60 public ThreadContext getContext() throws IllegalThreadStateException { 61 if (!debugger.isSuspended()) { 62 throw new IllegalThreadStateException("Target process must be suspended"); 63 } 64 long[] data = debugger.getThreadIntegerRegisterSet(handle, mustDuplicate); 65 Win32ThreadContext context = new Win32ThreadContext(debugger); 66 for (int i = 0; i < data.length; i++) { 67 context.setRegister(i, data[i]); 68 } 69 return context; 70 } 71 72 public boolean canSetContext() throws DebuggerException { 73 return true; 74 } 75 76 public void setContext(ThreadContext thrCtx) 77 throws IllegalThreadStateException, DebuggerException { 78 if (!debugger.isSuspended()) { 79 throw new IllegalThreadStateException("Target process must be suspended"); 80 } 81 X86ThreadContext context = (X86ThreadContext) thrCtx; 82 long[] data = new long[X86ThreadContext.NPRGREG]; 83 for (int i = 0; i < data.length; i++) { 84 data[i] = context.getRegister(i); 85 } 86 debugger.setThreadIntegerRegisterSet(handle, mustDuplicate, data); 87 } 88 89 public boolean equals(Object obj) { 90 if ((obj == null) || !(obj instanceof Win32Thread)) { 91 return false; 92 } 93 94 return (((Win32Thread) obj).getThreadID() == getThreadID()); 95 } 96 97 public int hashCode() { 98 return getThreadID(); 99 } 100 101 public String toString() { 102 return Integer.toString(getThreadID()); 103 } 104 105 /** Retrieves the thread ID of this thread by examining the Thread 106 Information Block. */ 107 private int getThreadID() { 108 if (!gotID) { 109 try { 110 // Get thread context 111 X86ThreadContext context = (X86ThreadContext) getContext(); 112 // Get LDT entry for FS register 113 Win32LDTEntry ldt = 114 debugger.getThreadSelectorEntry(handle, 115 mustDuplicate, 116 (int) context.getRegister(X86ThreadContext.FS)); 117 // Get base address of segment = Thread Environment Block (TEB) 118 Address teb = debugger.newAddress(ldt.getBase()); 119 // Thread ID is at offset 0x24 120 id = (int) teb.getCIntegerAt(0x24, 4, true); 121 gotID = true; 122 } catch (AddressException e) { 123 throw new DebuggerException(e); 124 } 125 } 126 127 return id; 128 } 129 }