rebased to master after sw 3rd party completed
[dyninst.git] / dyninstAPI_RT / src / RTposix.c
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 /************************************************************************
32  * $Id: RTposix.c,v 1.37 2008/04/11 23:30:45 legendre Exp $
33  * RTposix.c: runtime instrumentation functions for generic posix.
34  ************************************************************************/
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <signal.h>
39 #include <assert.h>
40 #include <errno.h>
41 #include <string.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <sys/types.h>
45 #include <sys/un.h>
46 #include <sys/mman.h>
47
48 #if !defined(os_vxworks)
49 // VxWorks is missing these headers.
50 #include <memory.h>
51 #include <sys/socket.h>
52 #include <pwd.h>
53 #endif
54
55 #include "dyninstAPI_RT/h/dyninstAPI_RT.h"
56 #include "dyninstAPI_RT/src/RTcommon.h"
57 #include "dyninstAPI_RT/src/RTheap.h"
58
59 #define SOCKLEN_T socklen_t
60
61 #if !(defined(arch_power) && defined(os_linux))
62 void RTmutatedBinary_init() 
63 {
64     return;
65 }
66 #endif
67
68 #if defined(__GNUC) || defined(__GNUC__)
69 #if defined(DYNINST_RT_STATIC_LIB)
70 /*
71  * In the static version of the library, constructors cannot be
72  * used to run code at initialization. See DYNINSTglobal_ctors_handler.
73  */
74 void libdyninstAPI_RT_init(void);
75 #else
76 void libdyninstAPI_RT_init(void) __attribute__ ((constructor));
77 #endif
78 #endif
79
80 #if defined (cap_async_events)
81 struct passwd *passwd_info = NULL;
82 #endif
83
84 void libdyninstAPI_RT_init() 
85 {
86    static int initCalledOnce = 0;
87
88    rtdebug_printf("%s[%d]:  DYNINSTinit:  welcome to libdyninstAPI_RT_init()\n", __FILE__, __LINE__);
89
90    if (initCalledOnce) return;
91    initCalledOnce++;
92
93   
94    DYNINSTinit();
95    rtdebug_printf("%s[%d]:  did DYNINSTinit\n", __FILE__, __LINE__);
96 }
97
98
99 /************************************************************************
100  * void DYNINSTasyncConnect(int pid)
101  *
102  * Connect to mutator's async handler thread. <pid> is pid of mutator
103 ************************************************************************/
104
105 static int async_socket = -1;
106 static int needToDisconnect = 0;
107 static char socket_path[255];
108
109 int DYNINSTasyncConnect(int pid)
110 {
111    if (DYNINSTstaticMode)
112       return 0;
113 #if defined (os_vxworks)
114    return 1;
115
116 #elif defined (cap_async_events)
117   int sock_fd;
118   struct sockaddr_un sadr;
119    int res;
120    int mutatee_pid;
121    uid_t euid;
122
123    rtdebug_printf("%s[%d]:  DYNINSTasyncConnnect:  entry\n", __FILE__, __LINE__);
124    rtdebug_printf("%s[%d]:  DYNINSTinit:  before geteuid\n", __FILE__, __LINE__);
125
126    euid = geteuid();
127    passwd_info = getpwuid(euid);
128    assert(passwd_info);
129
130   if (async_socket != -1)
131   {
132           fprintf(stderr, "%s[%d]: - DYNINSTasyncConnect already initialized\n",
133                           __FILE__, __LINE__);
134
135      rtdebug_printf("%s[%d]:  DYNINSTasyncConnnect:  already connected\n", 
136                          __FILE__, __LINE__);
137      return 0;
138   }
139
140   rtdebug_printf("%s[%d]:  DYNINSTasyncConnnect:  before socket 2\n", __FILE__, __LINE__);
141   mutatee_pid = getpid();
142
143   snprintf(socket_path, (size_t) 255, "%s/dyninstAsync.%s.%d.%d", 
144                   P_tmpdir, passwd_info->pw_name, pid, mutatee_pid);
145
146   rtdebug_printf("%s[%d]:  DYNINSTasyncConnnect:  before socket: %s\n", __FILE__, __LINE__, socket_path);
147
148   errno = 0;
149
150   sock_fd = socket(PF_UNIX, SOCK_STREAM, 0);
151
152   if (sock_fd < 0) 
153   {
154     fprintf(stderr, "%s[%d]: DYNINSTasyncConnect() socket(%s): %s\n", 
155                         __FILE__, __LINE__, socket_path, strerror(errno));
156     abort();
157   }
158
159   rtdebug_printf("%s[%d]:  DYNINSTasyncConnnect:  after socket\n", __FILE__, __LINE__);
160
161   sadr.sun_family = PF_UNIX;
162   strcpy(sadr.sun_path, socket_path);
163
164   rtdebug_printf("%s[%d]:  DYNINSTasyncConnnect:  before connect\n", __FILE__, __LINE__);
165   res = 0;
166   errno = 0;
167
168   res = connect(sock_fd, (struct sockaddr *) &sadr, sizeof(sadr)); 
169
170   if (res < 0)
171   {
172     perror("DYNINSTasyncConnect() connect()");
173   }
174
175   rtdebug_printf("%s[%d]:  DYNINSTasyncConnnect:  after connect to %s, res = %d, -- %s\n", 
176                   __FILE__, __LINE__, socket_path, res, strerror(errno));
177
178   /* maybe need to do fcntl to set nonblocking writes on this fd */
179
180   if (async_socket == -1)
181   {
182           rtdebug_printf("%s[%d]:  WARN:  async socket has not been reset!!\n", __FILE__, __LINE__);
183   }
184
185   async_socket = sock_fd;
186
187   needToDisconnect = 1;
188
189  /* atexit(exit_func); */
190   rtdebug_printf("%s[%d]:  leaving DYNINSTasyncConnect\n", __FILE__, __LINE__);
191   return 1; 
192 #else
193   fprintf(stderr, "%s[%d]:  called DYNINSTasyncConect when async_events disabled\n",
194                   __FILE__, __LINE__);
195   return 0;
196 #endif
197 }
198
199 int DYNINSTasyncDisconnect()
200 {
201    if (DYNINSTstaticMode)
202       return 0;
203    rtdebug_printf("%s[%d]:  welcome to DYNINSTasyncDisconnect\n", __FILE__, __LINE__);
204    if (needToDisconnect) {
205       close (async_socket);
206       needToDisconnect = 0;
207    }
208    async_socket = -1;
209    return 0;
210 }
211
212 int DYNINSTwriteEvent(void *ev, size_t sz)
213 {
214   ssize_t res;
215
216   if (DYNINSTstaticMode)
217      return 0;
218   
219     rtdebug_printf("%s[%d]:  welcome to DYNINSTwriteEvent: %d bytes\n", __FILE__, __LINE__, sz);
220   if (-1 == async_socket)
221   {
222           rtdebug_printf("%s[%d]:  failed to DYNINSTwriteEvent, no socket\n", __FILE__, __LINE__);
223           return -1;
224   }
225
226 try_again:
227   res = write(async_socket, ev, sz); 
228   if (-1 == res) {
229     if (errno == EINTR || errno == EAGAIN) 
230        goto try_again;
231     else {
232        perror("write");
233        return -1;
234     }
235   }
236   if ((size_t)res != sz) {
237     /*  maybe we need logic to handle partial writes? */
238     fprintf(stderr, "%s[%d]:  partial ? write error, %zd bytes, should be %zu\n",
239             __FILE__, __LINE__, res, sz);
240     return -1;
241   }
242   return 0;
243 }
244
245 void *map_region(void *addr, int len, int fd) {
246      void *result;
247      result = mmap(addr, len, PROT_READ|PROT_WRITE|PROT_EXEC, 
248                    DYNINSTheap_mmapFlags, fd, 0);
249      if (result == MAP_FAILED)
250          return NULL;
251      return result;
252 }
253
254 int unmap_region(void *addr, int len) {
255     int result;
256     result = munmap(addr, len);
257     if (result == -1)
258         return 0;
259     return 1;
260 }
261
262 #if defined(cap_mutatee_traps)
263 extern void dyninstTrapHandler(int sig, siginfo_t *info, void *context);
264
265 int DYNINSTinitializeTrapHandler()
266 {
267    int result;
268    struct sigaction new_handler;
269
270    new_handler.sa_sigaction = dyninstTrapHandler;
271    //new_handler.sa_restorer = NULL; obsolete
272    sigemptyset(&new_handler.sa_mask);
273    new_handler.sa_flags = SA_SIGINFO | SA_NODEFER;
274    
275    result = sigaction(SIGTRAP, &new_handler, NULL);
276    return (result == 0) ? 1 /*Success*/ : 0 /*Fail*/ ;
277 }
278
279 #endif