Need to flush trap mapping table into the mutatee after instrumentation for registeri...
[dyninst.git] / dyninstAPI / src / syscallNotification.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 // $Id: syscall-linux.C,v 1.20 2008/05/28 17:14:19 legendre Exp $
32
33 #include "common/src/headers.h"
34 #include "dyninstAPI/src/inst.h"
35 #include "dyninstAPI/src/syscallNotification.h"
36 #include "dyninstAPI/src/dynProcess.h"
37 #include "dyninstAPI/src/ast.h"
38
39 #include "EventType.h"
40 #include "dyninstAPI/src/pcEventMuxer.h"
41 #include "patchAPI/h/PatchMgr.h"
42 #include "patchAPI/h/Point.h"
43
44 using namespace ProcControlAPI;
45 using namespace PatchAPI;
46
47
48 syscallNotification::syscallNotification(syscallNotification *parentSN,
49                                          PCProcess *child) : preForkInst(NULL),
50                                                            postForkInst(NULL),
51                                                            preExecInst(NULL),
52                                                            postExecInst(NULL),
53                                                            preExitInst(NULL),
54                                                            preLwpExitInst(NULL),
55                                                            proc(child) {
56     // We need to copy over the instMappings and get the new miniTramps from
57     // the parent process
58     // We don't copy the instMappings, but make new copies.
59   if (parentSN->preForkInst) {
60     preForkInst = new instMapping(parentSN->preForkInst, child);
61   }
62   if (parentSN->postForkInst) {
63     postForkInst = new instMapping(parentSN->postForkInst, child);
64   }
65   if (parentSN->preExecInst) {
66     preExecInst = new instMapping(parentSN->preExecInst, child);
67   }
68   if (parentSN->postExecInst) {
69     postExecInst = new instMapping(parentSN->postExecInst, child);
70   }
71   if (parentSN->preExitInst) {
72     preExitInst = new instMapping(parentSN->preExitInst, child);
73   }
74   if (parentSN->preLwpExitInst) {
75     preLwpExitInst = new instMapping(parentSN->preLwpExitInst, child);
76   }
77 }
78
79 /////////// Prefork instrumentation 
80
81 bool syscallNotification::installPreFork() {
82   if (!PCEventMuxer::useBreakpoint(EventType(EventType::Pre, EventType::Fork))) {
83     return true;
84   }
85
86    preForkInst = new instMapping(getForkFuncName(),
87                                  "DYNINST_instForkEntry",
88                                  FUNC_ENTRY);
89    preForkInst->dontUseTrampGuard();
90    pdvector<instMapping *> instReqs;
91    instReqs.push_back(preForkInst);
92    
93    proc->installInstrRequests(instReqs);
94    proc->trapMapping.flush();
95
96    return true;
97 }
98
99 /////////// Postfork instrumentation
100
101 bool syscallNotification::installPostFork() {
102    if (!PCEventMuxer::useBreakpoint(EventType(EventType::Post, EventType::Fork))) return true;
103
104    AstNodePtr returnVal = AstNode::operandNode(AstNode::ReturnVal, (void *)0);
105    postForkInst = new instMapping(getForkFuncName(), "DYNINST_instForkExit",
106                                   FUNC_EXIT|FUNC_ARG,
107                                   returnVal);
108    postForkInst->dontUseTrampGuard();
109    postForkInst->canUseTrap(false);
110    
111    pdvector<instMapping *> instReqs;
112    instReqs.push_back(postForkInst);
113    
114    proc->installInstrRequests(instReqs);
115    proc->trapMapping.flush();
116
117    return true;
118 }    
119
120 /////////// Pre-exec instrumentation
121
122 bool syscallNotification::installPreExec() {
123    if (!PCEventMuxer::useBreakpoint(EventType(EventType::Pre, EventType::Exec))) return true;
124    AstNodePtr arg0 = AstNode::operandNode(AstNode::Param, (void *)0);
125    preExecInst = new instMapping(getExecFuncName(), "DYNINST_instExecEntry",
126                                  FUNC_ENTRY|FUNC_ARG,
127                                  arg0);
128    preExecInst->dontUseTrampGuard();
129    
130    pdvector<instMapping *> instReqs;
131    instReqs.push_back(preExecInst);
132    
133    proc->installInstrRequests(instReqs);
134    proc->trapMapping.flush();
135
136    return true;
137 }    
138
139 //////////// Post-exec instrumentation
140
141 bool syscallNotification::installPostExec() {
142     // OS-handled
143     postExecInst = NULL;
144     return true;
145 }    
146
147 /////////// Pre-exit instrumentation
148
149 bool syscallNotification::installPreExit() {
150    if (!PCEventMuxer::useBreakpoint(EventType(EventType::Pre, EventType::Exit))) return true;
151    AstNodePtr arg0 = AstNode::operandNode(AstNode::Param, (void *)0);
152    preExitInst = new instMapping(getExitFuncName(), "DYNINST_instExitEntry",
153                                  FUNC_ENTRY|FUNC_ARG,
154                                  arg0);
155    preExitInst->dontUseTrampGuard();
156    
157    preExitInst->allow_trap = true;
158    
159    pdvector<instMapping *> instReqs;
160    instReqs.push_back(preExitInst);
161    
162    proc->installInstrRequests(instReqs);
163    proc->trapMapping.flush();
164
165    return true;
166 }    
167
168 bool syscallNotification::installPreLwpExit() {
169    preLwpExitInst = NULL;
170    return true;
171 }
172
173 //////////////////////////////////////////////////////
174
175 /////// Remove pre-fork instrumentation
176
177 bool syscallNotification::removePreFork() {
178    if (!PCEventMuxer::useBreakpoint(EventType(EventType::Pre, EventType::Fork))) return true;
179
180     if (!preForkInst) return false;
181
182     if (!proc->isAttached() || proc->isExecing()) {
183         delete preForkInst;
184         preForkInst = NULL;
185         return true;
186     }
187     
188     
189     InstancePtr handle;
190     for (unsigned i = 0; i < preForkInst->instances.size(); i++) {
191        handle = preForkInst->instances[i];
192         
193        bool removed = uninstrument(handle);
194        // At some point we should handle a negative return... but I
195        // have no idea how.
196        assert(removed);
197        // The instance is deleted when the instance is freed, so
198        // we don't have to.
199     }
200     //proc->relocate();
201     /* PatchAPI stuffs */
202     AddressSpace::patch(proc);
203     /* End of PatchAPI stuffs */
204
205
206     delete preForkInst;
207     preForkInst = NULL;
208     return true;
209 }
210
211     
212
213 /////// Remove post-fork instrumentation
214
215 bool syscallNotification::removePostFork() {
216    if (!PCEventMuxer::useBreakpoint(EventType(EventType::Post, EventType::Fork))) return true;
217
218     if (!postForkInst) return false;
219
220     if (!proc->isAttached() || proc->isExecing()) {
221         delete postForkInst;
222         postForkInst = NULL;
223         return true;
224     }
225
226     InstancePtr handle;
227     for (unsigned i = 0; i < postForkInst->instances.size(); i++) {
228        handle = postForkInst->instances[i];
229         
230        bool removed = uninstrument(handle);
231        // At some point we should handle a negative return... but I
232        // have no idea how.
233        assert(removed);
234        // The instance is deleted when the instance is freed, so
235        // we don't have to.
236     }
237     //proc->relocate();
238     /* PatchAPI stuffs */
239     AddressSpace::patch(proc);
240     /* End of PatchAPI stuffs */
241
242     delete postForkInst;
243     postForkInst = NULL;
244     return true;
245 }
246
247 /////// Remove pre-exec instrumentation
248
249 bool syscallNotification::removePreExec() {
250    if (!PCEventMuxer::useBreakpoint(EventType(EventType::Pre, EventType::Exec))) return true;
251
252     if (!preExecInst) return false;
253
254     if (!proc->isAttached() || proc->isExecing()) {
255         delete preExecInst;
256         preExecInst = NULL;
257         return true;
258     }
259
260     InstancePtr handle;
261     for (unsigned i = 0; i < preExecInst->instances.size(); i++) {
262        handle = preExecInst->instances[i];
263         
264        bool removed = uninstrument(handle);
265        // At some point we should handle a negative return... but I
266        // have no idea how.
267        assert(removed);
268        // The instance is deleted when the instance is freed, so
269        // we don't have to.
270     }
271     //proc->relocate();
272     /* PatchAPI stuffs */
273     AddressSpace::patch(proc);
274     /* End of PatchAPI stuffs */
275
276     delete preExecInst;
277     preExecInst = NULL;
278     return true;
279 }
280
281 /////// Remove post-exec instrumentation
282
283 bool syscallNotification::removePostExec() {
284     // OS traps this, we don't have a choice.
285     return true;
286 }
287
288 /////// Remove pre-exit instrumentation
289
290 bool syscallNotification::removePreExit() {
291    if (!PCEventMuxer::useBreakpoint(EventType(EventType::Pre, EventType::Exit))) return true;
292
293     if( !preExitInst ) return false;
294
295     if (!proc->isAttached() || proc->isExecing()) {
296         delete preExitInst;
297         preExitInst = NULL;
298         return true;
299     }
300     
301     InstancePtr handle;
302     for (unsigned i = 0; i < preExitInst->instances.size(); i++) {
303        handle = preExitInst->instances[i];
304         
305        bool removed = uninstrument(handle);
306        // At some point we should handle a negative return... but I
307        // have no idea how.
308        assert(removed);
309        // The instance is deleted when the instance is freed, so
310        // we don't have to.
311     }
312     //proc->relocate();
313     /* PatchAPI stuffs */
314     AddressSpace::patch(proc);
315     /* End of PatchAPI stuffs */
316
317     delete preExitInst;
318     preExitInst = NULL;
319     return true;
320 }
321
322 bool syscallNotification::removePreLwpExit() {
323    return true;
324 }
325
326 //////////////////////////////////////////////
327