Update copyright to LGPL on all files
[dyninst.git] / testsuite / src / instruction / test_instruction_bind_eval.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 #include "instruction_comp.h"
33 #include "test_lib.h"
34
35 #include "Instruction.h"
36 #include "InstructionDecoder.h"
37 #include "Expression.h"
38 #include "Result.h"
39
40 //#include <dyn_detail/boost/assign/list_of.hpp>
41 //#include <dyn_detail/boost/iterator/indirect_iterator.hpp>
42 #include <boost/assign/list_of.hpp>
43 #include <boost/iterator/indirect_iterator.hpp>
44
45 using namespace Dyninst;
46 using namespace InstructionAPI;
47 using namespace boost::assign;
48 using namespace boost;
49
50 using namespace std;
51
52 class test_instruction_bind_eval_Mutator : public InstructionMutator {
53 public:
54    test_instruction_bind_eval_Mutator() { };
55    virtual test_results_t executeTest();
56 };
57
58 extern "C" DLLEXPORT TestMutator* test_instruction_bind_eval_factory()
59 {
60    return new test_instruction_bind_eval_Mutator();
61 }
62
63 template <typename T>
64 struct shared_ptr_lt
65 {
66   bool operator()(const T& lhs, const T& rhs)
67   {
68     // Non-nulls precede nulls
69     if(rhs.get() == NULL)
70     {
71       return lhs.get() != NULL;
72     }
73     if(lhs.get() == NULL)
74       return false;
75     // Otherwise, dereference and compare
76     return *lhs < *rhs;
77   }
78   
79 };
80
81
82 typedef std::set<RegisterAST::Ptr, shared_ptr_lt<RegisterAST::Ptr> > registerSet;
83
84 test_results_t failure_accumulator(test_results_t lhs, test_results_t rhs)
85 {
86   if(lhs == FAILED || rhs == FAILED)
87   {
88     return FAILED;
89   }
90   return PASSED;
91 }
92
93 test_results_t verifyCFT(Expression::Ptr cft, bool expectedDefined, unsigned long expectedValue, Result_Type expectedType)
94 {
95   Result cftResult = cft->eval();
96   if(cftResult.defined != expectedDefined) {
97     logerror("FAILED: expected result defined %s, actual %s\n", expectedDefined ? "true" : "false", 
98              cftResult.defined ? "true" : "false");
99     return FAILED;
100   }
101   if(expectedDefined)
102   {
103     if(cftResult.type != expectedType)
104     {
105       logerror("FAILED: expected result type %d, actual %d\n", expectedType, cftResult.type);
106       return FAILED;
107     }
108     if(cftResult.convert<unsigned long>() != expectedValue)
109     {
110       logerror("FAILED: expected result value 0x%x, actual 0x%x\n", expectedValue, cftResult.convert<unsigned long>());
111       return FAILED;
112     }
113   }
114   return PASSED;
115 }
116
117
118 test_results_t test_instruction_bind_eval_Mutator::executeTest()
119 {
120   const unsigned char buffer[] = 
121   {
122     0xFF, 0x94, 0xC1, 0xEF, 0xBE, 0xAD, 0xDE // call [8*EAX + ECX + 0xDEADBEEF]
123   };
124   unsigned int size = 7;
125   unsigned int expectedInsns = 2;
126   InstructionDecoder d(buffer, size);
127 #if defined(arch_x86_64_test)
128   d.setMode(true);
129 #else
130   d.setMode(false);
131 #endif
132   std::vector<Instruction::Ptr> decodedInsns;
133   Instruction::Ptr i;
134   do
135   {
136     i = d.decode();
137     decodedInsns.push_back(i);
138   }
139   while(i && i->isValid());
140   if(decodedInsns.size() != expectedInsns)
141   {
142     logerror("FAILED: Expected %d instructions, decoded %d\n", expectedInsns, decodedInsns.size());
143     for(std::vector<Instruction::Ptr>::iterator curInsn = decodedInsns.begin();
144         curInsn != decodedInsns.end();
145         ++curInsn)
146     {
147       logerror("\t%s\n", (*curInsn)->format().c_str());
148     }
149     
150     return FAILED;
151   }
152   if(decodedInsns.back() && decodedInsns.back()->isValid())
153   {
154     logerror("FAILED: Expected instructions to end with an invalid instruction, but they didn't");
155     return FAILED;
156   }
157
158   Expression::Ptr theCFT = decodedInsns[0]->getControlFlowTarget();
159   if(!theCFT) {
160     logerror("FAILED: instruction %s decoded from call [8*EAX + ECX + 0xDEADBEEF], no CFT found\n", decodedInsns[0]->format().c_str());
161     return FAILED;
162   }
163   if(verifyCFT(theCFT, false, 0x1000, u32) == FAILED)
164   {
165     return FAILED;
166   }
167   
168     
169 #if defined(arch_x86_64_test)
170   RegisterAST* eax = new RegisterAST(r_RAX);
171   RegisterAST* ecx = new RegisterAST(r_RCX);
172 #else
173   RegisterAST* eax = new RegisterAST(r_EAX);
174   RegisterAST* ecx = new RegisterAST(r_ECX);
175 #endif
176   Result three(u32, 3);
177   Result five(u32, 5);
178   
179   if(!theCFT->bind(eax, three)) {
180       logerror("FAILED: bind of EAX failed (insn %s)\n", decodedInsns[0]->format().c_str());
181     return FAILED;
182   }
183   if(verifyCFT(theCFT, false, 0x1000, u32) == FAILED)
184   {
185     return FAILED;
186   }
187   if(!theCFT->bind(ecx, five)) {
188     logerror("FAILED: bind of ECX failed\n");
189     return FAILED;
190   }
191   if(verifyCFT(theCFT, false, 0x1000, u32) == FAILED)
192   {
193     return FAILED;
194   }
195   vector<InstructionAST::Ptr> tmp;
196   theCFT->getChildren(tmp);
197   if(tmp.size() != 1)
198   {
199     logerror("FAILED: expected dereference with one child, got %d children\n", tmp.size());
200     return FAILED;
201   }
202   Expression::Ptr memRef = dyn_detail::boost::dynamic_pointer_cast<Expression>(tmp[0]);
203   if(!memRef) {
204     logerror("FAILED: memRef was not an expression\n");
205     return FAILED;
206   }
207   if(verifyCFT(memRef, true, 0xDEADBEEF + (0x03 * 0x08 + 0x05), u32) == FAILED) {
208     return FAILED;
209   }
210
211   return PASSED;
212 }
213