Update copyright to LGPL on all files
[dyninst.git] / testsuite / src / dyninst / test1_40.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 // $Id: test1_40.C,v 1.1 2008/10/30 19:19:35 legendre Exp $
33 /*
34  * #Name: test1_40
35  * #Desc: Verify that we can monitor call sites
36  * #Dep: 
37  * #Arch: !,alpha_dec_osf4_0_test,ia64_unknown_linux2_4_test,!mips_sgi_irix6_4_test,os_windows
38  * #Notes:
39  */
40
41 #include "BPatch.h"
42 #include "BPatch_Vector.h"
43 #include "BPatch_thread.h"
44 #include "BPatch_snippet.h"
45
46 #include "test_lib.h"
47 #include "dyninst_comp.h"
48
49 class test1_40_Mutator : public DyninstMutator {
50         virtual test_results_t setup(ParameterDict &param);
51         virtual test_results_t executeTest();
52 };
53
54 extern "C" DLLEXPORT  TestMutator *test1_40_factory() 
55 {
56         return new test1_40_Mutator();
57 }
58
59 //
60 //  Test case 40:  verify that we can monitor call sites
61 //
62
63 static BPatch_function *findFunction40(const char *fname, 
64                 BPatch_image *appImage)
65 {
66         BPatch_Vector<BPatch_function *> bpfv;
67         if (NULL == appImage->findFunction(fname, bpfv) || (bpfv.size() != 1)) 
68         {
69
70                 logerror("**Failed test #40 (monitor call sites)\n");
71                 logerror("  Expected 1 functions matching %s, got %d\n",
72                                 fname, bpfv.size());
73                 return NULL;
74         }
75         return bpfv[0];
76 }
77
78 static int setVar40(const char *vname, void *value, BPatch_image *appImage)
79 {
80         BPatch_variableExpr *v;
81         void *buf = value;
82
83         if (NULL == (v = appImage->findVariable(vname))) 
84         {
85                 logerror("**Failed test #40 (monitor call sites)\n");
86                 logerror("  cannot find variable %s\n", vname);
87                 return -1;
88         }
89
90         // Get around endianness on cross address-width mutators.
91         // Note: Can't use reinterpret_cast here.  G++ produces an error:
92         //   reinterpret_cast from `void*' to `unsigned int' loses precision
93
94         unsigned long longAddr = (unsigned long)(value);
95         unsigned int shortAddr = (unsigned  int)(unsigned long)(value);
96
97         switch (v->getSize()) {
98                 case 4: buf = reinterpret_cast<void *>(&shortAddr); break;
99                 case 8: buf = reinterpret_cast<void *>(&longAddr);  break;
100                 default: assert(0 && "Invalid size of mutatee address variable");
101         }
102
103         // Done silly casting magic.  Write the value.
104         if (! v->writeValue(buf, sizeof(unsigned int),false)) 
105         {
106                 logerror("**Failed test #40 (monitor call sites)\n");
107                 logerror("  failed to write call site var to mutatee\n");
108                 return -1;
109         }
110
111         return 0;
112 }
113
114 #ifdef RETURNONFAIL
115 #undef RETURNONFAIL
116 #endif
117 #define RETURNONFAIL(expr) if((expr) < 0) return FAILED
118
119 test_results_t test1_40_Mutator::executeTest() 
120 {
121         const char *monitorFuncName = "test1_40_monitorFunc";
122         const char *callSiteAddrVarName = "test1_40_callsite5_addr";
123
124         BPatch_function *monitorFunc = NULL;
125         BPatch_Vector<BPatch_function *> bpfv;
126
127         BPatch_function *call40_1 = findFunction40("test1_40_call1", appImage);
128         RETURNONNULL(call40_1);
129         RETURNONFAIL(setVar40("test1_40_addr_of_call1", call40_1->getBaseAddr(),appImage));
130
131         BPatch_function *call40_2 = findFunction40("test1_40_call2", appImage);
132         RETURNONNULL(call40_2);
133         RETURNONFAIL(setVar40("test1_40_addr_of_call2", call40_2->getBaseAddr(),appImage));
134
135         BPatch_function *call40_3 = findFunction40("test1_40_call3", appImage);
136         RETURNONNULL(call40_3);
137         RETURNONFAIL(setVar40("test1_40_addr_of_call3", call40_3->getBaseAddr(),appImage));
138
139         //  call40_5 is the "dispatcher" of function pointers
140         BPatch_function *targetFunc = findFunction40("test1_40_call5", appImage);
141         RETURNONNULL(targetFunc);
142         //RETURNONFAIL(setVar40("test1_40_addr_of_call5", call40_5->getBaseAddr(),appImage));
143
144         monitorFunc = findFunction40(monitorFuncName, appImage);
145         RETURNONNULL(monitorFunc);
146
147         BPatch_Vector<BPatch_point *> *calls = targetFunc->findPoint(BPatch_subroutine);
148         if (!calls) 
149         {
150                 logerror("**Failed test #40 (monitor call sites)\n");
151                 logerror("  cannot find call points for test1_40_call5\n");
152                 return FAILED;
153         }
154
155         BPatch_Vector<BPatch_point *> dyncalls;
156         for (unsigned int i = 0; i < calls->size(); ++i) 
157         {
158                 BPatch_point *pt = (*calls)[i];
159                 if (pt->isDynamic())
160                         dyncalls.push_back(pt);
161         }
162
163         if (dyncalls.size() != 1) 
164         {
165                 logerror("**Failed test #40 (monitor call sites)\n");
166                 logerror("  wrong number of dynamic points found (%d -- not 1)\n",
167                                 dyncalls.size());
168                 logerror("  total number of calls found: %d\n", calls->size());
169                 return FAILED;
170         }
171
172         // write address of anticipated call site into mutatee var.
173         void *callsite_address = dyncalls[0]->getAddress();
174         RETURNONFAIL(setVar40(callSiteAddrVarName, callsite_address, appImage));
175
176         //  issue command to monitor calls at this site, and we're done.
177         if (! dyncalls[0]->monitorCalls(monitorFunc)) 
178         {
179                 logerror("**Failed test #40 (monitor call sites)\n");
180                 logerror("  cannot monitor calls\n");
181                 return FAILED;
182         }
183
184         return PASSED;
185 }
186
187 // External Interface
188
189 test_results_t test1_40_Mutator::setup(ParameterDict &param) 
190 {
191         bool useAttach = param["useAttach"]->getInt() == USEATTACH;
192         appThread = (BPatch_thread *)(param["appThread"]->getPtr());
193         int mutateeXLC = param["mutateeXLC"]->getInt();
194
195         // xlc does not produce the intended dynamic call points for this example
196         if (mutateeXLC) 
197         {
198                 return SKIPPED;
199         }
200
201         // Read the program's image and get an associated image object
202         appImage = appThread->getImage();
203
204         if (isMutateeFortran(appImage)) 
205         {
206                 return SKIPPED;
207         }
208
209         if ( useAttach )
210         {
211                 if ( ! signalAttached(appThread, appImage) )
212                         return FAILED;
213         }
214
215         // Run mutator code
216         return PASSED;
217 }