I have done a commit that fixes the "irpc-trap" bug. This bug occurs
[dyninst.git] / dyninstAPI_RT / src / RTsolaris.c
1 /*
2  * Copyright (c) 1996 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.11 2000/03/17 21:56:19 schendel Exp $
44  * RTsolaris.c: mutatee-side library function specific to Solaris
45  ************************************************************************/
46
47 #include <signal.h>
48 #include <sys/ucontext.h>
49 #include <assert.h>
50 #include <stdio.h>
51 #include <dlfcn.h>
52
53 #include <sys/procfs.h> /* /proc PIOCUSAGE */
54 #include <fcntl.h> /* O_RDONLY */
55 #include <unistd.h> /* getpid() */
56
57 #include "dyninstAPI_RT/h/dyninstAPI_RT.h"
58
59 /************************************************************************
60  * void DYNINSTos_init(void)
61  *
62  * os initialization function
63 ************************************************************************/
64
65 extern void DYNINSTheap_setbounds();  /* RTheap-solaris.c */
66
67 void
68 DYNINSTos_init(int calledByFork, int calledByAttach)
69 {
70     /*
71        Install trap handler.
72        This is currently being used only on the x86 platform.
73     */
74 #ifdef i386_unknown_solaris2_5
75     void DYNINSTtrapHandler(int sig, siginfo_t *info, ucontext_t *uap);
76     struct sigaction act;
77     act.sa_handler = DYNINSTtrapHandler;
78     act.sa_flags = 0;
79     sigfillset(&act.sa_mask);
80     if (sigaction(SIGTRAP, &act, 0) != 0) {
81         perror("sigaction(SIGTRAP)");
82         assert(0);
83         abort();
84     }
85 #endif
86
87     DYNINSTheap_setbounds();
88 }
89
90
91 \f
92
93
94 /****************************************************************************
95    The trap handler. Currently being used only on x86 platform.
96
97    Traps are used when we can't insert a jump at a point. The trap
98    handler looks up the address of the base tramp for the point that
99    uses the trap, and set the pc to this base tramp.
100    The paradynd is responsible for updating the tramp table when it
101    inserts instrumentation.
102 *****************************************************************************/
103
104 #ifdef i386_unknown_solaris2_5
105 trampTableEntry DYNINSTtrampTable[TRAMPTABLESZ];
106 unsigned DYNINSTtotalTraps = 0;
107
108 static unsigned lookup(unsigned key) {
109     unsigned u;
110     unsigned k;
111     for (u = HASH1(key); 1; u = (u + HASH2(key)) % TRAMPTABLESZ) {
112       k = DYNINSTtrampTable[u].key;
113       if (k == 0)
114         return 0;
115       else if (k == key)
116         return DYNINSTtrampTable[u].val;
117     }
118     /* not reached */
119 }
120
121 void DYNINSTtrapHandler(int sig, siginfo_t *info, ucontext_t *uap) {
122     unsigned pc = uap->uc_mcontext.gregs[PC];
123     unsigned nextpc;
124
125     /* If we're in the process of running an inferior RPC, we'll
126        ignore the trap here and have the daemon rerun the trap
127        instruction when the inferior rpc is done.  Because the default
128        behavior is for the daemon to reset the PC to it's previous
129        value and the PC is still at the trap instruction, we don't
130        need to make any additional adjustments to the PC in the
131        daemon.
132
133        This is used only on x86 platforms, so if multithreading is
134        ever extended to x86 platforms, then perhaps this would need to
135        be modified for that.  */
136
137     if(curRPC.runningInferiorRPC == 1) {
138       /* If the current PC is somewhere in the RPC then it's a trap that
139          occurred just before the RPC and is just now getting delivered.
140          That is we want to ignore it here and regenerate it later. */
141       if(curRPC.begRPCAddr <= pc && pc <= curRPC.endRPCAddr) {
142       /* If a previous trap didn't get handled on this next irpc (assumes one 
143          trap per irpc) then we have a bug, a trap didn't get regenerated */
144         /* printf("trapHandler, begRPCAddr: %x, pc: %x, endRPCAddr: %x\n",
145            curRPC.begRPCAddr, pc, curRPC.endRPCAddr);
146         */
147         assert(trapNotHandled==0);
148         trapNotHandled = 1; 
149         return;
150       }
151       else  ;   /* a trap occurred as a result of a function call within the */ 
152                 /* irpc, these traps we want to handle */
153     }
154     else { /* not in an irpc */
155       if(trapNotHandled == 1) {
156         /* Ok good, the trap got regenerated.
157            Check to make sure that this trap is the one corresponding to the one
158            that needs to get regenerated.
159         */
160         assert(pcAtLastIRPC == pc);
161         trapNotHandled = 0;
162         /* we'll then continue to process the trap */
163       }
164     }
165     nextpc = lookup(pc);
166
167     if (!nextpc) {
168       /* kludge: maybe the PC was not automatically adjusted after the trap */
169       /* this happens for a forked process */
170       pc--;
171       nextpc = lookup(pc);
172     }
173
174     if (nextpc) {
175       uap->uc_mcontext.gregs[PC] = nextpc;
176     } else {
177       assert(0);
178       abort();
179     }
180     DYNINSTtotalTraps++;
181 }
182 #endif
183
184 int DYNINSTloadLibrary(char *libname)
185 {
186     if (dlopen(libname, RTLD_NOW | RTLD_GLOBAL) != NULL)
187         return 1;
188     else
189         return 0;
190 }
191