Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / arch.h
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 // Architecture include. Use this one instead of arch-<platform>
33
34 #if !defined(arch_h)
35 #define arch_h
36
37 #include <assert.h>
38 #include <vector>
39
40 #include "dyninstAPI/src/patch.h"
41
42 #if defined(sparc_sun_sunos4_1_3) \
43  || defined(sparc_sun_solaris2_4)
44 #include "arch-sparc.h"
45
46 #elif defined(arch_power)
47 #include "arch-power.h"
48
49 #elif defined(i386_unknown_solaris2_5) \
50    || defined(i386_unknown_nt4_0) \
51    || defined(i386_unknown_linux2_0) \
52    || defined(x86_64_unknown_linux2_4)
53 #include "arch-x86.h"
54
55 #elif defined(ia64_unknown_linux2_4)
56 #include "arch-ia64.h"
57
58 #else
59 #error "unknown architecture"
60
61 #endif
62
63 #include "dyninstAPI/src/bitArray.h"
64
65 class dyn_lwp;
66 class dyn_thread;
67 class process;
68 class AddressSpace;
69 class instPoint;
70 class registerSpace;
71 class regTracker_t;
72 class AstNode;
73 class Emitter;
74 class pcRelRegion;
75 class int_function;
76 class generatedCodeObject;
77 class baseTrampInstance;
78
79 // Code generation
80 // This class wraps the actual code generation mechanism: we keep a buffer
81 // and a pointer to where we are in the buffer. This may vary by platform,
82 // hence the typedef wrappers.
83 class codeGen {
84     // Instruction modifies these.
85     friend class instruction;
86     friend class AstNode;
87  public:
88     // Default constructor -- makes an empty generation area
89     codeGen();
90     // Make a generation buffer with the given size
91     codeGen(unsigned size);
92     // Use a preallocated buffer
93     codeGen(codeBuf_t *buf, int size);
94     ~codeGen();
95
96     // Copy constructor. Deep-copy -- allocates
97     // a new buffer
98     codeGen(const codeGen &);
99
100     // We consider our pointer to either be the start
101     // of the buffer, or NULL if the buffer is empty
102     bool operator==(void *ptr) const;
103     bool operator!=(void *ptr) const;
104
105     // Assignment....
106     codeGen &operator=(const codeGen &param);
107
108     // Initialize the current using the argument as a "template"
109     void applyTemplate(codeGen &codeTemplate);
110     static codeGen baseTemplate;
111
112     // Allocate a certain amount of space
113     void allocate(unsigned);
114     // And invalidate
115     void invalidate();
116
117     // Finally, tighten down the memory usage. This frees the 
118     // buffer if it's bigger than necessary and copies everything
119     // to a new fixed buffer.
120     void finalize();
121     
122     // Copy a buffer into here and move the offset
123     void copy(const void *buf, const unsigned size);
124     // Similar, but slurp from the start of the parameter
125     void copy(codeGen &gen);
126
127     // How much space are we using?
128     unsigned used() const;
129
130     // Blind pointer to the start of the code area
131     void *start_ptr() const;
132     // With ptr() and used() you can copy into the mutatee.
133
134     // Pointer to the current location...
135     void *cur_ptr() const;
136
137     // And pointer to a given offset
138     void *get_ptr(unsigned offset) const;
139
140     // For things that make a copy of the current pointer and
141     // play around with it. This recalculates the current offset
142     // based on a new pointer
143     void update(codeBuf_t *ptr);
144
145     // Set the offset at a particular location.
146     void setIndex(codeBufIndex_t offset);
147
148     codeBufIndex_t getIndex() const;
149
150     // Move up or down a certain amount
151     void moveIndex(int disp);
152
153     // To calculate a jump between the "from" and where we are
154     static int getDisplacement(codeBufIndex_t from, codeBufIndex_t to);
155
156     // For code generation -- given the current state of 
157     // generation and a base address in the mutatee, 
158     // produce a "current" address.
159     Address currAddr() const;
160     Address currAddr(Address base) const;
161     
162     enum { cgNOP, cgTrap, cgIllegal };
163
164     void fill(unsigned fillSize, int fillType);
165     // Since we have a known size
166     void fillRemaining(int fillType);
167
168     void setData(process *proc, dyn_thread *thr, dyn_lwp *lwp,
169                  Address startAddr,
170                  instPoint *point,
171                  registerSpace *rs);
172
173     //Add a new PCRelative region that should be generated after 
174     // addresses are fixed
175     void addPCRelRegion(pcRelRegion *reg);
176
177     //Have each region generate code with this codeGen object being
178     // placed at addr
179     void applyPCRels(Address addr);
180
181     //Return true if there are any active regions.
182     bool hasPCRels() const;
183
184     //Add a new patch point
185     void addPatch(const relocPatch &p);
186
187     //Create a patch into the codeRange
188     void addPatch(void *dest, patchTarget *source, 
189                   unsigned size = sizeof(Address),
190                   relocPatch::patch_type_t ptype = relocPatch::abs,
191                   Dyninst::Offset off = 0);
192
193     std::vector<relocPatch> &allPatches();
194
195     //Apply all patches that have been added
196     void applyPatches();
197
198     //void setProcess(process *p);
199     void setAddrSpace(AddressSpace *a);
200     void setThread(dyn_thread *t) { thr_ = t; }
201     void setLWP(dyn_lwp *l) { lwp_ = l; }
202     void setRegisterSpace(registerSpace *r) { rs_ = r; }
203     void setAddr(Address a) { addr_ = a; }
204     void setPoint(instPoint *i) { ip_ = i; }
205     void setRegTracker(regTracker_t *t) { t_ = t; }
206     void setCodeEmitter(Emitter *emitter) { emitter_ = emitter; }
207     void setFunction(int_function *f) { f_ = f; }
208     void setObj(generatedCodeObject *object) { obj_ = object; }
209     void setBTI(baseTrampInstance *i) { bti_ = i; }
210
211     dyn_lwp *lwp();
212     dyn_thread *thread();
213     //process *proc();
214     AddressSpace *addrSpace();
215     Address startAddr() const { return addr_; }
216     instPoint *point();
217     baseTrampInstance *bti() const { return bti_; }
218     int_function *func();
219     registerSpace *rs();
220     regTracker_t *tracker();
221     Emitter *codeEmitter();
222     Emitter *emitter() { return codeEmitter(); } // A little shorter
223
224     generatedCodeObject *obj();
225
226     void beginTrackRegDefs();
227     void endTrackRegDefs();
228     const bitArray &getRegsDefined();
229     void markRegDefined(Register r);
230     bool isRegDefined(Register r);
231
232     void setPCRelUseCount(int c) { pc_rel_use_count = c; }
233     int getPCRelUseCount() const { return pc_rel_use_count; }
234  private:
235     codeBuf_t *buffer_;
236     codeBufIndex_t offset_;
237     unsigned size_;
238     int pc_rel_use_count;
239
240     Emitter *emitter_;
241     bool allocated_;
242
243     //process *proc_;
244     AddressSpace *aSpace_;
245     dyn_thread *thr_;
246     dyn_lwp * lwp_;
247     registerSpace *rs_;
248     regTracker_t *t_;
249     Address addr_;
250     instPoint *ip_;
251     int_function *f_;
252     baseTrampInstance *bti_;
253     bool isPadded_;
254
255     bitArray regsDefined_;
256     bool trackRegDefs_;
257
258     generatedCodeObject *obj_;
259
260     std::vector<relocPatch> patches_;
261     std::vector<pcRelRegion *> pcrels_;
262 };
263
264 class pcRelRegion {
265    friend class codeGen;
266  protected:
267    codeGen *gen;
268    instruction orig_instruc;
269    unsigned cur_offset;
270    unsigned cur_size;
271  public:
272    pcRelRegion(const instruction &i);
273    virtual unsigned apply(Address addr) = 0;
274    virtual unsigned maxSize() = 0;
275    virtual bool canPreApply();
276    virtual ~pcRelRegion();
277 }; 
278
279 // For platforms that require bit-twiddling. These should go away in the future.
280 #define GET_PTR(insn, gen) codeBuf_t *insn = (codeBuf_t *)(gen).cur_ptr()
281 #define SET_PTR(insn, gen) (gen).update(insn)
282 #define REGET_PTR(insn, gen) insn = (codeBuf_t *)(gen).cur_ptr()
283
284 #endif