Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI_RT / src / RTwinnt.c
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 /************************************************************************
33  * $Id: RTwinnt.c,v 1.22 2006/06/09 03:50:49 jodom Exp $
34  * RTwinnt.c: runtime instrumentation functions for Windows NT
35  ************************************************************************/
36 #include "dyninstAPI_RT/h/dyninstAPI_RT.h"
37 #include "RTcommon.h"
38 #include <windows.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 //#define WIN32_LEAN_AND_MEAN
42 #include <windows.h>
43 #include <mmsystem.h>
44 #include <errno.h>
45 #include <limits.h>
46 #include <process.h>
47 #include <fcntl.h>
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include <io.h>
51 #include <stdio.h>
52 //#include <winsock2.h>
53
54 /************************************************************************
55  * void DYNINSTbreakPoint(void)
56  *
57  * stop oneself.
58 ************************************************************************/
59
60 void DYNINSTbreakPoint(void) {
61   /* TODO: how do we stop all threads? */
62     DYNINST_break_point_event = 1;
63     DebugBreak();
64     DYNINST_break_point_event = 0;
65 }
66
67 void DYNINSTsafeBreakPoint() {
68     DYNINSTbreakPoint();
69 }
70
71 static dyntid_t initial_thread_tid;
72 void DYNINSTos_init(int calledByFork, int calledByAttach)
73 {
74   RTprintf("DYNINSTos_init(%d,%d)\n", calledByFork, calledByAttach);
75   initial_thread_tid = (dyntid_t) GetCurrentThreadId();
76 }
77
78 /* this function is automatically called when windows loads this dll
79  if we are launching a mutatee to instrument, dyninst will place
80  the correct values in libdyninstAPI_RT_DLL_localPid and
81  libdyninstAPI_RT_DLL_localCause and they will be passed to
82  DYNINSTinit to correctly initialize the dll.  this keeps us
83  from having to instrument two steps from the mutator (load and then 
84  the execution of DYNINSTinit()
85 */
86
87 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
88 {
89    static int DllMainCalledOnce = 0;
90
91    if(DllMainCalledOnce)
92       return 1;
93    DllMainCalledOnce++;
94
95    if(libdyninstAPI_RT_init_localPid != -1 || libdyninstAPI_RT_init_localCause != -1)
96       DYNINSTinit(libdyninstAPI_RT_init_localCause, libdyninstAPI_RT_init_localPid,
97                   libdyninstAPI_RT_init_maxthreads, libdyninstAPI_RT_init_debug_flag);
98
99
100    return 1; 
101 }
102  
103
104
105 char gLoadLibraryErrorString[ERROR_STRING_LENGTH];
106 int DYNINSTloadLibrary(char *libname)
107 {
108     HMODULE res;
109     gLoadLibraryErrorString[0] = '\0';
110     res = LoadLibrary(libname);
111     if (res == NULL) {
112         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 
113                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
114                   gLoadLibraryErrorString, ERROR_STRING_LENGTH, NULL);
115         return 0;
116     }
117     return 1;
118 }
119
120 /************************************************************************
121  * void DYNINSTasyncConnect()
122  *
123  * Connect to mutator's async handler thread. <pid> is pid of mutator
124  ************************************************************************/
125 //CRITICAL_SECTION comms_mutex;
126
127 int async_socket = -1;
128 int connect_port = 0;
129
130 int DYNINSTasyncConnect(int mutatorpid)
131 {
132   int sock_fd;
133   struct sockaddr_in sadr;
134   struct in_addr *inadr;
135   struct hostent *hostptr;
136   
137   WORD wsversion = MAKEWORD(2,0);
138   WSADATA wsadata;
139   rtBPatch_asyncEventRecord ev;
140
141   if (async_socket != -1) 
142   {
143           /*fprintf(stderr, "%s[%d]:  already connected\n", __FILE__, __LINE__);*/
144       return 0;
145   }
146
147   RTprintf("%s[%d]:  inside DYNINSTasyncConnect\n", __FILE__, __LINE__);
148
149   if (0 == connect_port) 
150   {
151     fprintf(stderr, "%s[%d]:  DYNINSTasyncConnect, no port\n",
152             __FILE__, __LINE__);    
153   }
154
155   WSAStartup(wsversion, &wsadata);
156    
157   RTprintf("%s[%d]:  DYNINSTasyncConnect before gethostbyname\n", __FILE__, __LINE__);
158
159   hostptr = gethostbyname("localhost");
160   inadr = (struct in_addr *) ((void*) hostptr->h_addr_list[0]);
161
162   RTprintf("%s[%d]:  inside DYNINSTasyncConnect before memset\n", __FILE__, __LINE__);
163
164   memset((void*) &sadr, 0, sizeof(sadr));
165   sadr.sin_family = PF_INET;
166   sadr.sin_port = htons((u_short)connect_port);
167   sadr.sin_addr = *inadr;
168
169   RTprintf("%s[%d]:   DYNINSTasyncConnect before socket\n", __FILE__, __LINE__);
170
171   sock_fd = socket(PF_INET, SOCK_STREAM, 0);
172
173   if (sock_fd == INVALID_SOCKET) 
174   {
175     fprintf(stderr, "DYNINST: socket failed: %d\n", WSAGetLastError());
176   }
177
178   RTprintf("%s[%d]:   DYNINSTasyncConnect before connect\n", __FILE__, __LINE__);
179
180   if (connect(sock_fd, (struct sockaddr *) &sadr, sizeof(sadr)) == SOCKET_ERROR) 
181   {
182     fprintf(stderr, "DYNINSTasyncConnect: connect failed: %d\n", WSAGetLastError());
183   }
184
185   /* maybe need to do fcntl to set nonblocking writes on this fd */
186
187   async_socket = sock_fd;
188
189   RTprintf("%s[%d]:   DYNINSTasyncConnect before write\n", __FILE__, __LINE__);
190
191   /* after connecting, we need to send along our pid */
192   ev.type = rtBPatch_newConnectionEvent;
193   ev.pid = _getpid();
194
195   if (!DYNINSTwriteEvent((void *) &ev, sizeof(rtBPatch_asyncEventRecord))) 
196   {
197     fprintf(stderr, "%s[%d]:  DYNINSTwriteEventFailed\n", __FILE__, __LINE__);
198   }
199
200   /* initialize comms mutex */
201
202   //InitializeCriticalSection(&comms_mutex);
203   //fprintf(stderr, "%s[%d]: DYNINSTasyncConnect appears to have succeeded\n", __FILE__, __LINE__);
204
205   RTprintf("%s[%d]:  leaving DYNINSTasyncConnect\n", __FILE__, __LINE__);
206
207   return 1; /*true*/
208 }
209
210 int DYNINSTasyncDisconnect()
211 {
212   WSACleanup();
213   return _close (async_socket);
214 }
215
216 void printSysError(unsigned errNo) {
217     char buf[1000];
218     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errNo, 
219                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
220                   buf, 1000, NULL);
221
222     fprintf(stderr, "*** System error [%d]: %s\n", errNo, buf);
223     fflush(stderr);
224 }
225
226 int DYNINSTwriteEvent(void *ev, size_t sz)
227 {
228   DYNINSTasyncConnect(DYNINST_mutatorPid);
229
230   if (send((SOCKET)async_socket, ev, sz, 0) != sz) 
231   {
232     printSysError(WSAGetLastError());
233     printf("DYNINSTwriteTrace: send error %d, %d %d\n",
234            WSAGetLastError(), sz, async_socket);
235
236     if (async_socket == -1)
237       return 1;
238     return 0;
239   }
240   return 1;
241 }
242
243 int dyn_pid_self()
244 {
245    return _getpid();
246 }
247
248 int dyn_lwp_self()
249 {
250     return GetCurrentThreadId();
251 }
252
253 dyntid_t dyn_pthread_self()
254 {
255    return (dyntid_t) dyn_lwp_self();
256 }
257
258 int DYNINSTthreadInfo(BPatch_newThreadEventRecord *ev)
259 {
260     return 1;
261 }
262
263 /* 
264    We reserve index 0 for the initial thread. This value varies by
265    platform but is always constant for that platform. Wrap that
266    platform-ness here. 
267 */
268 int DYNINST_am_initial_thread(dyntid_t tid) {
269     return (tid == initial_thread_tid);
270 }