Sets the brk pointer for save-the-world binaries to what it was when each
[dyninst.git] / dyninstAPI_RT / src / RTsolaris.c
1 /*
2  * Copyright (c) 1996-2004 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  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 /************************************************************************
43  * $Id: RTsolaris.c,v 1.23 2006/01/13 00:00:48 jodom Exp $
44  * RTsolaris.c: mutatee-side library function specific to Solaris
45  ************************************************************************/
46
47 #include "dyninstAPI_RT/h/dyninstAPI_RT.h"
48
49 #include <signal.h>
50 #include <sys/ucontext.h>
51 #include <assert.h>
52 #include <stdio.h>
53 #include <dlfcn.h>
54
55 #include <sys/procfs.h> /* /proc PIOCUSAGE */
56 #include <fcntl.h> /* O_RDONLY */
57 #include <unistd.h> /* getpid() */
58
59
60 #ifdef i386_unknown_solaris2_5
61 void DYNINSTtrapHandler(int sig, siginfo_t *info, ucontext_t *uap);
62
63 extern struct sigaction DYNINSTactTrap;
64 extern struct sigaction DYNINSTactTrapApp;
65 #endif
66
67 /************************************************************************
68  * void DYNINSTos_init(void)
69  *
70  * OS initialization function
71 ************************************************************************/
72
73 extern void DYNINSTheap_setbounds();  /* RTheap-solaris.c */
74
75 void
76 DYNINSTos_init(int calledByFork, int calledByAttach)
77 {
78     RTprintf("DYNINSTos_init(%d,%d)\n", calledByFork, calledByAttach);
79     DYNINSTheap_setbounds();
80     /* uncomment this if you want instrumentation written out in core files */
81     /* setmemwrite(); */
82 }
83
84 int DYNINSTloadLibrary(char *libname)
85 {
86   void *res;
87   char *err_str;
88   gLoadLibraryErrorString[0]='\0';
89   gBRKptr = sbrk(0);
90   
91   if (NULL == (res = dlopen(libname, RTLD_NOW | RTLD_GLOBAL))) {
92     /* An error has occurred */
93     perror( "DYNINSTloadLibrary -- dlopen" );
94     
95     if (NULL != (err_str = dlerror()))
96       strncpy(gLoadLibraryErrorString, err_str, ERROR_STRING_LENGTH);
97     else 
98       sprintf(gLoadLibraryErrorString,"unknown error with dlopen");
99     
100     fprintf(stderr, "%s[%d]: %s\n",__FILE__,__LINE__,gLoadLibraryErrorString);
101     return 0;  
102   } else
103     return 1;
104 }
105
106
107 /*
108 We can get Solaris to put instrumented code in the core file of dumped
109 mutatees by setting setting WRITE protection on all pages in the
110 process (SHARED text pages cannot have WRITE protect set).
111
112 To use, compile and link this code with the runtime library, and call
113 setmemwrite from DYNINSTinit.
114 */
115
116 /* Set every page in this process to be writable to
117    cause pages with instrumented code to be saved in core dumps. */
118 #include <sys/types.h>
119 #include <sys/mman.h>
120 #include <sys/procfs.h>
121 #define maxpmap 512
122 static
123 int setmemwrite()
124 {
125     int pfd, numpmap, i;
126     prmap_t pmap[maxpmap];
127
128     char buf[32];
129     sprintf(buf, "/proc/%05d", getpid());
130     pfd = open(buf, O_RDONLY);
131     if (0 > pfd) {
132          perror("open (in setmemwrite)");
133          fprintf(stderr, "Can't open /proc on myself\n");
134          exit(1);
135     }
136     if (0 > ioctl(pfd, PIOCNMAP, &numpmap)) {
137          perror("PIOCNMAP (in setmemwrite)");
138          exit(1);
139     }
140     if (numpmap + 1 > maxpmap) {
141          fprintf(stderr, "Too many memory mappings\n");
142          exit(1);
143     }
144     if (0 > ioctl(pfd, PIOCMAP, pmap)) {
145          perror("PIOCMAP (in setmemwrite)");
146          exit(1);
147     }
148     for (i = 0; i < numpmap; i++) {
149          prmap_t *p = &pmap[i];
150          /* Enable WRITE if this region does not have it already and
151             we won't get in trouble for setting it (i.e., it is not
152             SHARED). */
153          if (~p->pr_mflags & MA_WRITE
154              && ~p->pr_mflags & MA_SHARED)
155               if (0 > mprotect(p->pr_vaddr, p->pr_size,
156                                PROT_WRITE
157                                | PROT_READ
158                                | (p->pr_mflags & MA_EXEC ? PROT_EXEC : 0))) {
159                    perror("mprotect (in setmemwrite)");
160                    fprintf(stderr, "mprotect (it %d) args: %#010x, %x, %x\n",
161                            i,
162                            p->pr_vaddr, p->pr_size, 
163                            PROT_WRITE
164                            | PROT_READ
165                            | (p->pr_mflags & MA_EXEC ? PROT_EXEC : 0));
166                    exit(1);
167               }
168     }
169     close(pfd);
170     return 0;
171 }
172
173 int dyn_pthread_self()
174 {
175      return 0;
176 }
177
178 void DYNINST_initialize_index_list()
179 {
180 }
181
182 int dyn_pid_self()
183 {
184    return getpid();
185 }
186