Update copyright to LGPL on all files
[dyninst.git] / instructionAPI / src / InstructionTest.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 "../h/InstructionDecoder.h"
33 #include <iostream>
34 #include <dyn_detail/boost/assign.hpp>
35 #include "../h/Register.h"
36
37 using namespace Dyninst::InstructionAPI;
38 using namespace std;
39 using namespace boost::assign;
40
41 template< typename strT >
42 strT& operator<<(strT& s, std::set<RegisterAST::Ptr> regs)
43 {
44   for(std::set<RegisterAST::Ptr>::const_iterator i = regs.begin();
45       i != regs.end();
46       ++i)
47   {
48     s << (*i)->format() << " ";
49   }
50   s << endl;
51   return s;
52 }
53
54
55 class testSuite
56 {
57 public:
58   testSuite() : numTests(0), numFailures(0)
59   {
60   }
61   
62   bool testDecode(InstructionDecoder& testMe, const unsigned char* instruction, int size, const char* name)
63   {
64     Instruction tempInstruction = testMe.decode(instruction, size);
65     return testAssertEqual(name, tempInstruction.format());
66   }
67
68   bool testRegisters(InstructionDecoder& testMe, const unsigned char* instruction, int size, 
69                      set<RegisterAST::Ptr> expectedRead, set<RegisterAST::Ptr> expectedWritten)
70   {
71     std::set<RegisterAST::Ptr> actualRead, actualWritten;
72     Instruction testInsn = testMe.decode(instruction, size);
73     testInsn.getReadSet(actualRead);
74     testInsn.getWriteSet(actualWritten);
75     return testAssertEqual(expectedRead, actualRead) && testAssertEqual(expectedWritten, actualWritten);
76   }
77   template< typename T1, typename T2>
78   bool testAssertEqual(boost::shared_ptr<T1> lhs, boost::shared_ptr<T2> rhs)
79   {
80     numTests++;
81     if(*lhs == *rhs)
82     {
83       cout << ".";
84       return true;
85     }
86     else
87     {
88       cout << "F";
89       failureLog << "FAIL: expected " << *lhs << ", actual " << *rhs << endl;
90       numFailures++;
91       return false;
92     }
93   }
94   
95
96   template< typename T1, typename T2 >
97   bool testAssertEqual(T1 lhs, T2 rhs)
98   {
99     numTests++;
100     if(lhs == rhs)
101     {
102       cout << ".";
103       return true;
104     }
105     else
106     {
107       cout << "F";
108       failureLog << "FAIL: expected " << lhs << ", actual " << rhs << endl;
109       numFailures++;
110       return false;
111     }
112   }
113   void printResultsSummary() const
114   {
115     cout << endl;
116     cout << "RESULTS: " << numTests << " tests, " << numFailures << " failures" << endl;
117     if(numFailures)
118     {
119       cout << "FAILURE DETAILS:" << endl;
120       cout << failureLog.str() << endl;
121     }
122     else
123     {
124       cout << "PASSED!" << endl;
125     }
126   }
127   
128 private:
129   std::stringstream failureLog;
130   int numTests;
131   int numFailures;
132   
133 };
134
135
136
137 int main(int argc, char** argv)
138 {
139   InstructionDecoder testMe;
140   const unsigned char MovRegToReg[2] = { 0x89, 0xe5 }; // mov %esp, %ebp
141   const unsigned char MovRegToRegIndirect[2] = { 0x89, 0x01 }; // mov %eax, *%ecx
142   const unsigned char MovRegToRegIndirectOffset[3] = { 0x89, 0x45, 0xd4 }; // mov %eax, 0xffffffd4(%ebp)
143   // mov 0x390(%ecx), %edx
144   const unsigned char MovRegToRegIndirectLongOffset[6] = { 0x8b, 0x91, 0x90, 0x03, 0x00, 0x00 };
145   const unsigned char IndirectCall[2] = { 0xff, 0xd0 }; // call *%eax
146   const unsigned char ConditionalJump[2] = { 0x74, 0x02 }; // je +0x02
147   const unsigned char MovRegToReg2[2] = {0x89, 0xe1}; // move %esp, %ecx
148   const unsigned char UnconditionalJump[2] = {0xeb, 0x14}; // jmp +0x14
149   const unsigned char SIBMove[3] = {0x8b, 0x14, 0xb0}; // mov (%eax, %esi, 4), %edx
150   const unsigned char AddRegImmediate[3] = {0x83, 0xc0, 0x01}; // add $0x1, %eax
151   const unsigned char SubRegImmediate[3] = {0x83, 0xe8, 0x01}; // add $0x1, %eax
152   const unsigned char PushTest[1] = {0x56}; // push %ESI
153   const unsigned char PopTest[1] = {0x5E}; // pop %ESI
154   const unsigned char XCHGTest[1] = {0x91}; // xchg %ecx, %eax
155   const unsigned char SIBDisplacementTest[7] = 
156   {
157     0x89, 0x84, 0x01, 0xef, 0xbe, 0xad, 0xde // mov eax, (%eax, %ecx, 1)+$0xdeadbeef
158   };
159   const unsigned char EightBitRegTest[2] = {0x2c, 0x01}; // sub $0x1, %al
160   const unsigned char EightBitRegTest2[2] = {0x88, 0xc1}; // mov %al, %cl
161   const unsigned char ReturnTest[1] = {0xc3}; // ret
162   const unsigned char AddCarryTest[2] = {0x11, 0x01}; // adc %eax, *%ecx
163   const unsigned char WordJumpTest[5] = 
164   {
165     0xe9, 0x0e, 0x00, 0x00, 0xee
166   }; // jmp +0xee00000e
167   const unsigned char LESTest[2] = 
168   {
169     0xc4, 0x02 // LES (%edx), %eax
170   };
171   const unsigned char OModeTest[5] =
172   {
173     0xa0, 0x03, 0x00, 0x00, 0x24 //  mov 0x24000003,%al
174   };
175
176   testSuite IA32Tests;
177   
178   IA32Tests.testDecode(testMe, EightBitRegTest2, 2, "mov CL, AL");
179   IA32Tests.testDecode(testMe, MovRegToReg, 2, "mov %esp, %ebp");
180   IA32Tests.testDecode(testMe, MovRegToRegIndirect, 2, "mov %eax, *%ecx");
181   IA32Tests.testDecode(testMe, MovRegToRegIndirectOffset, 3, "mov %eax, 0xffffffd4(%ebp)");
182   IA32Tests.testDecode(testMe, MovRegToReg2, 2, "mov %esp, %ecx");
183   IA32Tests.testDecode(testMe, IndirectCall, 2, "call *%eax");
184   IA32Tests.testDecode(testMe, ConditionalJump, 2, "je +0x02");
185   IA32Tests.testDecode(testMe, UnconditionalJump, 2, "jmp +0x14");
186   IA32Tests.testDecode(testMe, MovRegToRegIndirectLongOffset, 6, "mov 0x390(%ecx), %edx");
187   IA32Tests.testDecode(testMe, SIBMove, 3, "mov (%eax, %esi, 4), %edx");
188   IA32Tests.testDecode(testMe, AddRegImmediate, 3, "add $0x1, %eax");
189   IA32Tests.testDecode(testMe, SubRegImmediate, 3, "sub $0x1, %eax");
190   IA32Tests.testDecode(testMe, PushTest, 1, "push %esi");
191   IA32Tests.testDecode(testMe, PopTest, 1, "pop %esi");
192   IA32Tests.testDecode(testMe, XCHGTest, 1, "xchg %ecx, %eax");  
193   IA32Tests.testDecode(testMe, SIBDisplacementTest, 7, "mov eax, (%eax, %ecx, 1)+$0xdeadbeef"); 
194   IA32Tests.testDecode(testMe, EightBitRegTest, 2, "sub $0x1, %al");
195   IA32Tests.testDecode(testMe, ReturnTest, 1, "ret");
196   IA32Tests.testDecode(testMe, AddCarryTest, 2, "adc %eax, *%ecx");
197   IA32Tests.testDecode(testMe, WordJumpTest, 5, "jmp +0xee00000e");
198   IA32Tests.testDecode(testMe, LESTest, 2, "les (%edx), %eax");
199   IA32Tests.testDecode(testMe, OModeTest, 5, "mov 0x24000003,%al");
200
201   std::set<RegisterAST::Ptr> expectedRead, expectedWritten;
202   expectedRead.insert(RegisterAST::Ptr(new RegisterAST(Dyninst::InstructionAPI::r_AL)));
203   expectedWritten.insert(RegisterAST::Ptr(new RegisterAST(Dyninst::InstructionAPI::r_CL)));
204   IA32Tests.testRegisters(testMe, EightBitRegTest2, 2, expectedRead, expectedWritten);
205   expectedRead.clear();
206   expectedWritten.clear();
207   expectedRead = list_of(RegisterAST::Ptr(new RegisterAST(Dyninst::InstructionAPI::r_eAX)))(RegisterAST::Ptr(new RegisterAST((Dyninst::InstructionAPI::r_eCX))));
208   IA32Tests.testRegisters(testMe, AddCarryTest, 2, expectedRead, expectedWritten);
209   
210   
211   IA32Tests.printResultsSummary();
212   
213   return 0;
214 }