Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / arch.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 // Code generation
33
34 //////////////////////////
35 // Move to arch.C
36 //////////////////////////
37
38 #include <assert.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include "addressSpace.h"
43 #include "process.h"
44 #include "common/h/Types.h"
45 #include "common/h/parseauxv.h"
46 #if defined (os_osf)
47 #include <malloc.h>
48 #endif
49 #include "arch.h"
50 #include "util.h"
51 #include "function.h"
52 #include "dyn_thread.h"
53 #include "instPoint.h"
54 #include "registerSpace.h"
55
56 #if defined(arch_x86) || defined(arch_x86_64)
57 #define CODE_GEN_OFFSET_SIZE 1
58 #elif defined(arch_ia64)
59 #define CODE_GEN_OFFSET_SIZE (sizeof(codeBuf_t))
60 #else
61 #define CODE_GEN_OFFSET_SIZE (instruction::size())
62 #endif
63
64 const unsigned int codeGenPadding = 256;
65
66 codeGen::codeGen() :
67     buffer_(NULL),
68     offset_(0),
69     size_(0),
70     emitter_(NULL),
71     allocated_(false),
72     aSpace_(NULL),
73     thr_(NULL),
74     lwp_(NULL),
75     rs_(NULL),
76     t_(NULL),
77     addr_((Address)-1),
78     ip_(NULL),
79     f_(NULL),
80     bti_(NULL),
81     isPadded_(true),
82     trackRegDefs_(false),
83     obj_(NULL)
84 {}
85
86 // size is in bytes
87 codeGen::codeGen(unsigned size) :
88     buffer_(NULL),
89     offset_(0),
90     size_(size),
91     emitter_(NULL),
92     allocated_(true),
93     aSpace_(NULL),
94     thr_(NULL),
95     lwp_(NULL),
96     rs_(NULL),
97         t_(NULL),
98     addr_((Address)-1),
99     ip_(NULL),
100     f_(NULL),
101     bti_(NULL),
102     isPadded_(true),
103     trackRegDefs_(false),
104     obj_(NULL)
105 {
106     buffer_ = (codeBuf_t *)malloc(size+codeGenPadding);
107     if (!buffer_)
108        fprintf(stderr, "%s[%d]: malloc failed: size is %d + codeGenPadding = %d\n", FILE__, __LINE__, size, codeGenPadding);
109     assert(buffer_);
110     memset(buffer_, 0, size+codeGenPadding);
111 }
112
113
114 codeGen::~codeGen() {
115     if (allocated_ && buffer_) {
116         free(buffer_);
117     }
118 }
119
120 // Deep copy
121 codeGen::codeGen(const codeGen &g) :
122     offset_(g.offset_),
123     size_(g.size_),
124     emitter_(NULL),
125     allocated_(g.allocated_),
126     aSpace_(g.aSpace_),
127     thr_(g.thr_),
128     lwp_(g.lwp_),
129     rs_(g.rs_),
130         t_(g.t_),
131     addr_(g.addr_),
132     ip_(g.ip_),
133     f_(g.f_),
134     bti_(g.bti_),
135     isPadded_(g.isPadded_),
136     trackRegDefs_(g.trackRegDefs_),
137     obj_(g.obj_)
138 {
139     if (size_ != 0) {
140         assert(allocated_); 
141         int bufferSize = size_ + (isPadded_ ? codeGenPadding : 0);
142         buffer_ = (codeBuf_t *) malloc(bufferSize);
143         memcpy(buffer_, g.buffer_, bufferSize);
144     }
145     else
146         buffer_ = NULL;
147 }
148
149 bool codeGen::operator==(void *p) const {
150     return (p == (void *)buffer_);
151 }
152
153 bool codeGen::operator!=(void *p) const {
154     return (p != (void *)buffer_);
155 }
156
157 codeGen &codeGen::operator=(const codeGen &g) {
158     // Same as copy constructor, really
159     invalidate();
160     offset_ = g.offset_;
161     size_ = g.size_;
162     allocated_ = g.allocated_;
163     thr_ = g.thr_;
164     lwp_ = g.lwp_;
165     isPadded_ = g.isPadded_;
166     int bufferSize = size_ + (isPadded_ ? codeGenPadding : 0);
167     obj_ = g.obj_;
168     
169
170     if (size_ != 0) {
171        assert(allocated_); 
172
173        buffer_ = (codeBuf_t *) malloc(bufferSize);
174        //allocate(g.size_);
175         
176        memcpy(buffer_, g.buffer_, bufferSize);
177     }
178     else
179         buffer_ = NULL;
180     return *this;
181 }
182
183 void codeGen::allocate(unsigned size) 
184 {
185    if (buffer_ && size > size_) {
186       free(buffer_);
187       buffer_ = NULL;
188    }
189    if (buffer_ == NULL)
190    {
191       buffer_ = (codeBuf_t *)malloc(size+codeGenPadding);
192       isPadded_ = true;
193    }
194    
195    size_ = size;
196    offset_ = 0;
197    allocated_ = true;
198    if (!buffer_) {
199       fprintf(stderr, "%s[%d]:  malloc (%d) failed: %s\n", FILE__, __LINE__, size, strerror(errno));
200 #if defined (os_osf)
201     //struct mallinfo my_mallinfo  = mallinfo();
202     //extern struct mallinfo = mallinfo();
203     fprintf(stderr, "malloc info:\n");
204     fprintf(stderr, "\t arena = %d\n", mallinfo().arena);
205     fprintf(stderr, "\t ordblocks = %d\n", mallinfo().ordblks);
206     fprintf(stderr, "\t free ordblocks = %d\n", mallinfo().fordblks);
207     fprintf(stderr, "\t smblocks = %d\n", mallinfo().smblks);
208     fprintf(stderr, "\t free smblocks = %d\n", mallinfo().fsmblks);
209 #endif
210     }
211     assert(buffer_);
212 }
213
214 // Very similar to destructor
215 void codeGen::invalidate() {
216     if (allocated_ && buffer_) {
217         free(buffer_);
218     }
219     buffer_ = NULL;
220     size_ = 0;
221     offset_ = 0;
222     allocated_ = false;
223     isPadded_ = false;
224 }
225
226 void codeGen::finalize() {
227     assert(buffer_);
228     assert(size_);
229     if (size_ == offset_) return;
230     if (offset_ == 0) {
231         fprintf(stderr, "Warning: offset is 0 in codeGen::finalize!\n");
232         invalidate();
233         return;
234     }
235     codeBuf_t *newbuf = (codeBuf_t *)malloc(used());
236     memcpy((void *)newbuf, (void *)buffer_, used());
237     size_ = used(); // Don't use offset :D
238     isPadded_ = false;
239
240     free(buffer_);
241     buffer_ = newbuf;
242 }
243
244 void codeGen::copy(const void *b, const unsigned size) {
245     assert(buffer_);
246     memcpy(cur_ptr(), b, size);
247     // "Upgrade" to next index side
248     int disp = size;
249     if (disp % CODE_GEN_OFFSET_SIZE) {
250         disp += (CODE_GEN_OFFSET_SIZE - (disp % CODE_GEN_OFFSET_SIZE));
251     }
252     moveIndex(disp);
253 }
254
255 void codeGen::copy(codeGen &gen) {
256     memcpy((void *)cur_ptr(), (void *)gen.start_ptr(), gen.used());
257     offset_ += gen.offset_;
258     assert(used() <= size_);
259 }
260
261 // codeBufIndex_t stores in platform-specific units.
262 unsigned codeGen::used() const {
263     return offset_ * CODE_GEN_OFFSET_SIZE;
264 }
265
266 void *codeGen::start_ptr() const {
267     return (void *)buffer_;
268 }
269
270 void *codeGen::cur_ptr() const {
271     assert(buffer_);
272     if (sizeof(codeBuf_t) != CODE_GEN_OFFSET_SIZE)
273         fprintf(stderr, "ERROR: sizeof codeBuf %ld, OFFSET %d\n",
274                 (long) sizeof(codeBuf_t), CODE_GEN_OFFSET_SIZE);
275     assert(sizeof(codeBuf_t) == CODE_GEN_OFFSET_SIZE);
276     codeBuf_t *ret = buffer_;
277     ret += offset_;
278     return (void *)ret;
279 }
280
281 void *codeGen::get_ptr(unsigned offset) const {
282     assert(buffer_);
283     assert(offset < size_);
284     assert(sizeof(codeBuf_t) == CODE_GEN_OFFSET_SIZE);
285     assert((offset % CODE_GEN_OFFSET_SIZE) == 0);
286     unsigned index = offset / CODE_GEN_OFFSET_SIZE;
287     codeBuf_t *ret = buffer_;
288     ret += index;
289     return (void *)ret;
290 }
291
292 void codeGen::update(codeBuf_t *ptr) {
293     assert(buffer_);
294     assert(sizeof(unsigned char) == 1);
295     unsigned diff = ((unsigned char *)ptr) - ((unsigned char *)buffer_);
296     
297     // Align...
298     if (diff % CODE_GEN_OFFSET_SIZE) {
299         diff += CODE_GEN_OFFSET_SIZE - (diff % CODE_GEN_OFFSET_SIZE);
300         assert ((diff % CODE_GEN_OFFSET_SIZE) == 0);
301     }
302     // and integer division rules
303     offset_ = diff / CODE_GEN_OFFSET_SIZE;
304
305     // Keep the pad
306     if (used() > size_) {
307         fprintf(stderr, "WARNING: overflow of codeGen structure, trying to enlarge\n");
308         if ((used() - size_) > codeGenPadding) {
309             assert(0 && "Overflow in codeGen");
310         }
311         // Add an extra codeGenPadding to the end
312         size_ += codeGenPadding;
313         buffer_ = (codeBuf_t *)realloc(buffer_, size_ + codeGenPadding);
314         assert(buffer_);
315     }
316
317     assert(used() <= size_);
318 }
319
320 void codeGen::setIndex(codeBufIndex_t index) {
321     offset_ = index;
322     
323     // Keep the pad
324     if (used() > size_) {
325         fprintf(stderr, "WARNING: overflow of codeGen structure (%d requested, %d actual), trying to enlarge\n", used(), size_);
326
327         if ((used() - size_) > codeGenPadding) {
328             assert(0 && "Overflow in codeGen");
329         }
330         // Add an extra codeGenPadding to the end
331         size_ += codeGenPadding;
332         buffer_ = (codeBuf_t *)realloc(buffer_, size_ + codeGenPadding);
333         assert(buffer_);
334     }
335     assert(used() <= size_);
336 }
337
338 codeBufIndex_t codeGen::getIndex() const {
339     return offset_;
340 }
341
342 void codeGen::moveIndex(int disp) {
343     int cur = getIndex() * CODE_GEN_OFFSET_SIZE;
344     cur += disp;
345     if (cur % CODE_GEN_OFFSET_SIZE) {
346         fprintf(stderr, "Error in codeGen: current index %d/%d, moving by %d, mod %d\n",
347                 getIndex(), cur, disp, cur % CODE_GEN_OFFSET_SIZE);
348     }
349     assert((cur % CODE_GEN_OFFSET_SIZE) == 0);
350     setIndex(cur / CODE_GEN_OFFSET_SIZE);
351 }
352
353 int codeGen::getDisplacement(codeBufIndex_t from, codeBufIndex_t to) {
354     return ((to - from) * CODE_GEN_OFFSET_SIZE);
355 }
356
357 Address codeGen::currAddr() const {
358     assert(addr_ != (Address) -1);
359     return currAddr(addr_);
360 }
361
362 Address codeGen::currAddr(Address base) const { 
363     return (offset_ * CODE_GEN_OFFSET_SIZE) + base;
364 }
365
366 void codeGen::fill(unsigned fillSize, int fillType) {
367     switch(fillType) {
368     case cgNOP:
369         instruction::generateNOOP(*this, fillSize);
370         break;
371     case cgTrap: {
372         unsigned curUsed = used();
373         while ((used() - curUsed > (unsigned) fillSize))
374             instruction::generateTrap(*this);
375         assert((used() - curUsed) == (unsigned) fillSize);
376         break;
377     }
378     case cgIllegal: {
379         unsigned curUsed = used();
380         while ((used() - curUsed > (unsigned) fillSize))
381             instruction::generateIllegal(*this);
382         assert((used() - curUsed) == (unsigned) fillSize);
383         break;
384     }
385     default:
386         assert(0 && "unimplemented");
387     }
388 }
389
390 void codeGen::fillRemaining(int fillType) {
391     if (fillType == cgNOP) {
392         instruction::generateNOOP(*this,
393                                   size_ - used());
394     }
395     else {
396         assert(0 && "unimplemented");
397     }
398 }
399
400 void codeGen::applyTemplate(codeGen &c) {
401     // Copy off necessary bits...
402
403     aSpace_ = c.aSpace_;
404     thr_ = c.thr_;
405     lwp_ = c.lwp_;
406     rs_ = c.rs_;
407     addr_ = c.addr_;
408     ip_ = c.ip_;
409     f_ = c.f_;
410 }
411
412 void codeGen::setAddrSpace(AddressSpace *a)
413
414    aSpace_ = a; 
415    setCodeEmitter(a->getEmitter());
416 }
417
418 void codeGen::addPCRelRegion(pcRelRegion *reg) {
419 #if !defined(cap_noaddr_gen)
420    assert(0);
421 #endif
422    reg->gen = this;
423    reg->cur_offset = used();
424
425    if (startAddr() != (Address) -1 && reg->canPreApply()) {
426      //If we already have addressess for everything (usually when relocating a function)
427      // then don't bother creating the region, just generate the code.
428      reg->apply(startAddr() + reg->cur_offset);
429      delete reg;
430    }
431    else {
432      reg->cur_size = reg->maxSize();
433      fill(reg->cur_size, cgNOP);
434      pcrels_.push_back(reg);
435    }
436 }
437
438 void codeGen::applyPCRels(Address base)
439 {
440    vector<pcRelRegion *>::iterator i;
441
442    codeBufIndex_t orig_position = used();
443    for (i = pcrels_.begin(); i != pcrels_.end(); i++) {
444       pcRelRegion *cur = *i;
445       bool is_last_entry = ((cur->cur_offset + cur->cur_size) >= orig_position);
446
447       //Apply the patch
448       setIndex(cur->cur_offset / CODE_GEN_OFFSET_SIZE);
449       unsigned patch_size = cur->apply(base + cur->cur_offset);
450       assert(patch_size <= cur->cur_size);
451       unsigned size_change = cur->cur_size - patch_size;
452
453       if (size_change) {
454          if (is_last_entry) {
455             //If we resized the last object in the codeGen, then change the
456             // codeGen's end address
457             orig_position = cur->cur_offset + patch_size;
458          }
459          //Fill in any size changes with nops
460          fill(size_change, cgNOP);
461       }
462       delete cur;
463    }
464    setIndex(orig_position / CODE_GEN_OFFSET_SIZE);
465    pcrels_.clear();
466 }
467
468 bool codeGen::hasPCRels() const {
469    return (pcrels_.size() != 0);
470 }
471
472
473 pcRelRegion::pcRelRegion(const instruction &i) :
474    gen(NULL),
475    orig_instruc(i),
476    cur_offset(0),
477    cur_size(0)
478 {
479 }
480
481 pcRelRegion::~pcRelRegion()
482 {
483 }
484
485 std::vector<relocPatch>& codeGen::allPatches() {
486    return patches_;
487 }
488
489 void codeGen::addPatch(void *dest, patchTarget *source, 
490                        unsigned size,
491                        relocPatch::patch_type_t ptype,
492                        Dyninst::Offset off)
493 {
494    relocPatch p(dest, source, ptype, this, off, size);
495    patches_.push_back(p);
496 }
497
498 void codeGen::applyPatches()
499 {
500    std::vector<relocPatch>::iterator i;
501    for (i = patches_.begin(); i != patches_.end(); i++)
502       (*i).applyPatch();
503 }
504
505
506 relocPatch::relocPatch(void *d, patchTarget *s, patch_type_t ptype,
507                        codeGen *gen, Dyninst::Offset off, unsigned size) :
508    dest_(d),
509    source_(s),
510    size_(size),
511    ptype_(ptype),
512    gen_(gen),
513    offset_(off),
514    applied_(false)
515 {
516 }
517
518 void relocPatch::applyPatch()
519 {
520    if (applied_)
521       return;
522
523    Address addr = source_->get_address();
524
525    switch (ptype_) {
526       case pcrel:
527          addr = addr - (gen_->startAddr() + offset_);
528       case abs:
529          memcpy(dest_, &addr, size_);
530          break;
531       default:
532          assert(0);
533    }
534    applied_ = true;
535 }
536
537 bool relocPatch::isApplied()
538 {
539    return applied_;
540 }
541
542 bool pcRelRegion::canPreApply()
543 {
544   return false;
545 }
546
547 std::string patchTarget::get_name() const {
548    return std::string("UNNAMED");
549 }
550
551 patchTarget::~patchTarget()
552 {
553 }
554
555 toAddressPatch::~toAddressPatch() {
556 }
557
558 Address toAddressPatch::get_address() const 
559
560   return addr; 
561 }
562
563 unsigned toAddressPatch::get_size() const { 
564   return 0; 
565 }
566
567 void toAddressPatch::set_address(Address a) {
568    addr = a;
569 }
570
571 codeGen codeGen::baseTemplate;
572
573 dyn_lwp *codeGen::lwp() {
574     if (lwp_) return lwp_;
575     if (thr_) return thr_->get_lwp();
576     return NULL;
577 }
578
579 dyn_thread *codeGen::thread() {
580     return thr_;
581 }
582
583 AddressSpace *codeGen::addrSpace() {
584     if (aSpace_) { return aSpace_; }
585     if (f_) { return f_->proc(); }
586     if (ip_) { return ip_->proc(); }
587     if (thr_) { return thr_->get_proc(); }
588     return NULL;
589 }
590
591 instPoint *codeGen::point() {
592     return ip_;
593 }
594
595 int_function *codeGen::func() {
596     if (f_) return f_;
597     if (ip_) return ip_->func();
598     return NULL;
599 }
600
601 registerSpace *codeGen::rs() {
602     return rs_;
603 }
604
605 regTracker_t *codeGen::tracker() {
606     return t_; 
607 }
608
609 Emitter *codeGen::codeEmitter() {
610     return emitter_;
611 }
612
613 generatedCodeObject *codeGen::obj() {
614     return obj_;
615 }
616
617 void codeGen::beginTrackRegDefs()
618 {
619    trackRegDefs_ = true;
620    regsDefined_ = registerSpace::getBitArray();
621 }
622
623 void codeGen::endTrackRegDefs()
624 {
625    trackRegDefs_ = false;
626 }
627  
628 const bitArray &codeGen::getRegsDefined()
629 {
630    return regsDefined_;
631 }
632
633 void codeGen::markRegDefined(Register r) {
634    if (!trackRegDefs_)
635       return;
636    regsDefined_[r] = true;
637 }
638
639 bool codeGen::isRegDefined(Register r) {
640    assert(trackRegDefs_);
641    return regsDefined_[r];
642 }