Tracking commit: working in progress on dlopenDYNINSTlib()
[dyninst.git] / dyninstAPI / src / inst-ia64.C
1 /*
2  * Copyright (c) 1996 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 /*
43  * inst-ia64.C - ia64 dependent functions and code generator
44  * $Id: inst-ia64.C,v 1.9 2002/06/20 20:06:13 tlmiller Exp $
45  */
46
47 /* Note that these should all be checked for (linux) platform
48    independence and the possibility of refactoring their originals
49    into in- and de-pendent parts. */
50
51 #include <iomanip.h>
52 #include <limits.h>
53
54 #include "common/h/headers.h"
55
56 #ifndef BPATCH_LIBRARY
57 #include "rtinst/h/rtinst.h"
58 #endif
59 #include "common/h/Dictionary.h"
60 #include "dyninstAPI/src/symtab.h"
61 #include "dyninstAPI/src/process.h"
62 #include "dyninstAPI/src/inst.h"
63 #include "dyninstAPI/src/instP.h"
64 #include "dyninstAPI/src/ast.h"
65 #include "dyninstAPI/src/util.h"
66 #include "dyninstAPI/src/stats.h"
67 #include "dyninstAPI/src/os.h"
68 #include "dyninstAPI/src/showerror.h"
69
70 #include "dyninstAPI/src/arch-ia64.h"
71 #include "dyninstAPI/src/inst-ia64.h"
72 #include "dyninstAPI/src/instPoint.h"   // includes instPoint-ia64.h
73 #include "dyninstAPI/src/instP.h"       // class returnInstance
74
75 // for function relocation
76 #include "dyninstAPI/src/func-reloc.h" 
77 #include "dyninstAPI/src/LocalAlteration.h"
78
79 /* Required by process, ast .C, et al */
80 registerSpace * regSpace;
81
82 /* Required by ast.C */
83 void emitVload( opCode op, Address src1, Register src2, Register dest,
84                 char * ibuf, Address & base, bool noCost, int size ) {}
85
86 /* Required by ast.C */
87 Register emitFuncCall( opCode op, registerSpace * rs, char * ibuf,
88                         Address & base, const vector<AstNode *> & operands,
89                         const string & callee, process * proc,
90                         bool noCost, const function_base * calleefunc, 
91                         const instPoint *location) { return 0; }
92
93 /* Required by symtab.C */
94 void pd_Function::checkCallPoints() { }
95
96 /* Required by symtab.C */
97 bool pd_Function::findInstPoints(const image *i_owner) { return true; }
98
99 /* Required by func-reloc.C */
100 LocalAlteration *fixOverlappingAlterations( LocalAlteration * alteration, LocalAlteration * tempAlteration ) { return NULL; }
101
102 /* Required by LocalAlteration.C */
103 int InsertNops::sizeOfNop() { return 0; }
104
105 /* Required by func-reloc.C */
106 bool InsertNops::RewriteFootprint( Address oldBaseAdr, Address & oldAdr,
107                                 Address newBaseAdr, Address & newAdr,
108                                 instruction oldInstructions[],
109                                 instruction newInstructions[],
110                                 int & oldOffset, int & newOffset,
111                                 int newDisp, unsigned & codeOffset,
112                                 unsigned char *code ) { return false; }
113
114 /* Required by func-reloc.C */
115 bool ExpandInstruction::RewriteFootprint( Address oldBaseAdr, Address & oldAdr,
116                 Address newBaseAdr, Address & newAdr,
117                 instruction oldInstructions[], instruction newInstructions[],
118                 int &oldOffset, int &newOffset, int newDisp,
119                 unsigned &codeOffset, unsigned char* code ) { return false; }
120
121 /* Required by ast.C */
122 void emitFuncJump(opCode op, char * i, Address & base,
123                         const function_base * callee, process * proc ) { }
124
125 Register emitFuncCall(opCode op, registerSpace * rs,
126                       char * ibuf, Address & base,
127                       const vector<AstNode *> &operands,
128                       const string & callee, process * proc,
129                       bool noCost, const function_base * calleefunc,  
130                       const vector<AstNode *> & ifForks,
131                       const instPoint * location) { }
132
133
134 /* Required by BPatch_ function, image .C */
135 BPatch_point *createInstructionInstPoint( process * proc, void * address,
136                         BPatch_point ** alternative, BPatch_function * bpf ) { return NULL; }
137
138 /* Required by ast.C */
139 void emitASload( BPatch_addrSpec_NP as, Register dest, char * baseInsn,
140                         Address & base, bool noCost ) { }
141
142 /* FIXME: who actually needs this? */
143 bool PushEIP::RewriteFootprint( Address oldBaseAdr, Address & oldAdr,
144                 Address newBaseAdr, Address & newAdr,
145                 instruction oldInstructions[], instruction newInstructions[],
146                 int & oldInsnOffset, int & newInsnOffset,
147                 int newDisp, unsigned & codeOffset, unsigned char * code ) { return false; }
148
149 /* Required by process.C */
150 void instWaitingList::cleanUp( process *, Address addr ) { }
151
152 /* Required by BPatch_thread.C */
153 bool process::replaceFunctionCall( const instPoint * point, 
154                         const function_base * func ) { return false; }
155
156 /* Required by ast.C */
157 void emitV( opCode op, Register src1, Register src2, Register dest,
158                 char * ibuf, Address & base, bool noCost, int size ) { }
159
160 /* Required by inst.C */
161 bool deleteBaseTramp( process *, instPoint *, instInstance * ) { return false; }
162
163 /* Required by ast.C */
164 void emitImm( opCode op, Register src1, RegValue src2imm, Register dest,
165                 char *ibuf, Address & base, bool noCost ) { }
166
167 /* Required by ast.C */
168 int getInsnCost( opCode op ) { return -1; }
169
170 /* Required by process.C */
171 bool process::emitInferiorRPCtrailer( void * void_insnPtr, Address & baseBytes,
172                         unsigned & breakOffset, bool shouldStopForResult,
173                         unsigned & stopForResultOffset,
174                         unsigned & justAfter_stopForResultOffset,
175                         bool isFunclet ) { return false; }
176
177 /* Required by process.C */
178 bool process::heapIsOk( const vector<sym_data> & find_us ) { return false; }
179
180 /* Required by inst.C */
181 void emitVupdate( opCode op, RegValue src1, Register src2,
182                 Address dest, char * ibuf, Address & base, bool noCost ) { }
183
184 /* Required by ast.C */
185 void emitLoadPreviousStackFrameRegister( Address register_num,
186                 Register dest, char * insn, Address & base,
187                 int size, bool noCost ) { }
188
189 /* Required by func-reloc.C */
190 bool pd_Function::isTrueCallInsn( const instruction insn ) { }
191
192 /* Required by BPatch_thread.C */
193 void returnInstance::installReturnInstance( process * proc ) { }
194
195 /* Required by ast.C */
196 void initTramps() { }
197
198 /* Required by func-reloc and ast .C */
199 void generateBranch( process * proc, Address fromAddr, Address newAddr ) { }
200
201 /* Required by func-reloc.C */
202 bool pd_Function::PA_attachGeneralRewrites( const image * owner,
203                 LocalAlterationSet * temp_alteration_set,
204                 Address baseAddress, Address firstAddress,
205                 instruction * loadedCode,
206                 unsigned numInstructions, int codeSize ) { return false; }
207
208 /* Required by LocalAlteration.C */
209 int InsertNops::numInstrAddedAfter() { return -1; }
210
211 /* Required by inst.C */
212 trampTemplate * findAndInstallBaseTramp( process * proc, instPoint * & location,
213                                         returnInstance * & retInstance,
214                                         bool trampRecursiveDesired,
215                                         bool noCost, bool & deferred ) { return NULL; }
216
217 /* Required by func-reloc.C */
218 bool pd_Function::isNearBranchInsn( const instruction insn ) { return false; }
219
220 /* Required by process.C */
221 bool process::emitInferiorRPCheader( void * void_insnPtr, Address & baseBytes, bool isFunclet ) { return false; }
222
223 /* Required by ast.C */
224 Register emitR( opCode op, Register src1, Register src2, Register dest,
225                         char * ibuf, Address & base, bool noCost ) { return 0; }
226
227 /* Required by func-reloc.C */
228 bool pd_Function::loadCode(const image * owner, process * proc,
229                 instruction * & oldCode, unsigned & numberOfInstructions,
230                 Address & firstAddress) { return false; }
231
232 /* Required by func-reloc.C */
233 bool pd_Function::PA_attachBranchOverlaps(
234                 LocalAlterationSet * temp_alteration_set,
235                 Address baseAddress, Address firstAddress,
236                 instruction loadedCode[], unsigned numberOfInstructions,
237                 int codeSize )  { return false; }
238
239 /* Required by BPatch_init.C */
240 void initDefaultPointFrequencyTable() { }
241
242 /* Required by inst.C, ast.C */
243 Address emitA( opCode op, Register src1, Register src2, Register dest,
244                 char * ibuf, Address & base, bool noCost ) { return 0; }
245
246 /* Required by ast.C */
247 bool doNotOverflow( int value ) { return false; }
248
249 /* Required by func-reloc.C */
250 bool pd_Function::PA_attachOverlappingInstPoints(
251                 LocalAlterationSet * temp_alteration_set,
252                 Address baseAddress, Address firstAddress,
253                 instruction * loadedCode , int codeSize ) { return false; }
254
255 /* Required by inst.C */
256 void installTramp( instInstance * inst, char * code, int codeSize ) { }
257
258 /* Required by func-reloc.C */
259 void pd_Function::copyInstruction( instruction & newInsn,
260         instruction & oldInsn, unsigned & codeOffset) { }
261
262 /* Required by func-reloc.C */
263 bool pd_Function::fillInRelocInstPoints(
264                 const image * owner, process * proc,   
265                 instPoint * & location, relocatedFuncInfo * & reloc_info,
266                 Address mutatee, Address mutator, instruction oldCode[],
267                 Address newAdr, instruction newCode[],
268                 LocalAlterationSet & alteration_set ) { return false; }
269
270 /* Required by ast.C */
271 void emitVstore( opCode op, Register src1, Register src2, Address dest,
272                 char * ibuf, Address & base, bool noCost, int size ) { }
273
274 /* Required by inst.C */
275 void generateNoOp( process * proc, Address addr ) { }
276
277 /* Required by func-reloc.C ? */
278 bool PushEIPmov::RewriteFootprint( Address oldBaseAdr, Address & oldAdr,
279                                 Address newBaseAdr, Address & newAdr,
280                                 instruction oldInstructions[],
281                                 instruction newInstructions[],
282                                 int & oldInsnOffset, int & newInsnOffset,
283                                 int newDisp, unsigned & codeOffset,
284                                 unsigned char * code) { return false; }
285
286 /* -------- implementation of InsnAddr -------- */
287
288 InsnAddr InsnAddr::generateFromAlignedDataAddress( Address addr, process * p ) {
289         assert( addr % 16 == 0 );  assert( p != NULL );
290         InsnAddr generated( addr, p );
291         return generated;
292         } /* end gFADA() */
293
294 /* FIXME: shouldn't these be writeTextSpace() calls? */
295 bool InsnAddr::writeMyBundleFrom( const unsigned char * savedCodeBuffer ) {
296         /* Aligns the instruction address and copies sixteen bytes from
297            the savedCodeBuffer to that address. */
298
299         unsigned short offset = encodedAddress % 16;
300         Address alignedAddress = encodedAddress - offset;
301
302         return myProc->writeDataSpace( (void *)alignedAddress, 16, savedCodeBuffer );
303         } /* end writeMyBundleFrom() */
304
305 bool InsnAddr::saveMyBundleTo( unsigned char * savedCodeBuffer ) {
306         /* Aligns the instruction address and copies sixteen bytes from
307            there to the savedCodeBuffer. */
308
309         unsigned short offset = encodedAddress % 16;
310         Address alignedAddress = encodedAddress - offset;
311
312         return myProc->readDataSpace( (void *)alignedAddress, 16, savedCodeBuffer, true );
313         } /* end saveMyBundleTo() */
314
315 bool InsnAddr::replaceBundleWith( const IA64_bundle & bundle ) {
316         /* Aligns the instruction address and copies in the bundle. */
317         unsigned short offset = encodedAddress % 16;
318         Address alignedAddress = encodedAddress - offset;
319         ia64_bundle_t theBundle = bundle.getMyBundle();
320
321         return myProc->writeDataSpace( (void *)alignedAddress, 16, & theBundle );
322         } /* end replaceInstructionWith() */
323
324 bool InsnAddr::saveBundlesTo( unsigned char * savedCodeBuffer, unsigned int numberOfBundles ) {
325         /* Align the instruction address and copy (numberOfBundles * 16) bytes 
326            from there to savedCodeBuffer. */
327         unsigned short offset = encodedAddress % 16;
328         Address alignedAddress = encodedAddress - offset;
329         
330         return myProc->readDataSpace( (void *)alignedAddress, (numberOfBundles * 16), savedCodeBuffer, true );
331         } /* end saveBundlesTo() */
332
333 bool InsnAddr::writeBundlesFrom( unsigned char * savedCodeBuffer, unsigned int numberOfBundles ) {
334         /* Align the instruction address and copy (numberOfBundles * 16) bytes 
335            from there to savedCodeBuffer. */
336         unsigned short offset = encodedAddress % 16;
337         Address alignedAddress = encodedAddress - offset;
338         
339         return myProc->writeDataSpace( (void *)alignedAddress, (numberOfBundles * 16), savedCodeBuffer );
340         } /* end saveBundlesTo() */
341
342 bool InsnAddr::replaceBundlesWith( const IA64_bundle * replacementBundles, unsigned int numberOfReplacementBundles ) {
343         /* Align the instruction address and copy (numberOfReplacementBundles * 16) bytes
344            from the savedCodeBuffer to that address. */
345
346         unsigned short offset = encodedAddress % 16;
347         Address alignedAddress = encodedAddress - offset;
348
349         ia64_bundle_t * rawReplacementBundles = (ia64_bundle_t *)malloc( sizeof( ia64_bundle_t ) * numberOfReplacementBundles );
350         for( int i = 0; i < numberOfReplacementBundles; i++ ) {
351                 rawReplacementBundles[i] = replacementBundles[i].getMyBundle();
352                 }
353
354         return myProc->writeDataSpace( (void *)alignedAddress, (numberOfReplacementBundles * 16), rawReplacementBundles );
355         } /* end replaceBundlesWith() */
356
357 bool InsnAddr::writeStringAtOffset( unsigned int offsetInBundles, const char * string, unsigned int length ) {
358         /* Align the instruction address and compute in the offset. */
359         unsigned short offset = encodedAddress % 16;
360         Address alignedOffset = encodedAddress - offset + (offsetInBundles * 16);
361
362         return myProc->writeDataSpace( (void *)alignedOffset, length, string );
363         } /* end writeStringAtOffset() */
364
365 uint64_t InsnAddr::operator * () {
366         /* Align the instruction address and compute in the offset. */
367         unsigned short offset = encodedAddress % 16;
368         Address alignedOffset = encodedAddress - offset;
369
370         /* Construct a decodable bundle from the machine code. */
371         ia64_bundle_t rawBundle;
372         if( ! myProc->readDataSpace( (const void *)alignedOffset, 16, (void *)& rawBundle, true ) ) {
373                 /* FIXME: probably overkill. */
374                 fprintf( stderr, "Failed to read from instruction address 0x%lX, aborting.\n", alignedOffset );
375                 abort();
376                 }
377         IA64_bundle bundle( rawBundle );
378
379         /* Return the appropriate left-aligned machine code. */
380         return bundle.getInstruction( offset ).getMachineCode();
381         } /* end operator * () */
382
383 #ifdef ZERO
384 class InsnAddr {
385         public:
386                 /* prefix increment */
387                 InsnAddr operator++ ();
388
389                 /* prefix decrement */
390                 InsnAddr operator-- ();
391
392                 /* postfix increment */
393                 InsnAddr operator++ (int dummy);
394
395                 /* postfix decrement */
396                 InsnAddr operator-- (int dummy);
397
398                 /* sum of two InsnAddrs */
399                 friend InsnAddr operator + ( InsnAddr lhs, InsnAddr rhs );
400
401                 /* difference of two InsnAddrs */
402                 friend InsnAddr operator - ( InsnAddr lhs, InsnAddr rhs );
403
404                 friend bool operator < ( InsnAddr lhs, InsnAddr rhs );
405                 friend bool operator <= ( InsnAddr lhs, InsnAddr rhs );
406                 friend bool operator > ( InsnAddr lhs, InsnAddr rhs );
407                 friend bool operator >= ( InsnAddr lhs, InsnAddr rhs );
408                 friend bool operator == ( InsnAddr lhs, InsnAddr rhs );
409                 friend bool operator != ( InsnAddr lhs, InsnAddr rhs );
410
411         private:
412                 Address encodedAddress;
413 }; /* end class InsnAddr */
414 #endif