Rename newtestsuite to testsuite
[dyninst.git] / testsuite / src / dyninst / test_stack_3.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 // $Id: test_stack_3.C,v 1.1 2008/10/30 19:22:22 legendre Exp $
43 /*
44  * #Name: test8_3
45  * #Desc: getCallStack through instrumentation
46  * #Dep: 
47  * #Arch: !(arch_alpha && os_osf_test)
48  * #Notes:
49  */
50
51 #include "BPatch.h"
52 #include "BPatch_Vector.h"
53 #include "BPatch_thread.h"
54 #include "BPatch_snippet.h"
55
56 #include "test_lib.h"
57
58 #include "dyninst_comp.h"
59 class test_stack_3_Mutator : public DyninstMutator {
60 private:
61   BPatch *bpatch;
62
63 public:
64   virtual bool hasCustomExecutionPath() { return true; }
65   virtual test_results_t setup(ParameterDict &param);
66   virtual test_results_t executeTest();
67 };
68 extern "C" DLLEXPORT TestMutator *test_stack_3_factory() {
69   return new test_stack_3_Mutator();
70 }
71
72 #if defined( DEBUG )
73 #include <sys/ptrace.h>
74 #endif
75 // static int mutatorTest( BPatch_thread * appThread, BPatch_image * appImage ) {
76 test_results_t test_stack_3_Mutator::executeTest() {
77   bool passedTest;
78
79   appThread->continueExecution();
80   static const frameInfo_t correct_frame_info[] = {
81         
82 #if defined( os_linux_test ) && (defined( arch_x86_test ) || defined( arch_x86_64_test ))
83     { true, true, BPatch_frameNormal, "_dl_sysinfo_int80" },
84 #endif
85 #if defined( os_aix_test ) && defined( arch_power_test )
86     /* AIX uses kill(), but the PC of a process in a syscall can
87        not be correctly determined, and appears to be the address
88        to which the syscall function will return. */
89 #elif defined( os_windows_test ) && (defined( arch_x86 ) || defined( arch_x86_64_test ))
90     /* Windows/x86 does not use kill(), so its lowermost frame will be 
91        something unidentifiable in a system DLL. */
92     { false, false, BPatch_frameNormal, NULL },
93 #else
94     { true, false, BPatch_frameNormal, "kill" },        
95 #endif
96 #if ! defined( os_windows_test )
97     /* Windows/x86's stop_process_() calls DebugBreak(); it's 
98        apparently normal to lose this frame. */
99     { true, false, BPatch_frameNormal, "stop_process_" },
100 #endif
101     { true, false, BPatch_frameNormal, "test_stack_3_func3" },
102     { true, false, BPatch_frameTrampoline, NULL },
103     /* On AIX and x86 (and others), if our instrumentation fires
104        before frame construction or after frame destruction, it's 
105        acceptable to not report the function (since, after all, it
106        doesn't have a frame on the stack. */
107     { true, true, BPatch_frameNormal, "test_stack_3_func2" },
108     { true, false, BPatch_frameNormal, "test_stack_3_func1" },
109     { true, false, BPatch_frameNormal, "test_stack_3_mutateeTest" },
110     { true, false, BPatch_frameNormal, "main" }
111   };
112         
113   /* Wait for the mutatee to stop in test_stack_3_func1(). */
114   if (waitUntilStopped( bpatch, appThread, 1, "getCallStack through instrumentation") < 0) {
115     appThread->getProcess()->terminateExecution();
116     return FAILED;
117   }
118         
119   /* Instrument test_stack_3_func2() to call test_stack_3_func3(), which will trip another breakpoint. */
120   BPatch_Vector<BPatch_function *> instrumentedFunctions;       
121   char *fName = "test_stack_3_func2";
122   appImage->findFunction(fName, instrumentedFunctions );
123   if (instrumentedFunctions.size() != 1) {
124     // FIXME Print out a useful error message
125     logerror("**Failed** test_stack_3\n");
126     logerror("    Unable to find function '%s'\n", fName);
127     appThread->getProcess()->terminateExecution();
128     return FAILED;
129   }
130         
131   BPatch_Vector<BPatch_point *> * functionEntryPoints = instrumentedFunctions[0]->findPoint( BPatch_entry );
132   if (functionEntryPoints->size() != 1) {
133     // FIXME Print out a useful error message
134     logerror("**Failed** test_stack_3\n");
135     logerror("    Unable to find entry point to function '%s'\n", fName);
136     appThread->getProcess()->terminateExecution();
137     return FAILED;
138   }
139         
140   BPatch_Vector<BPatch_function *> calledFunctions;
141   char *fName2 = "test_stack_3_func3";
142   appImage->findFunction(fName2, calledFunctions );
143   if (calledFunctions.size() != 1) {
144     //FIXME Print out a useful error message
145     logerror("**Failed** test_stack_3\n");
146     logerror("    Unable to find function '%s'\n", fName2);
147     appThread->getProcess()->terminateExecution();
148     return FAILED;
149   }
150         
151   BPatch_Vector<BPatch_snippet *> functionArguments;
152   BPatch_funcCallExpr functionCall( * calledFunctions[0], functionArguments );
153         
154   appThread->insertSnippet( functionCall, functionEntryPoints[0] );
155
156   /* Repeat for all three types of instpoints. */
157   BPatch_Vector<BPatch_point *> * functionCallPoints = instrumentedFunctions[0]->findPoint( BPatch_subroutine );
158   if (functionCallPoints->size() != 1) {
159     logerror("**Failed** test_stack_3\n");
160     logerror("    Unable to find subroutine call points in '%s'\n", fName);
161     appThread->getProcess()->terminateExecution();
162     return FAILED;
163   }
164   appThread->insertSnippet( functionCall, functionCallPoints[0] );
165         
166   BPatch_Vector<BPatch_point *> * functionExitPoints = instrumentedFunctions[0]->findPoint( BPatch_exit );
167   if (functionExitPoints->size() != 1) {
168     logerror("**Failed** test_stack_3\n");
169     logerror("    Unable to find exit points in '%s'\n", fName);
170     appThread->getProcess()->terminateExecution();
171     return FAILED;
172   }
173   appThread->insertSnippet( functionCall, functionExitPoints[0] );
174
175 #if defined( DEBUG )
176   for( int i = 0; i < 80; i++ ) { ptrace( PTRACE_SINGLESTEP, appThread->getPid(), NULL, NULL ); }
177         
178   for( int i = 80; i < 120; i++ ) {
179     ptrace( PTRACE_SINGLESTEP, appThread->getPid(), NULL, NULL );
180                 
181     BPatch_Vector<BPatch_frame> stack;
182     appThread->getCallStack( stack );
183                 
184     dprintf("single-step stack walk, %d instructions after stop for instrumentation.\n", i );
185     for( unsigned i = 0; i < stack.size(); i++ ) {
186       char name[ 40 ];
187       BPatch_function * func = stack[i].findFunction();
188                 
189       if( func == NULL ) { strcpy( name, "[UNKNOWN]" ); }
190       else { func->getName( name, 40 ); }
191                         
192       dprintf("  %10p: %s, fp = %p\n", stack[i].getPC(), name, stack[i].getFP() );
193     } /* end stack walk dumper */
194     dprintf("end of stack walk.\n" );
195   } /* end single-step iterator */
196 #endif /* defined( DEBUG ) */           
197
198   /* After inserting the instrumentation, let it be called. */
199   appThread->continueExecution();
200           
201   /* Wait for the mutatee to stop because of the instrumentation we just inserted. */
202   if (waitUntilStopped( bpatch, appThread, 1, "getCallStack through instrumentation (entry)") < 0) {
203     appThread->getProcess()->terminateExecution();
204     return FAILED;
205   }
206
207   passedTest = true;
208   if( !checkStack( appThread, correct_frame_info,
209                    sizeof(correct_frame_info)/sizeof(frameInfo_t),
210                    3, "getCallStack through instrumentation (entry)" ) ) {
211     passedTest = false;
212   }
213
214   /* Repeat for other two types of instpoints. */
215   appThread->continueExecution();       
216
217   /* Wait for the mutatee to stop because of the instrumentation we just inserted. */
218   if (waitUntilStopped( bpatch, appThread, 1, "getCallStack through instrumentation (call)") < 0) {
219     appThread->getProcess()->terminateExecution();
220     return FAILED;
221   }
222
223   if( !checkStack( appThread, correct_frame_info,
224                    sizeof(correct_frame_info)/sizeof(frameInfo_t),
225                    3, "getCallStack through instrumentation (call)" ) ) {
226     passedTest = false;
227   }
228         
229   appThread->continueExecution();       
230
231   /* Wait for the mutatee to stop because of the instrumentation we just inserted. */
232   if (waitUntilStopped( bpatch, appThread, 1, "getCallStack through instrumentation (exit)") < 0) {
233     appThread->getProcess()->terminateExecution();
234     return FAILED;
235   }
236
237   if( !checkStack( appThread, correct_frame_info,
238                    sizeof(correct_frame_info)/sizeof(frameInfo_t),
239                    3, "getCallStack through instrumentation (exit)" ) ) {
240     passedTest = false;
241   }
242
243   if (passedTest)
244     logerror("Passed test #3 (unwind through base and mini tramps)\n");
245
246   /* Return the mutatee to its normal state. */
247   appThread->continueExecution();       
248
249   while (!appThread->isTerminated()) {
250     // Workaround for issue with pgCC_high mutatee
251     bpatch->waitForStatusChange();
252   }
253
254   if (passedTest)
255     return PASSED;
256   return FAILED;
257 } /* end mutatorTest3() */
258
259 // External Interface
260 test_results_t test_stack_3_Mutator::setup(ParameterDict &param) {
261   DyninstMutator::setup(param);
262   bpatch = (BPatch *)(param["bpatch"]->getPtr());
263   return PASSED;
264 }