arm64: set number of regs defined in beginTrackRegDefs()
[dyninst.git] / dyninstAPI / src / codegen.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 // Code generation
32
33 #include <assert.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include "addressSpace.h"
38 #include "dynThread.h"
39 #include "dynProcess.h"
40 #include "common/src/Types.h"
41 #include "codegen.h"
42 #include "util.h"
43 #include "function.h"
44 #include "instPoint.h"
45 #include "registerSpace.h"
46 #include "pcrel.h"
47 #include "bitArray.h"
48
49 #include "instructionAPI/h/InstructionDecoder.h"
50
51 #if defined(arch_x86) || defined(arch_x86_64)
52 #define CODE_GEN_OFFSET_SIZE 1
53 #else
54 #define CODE_GEN_OFFSET_SIZE (instruction::size())
55 #endif
56
57 const unsigned int codeGenPadding = (128);
58 const unsigned int codeGenMinAlloc = (4 * 1024);
59
60 codeGen::codeGen() :
61     buffer_(NULL),
62     offset_(0),
63     size_(0),
64     max_(0),
65     pc_rel_use_count(0),
66     emitter_(NULL),
67     allocated_(false),
68     aSpace_(NULL),
69     thr_(NULL),
70     rs_(NULL),
71     t_(NULL),
72     addr_((Address)-1),
73     ip_(NULL),
74     f_(NULL),
75     bt_(NULL),
76     isPadded_(true),
77     trackRegDefs_(false),
78     inInstrumentation_(false), // save default
79     insertNaked_(false),
80     modifiedStackFrame_(false)
81 {}
82
83 // size is in bytes
84 codeGen::codeGen(unsigned size) :
85     buffer_(NULL),
86     offset_(0),
87     size_(size),
88     max_(size+codeGenPadding),
89     pc_rel_use_count(0),
90     emitter_(NULL),
91     allocated_(true),
92     aSpace_(NULL),
93     thr_(NULL),
94     rs_(NULL),
95         t_(NULL),
96     addr_((Address)-1),
97     ip_(NULL),
98     f_(NULL),
99     bt_(NULL),
100     isPadded_(true),
101     trackRegDefs_(false),
102     inInstrumentation_(false),
103     insertNaked_(false),
104     modifiedStackFrame_(false)
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         }
110     assert(buffer_);
111     memset(buffer_, 0, size+codeGenPadding);
112 }
113
114 // size is in bytes
115 codeGen::codeGen(codeBuf_t *buffer, int size) :
116     buffer_(buffer),
117     offset_(0),
118     size_(size-codeGenPadding),
119     max_(size+codeGenPadding),
120     pc_rel_use_count(0),
121     emitter_(NULL),
122     allocated_(false),
123     aSpace_(NULL),
124     thr_(NULL),
125     rs_(NULL),
126     t_(NULL),
127     addr_((Address)-1),
128     ip_(NULL),
129     f_(NULL),
130     bt_(NULL),
131     isPadded_(true),
132     trackRegDefs_(false),
133     inInstrumentation_(false),
134     insertNaked_(false),
135     modifiedStackFrame_(false)
136 {
137     assert(buffer_);
138     memset(buffer_, 0, size+codeGenPadding);
139 }
140
141
142 codeGen::~codeGen() {
143     if (allocated_ && buffer_) {
144         free(buffer_);
145     }
146 }
147
148 // Deep copy
149 codeGen::codeGen(const codeGen &g) :
150     buffer_(NULL),
151     offset_(g.offset_),
152     size_(g.size_),
153     max_(g.max_),
154     pc_rel_use_count(g.pc_rel_use_count),
155     emitter_(NULL),
156     allocated_(g.allocated_),
157     aSpace_(g.aSpace_),
158     thr_(g.thr_),
159     rs_(g.rs_),
160         t_(g.t_),
161     addr_(g.addr_),
162     ip_(g.ip_),
163     f_(g.f_),
164     bt_(g.bt_),
165     isPadded_(g.isPadded_),
166     trackRegDefs_(g.trackRegDefs_),
167     inInstrumentation_(g.inInstrumentation_),
168     insertNaked_(g.insertNaked_),
169     modifiedStackFrame_(g.modifiedStackFrame_)
170 {
171     if (size_ != 0) {
172         assert(allocated_); 
173         int bufferSize = size_ + (isPadded_ ? codeGenPadding : 0);
174         buffer_ = (codeBuf_t *) malloc(bufferSize);
175         memcpy(buffer_, g.buffer_, bufferSize);
176     }
177 }
178
179 bool codeGen::operator==(void *p) const {
180     return (p == (void *)buffer_);
181 }
182
183 bool codeGen::operator!=(void *p) const {
184     return (p != (void *)buffer_);
185 }
186
187 codeGen &codeGen::operator=(const codeGen &g) {
188     // Same as copy constructor, really
189     invalidate();
190     offset_ = g.offset_;
191     size_ = g.size_;
192     max_ = g.max_;
193     pc_rel_use_count = g.pc_rel_use_count;
194     allocated_ = g.allocated_;
195     thr_ = g.thr_;
196     isPadded_ = g.isPadded_;
197     int bufferSize = size_ + (isPadded_ ? codeGenPadding : 0);
198     inInstrumentation_ = g.inInstrumentation_;
199     insertNaked_ = g.insertNaked_;
200     modifiedStackFrame_ = g.modifiedStackFrame_;
201
202     if (size_ != 0) {
203        assert(allocated_); 
204
205        buffer_ = (codeBuf_t *) malloc(bufferSize);
206        //allocate(g.size_);
207         
208        memcpy(buffer_, g.buffer_, bufferSize);
209     }
210     else
211         buffer_ = NULL;
212     return *this;
213 }
214
215 void codeGen::allocate(unsigned size) 
216 {
217    if (buffer_ && size > size_) {
218       free(buffer_);
219       buffer_ = NULL;
220    }
221
222    size_ = size;
223    max_ = size_ + codeGenPadding;
224
225    if (buffer_ == NULL)
226    {
227       buffer_ = (codeBuf_t *)malloc(max_);
228       isPadded_ = true;
229    }
230    
231    offset_ = 0;
232    allocated_ = true;
233    if (!buffer_) {
234       fprintf(stderr, "%s[%d]:  malloc (%d) failed: %s\n", FILE__, __LINE__, size, strerror(errno));
235    }
236    assert(buffer_);
237 }
238
239 // Very similar to destructor
240 void codeGen::invalidate() {
241     if (allocated_ && buffer_) {
242         free(buffer_);
243     }
244     buffer_ = NULL;
245     size_ = 0;
246     max_ = 0;
247     offset_ = 0;
248     allocated_ = false;
249     isPadded_ = false;
250 }
251
252 bool codeGen::verify() {
253     return true;
254 }
255
256 void codeGen::finalize() {
257     assert(buffer_);
258     assert(size_);
259     cerr << "FINALIZE!" << endl;
260     applyPatches();
261     if (size_ == offset_) return;
262     if (offset_ == 0) {
263         fprintf(stderr, "Warning: offset is 0 in codeGen::finalize!\n");
264         invalidate();
265         return;
266     }
267     buffer_ = (codeBuf_t *)::realloc(buffer_, used());
268     max_ = used();
269     size_ = used();
270     isPadded_ = false;
271 }
272
273 void codeGen::copy(const void *b, const unsigned size, const codeBufIndex_t index) {
274   if (size == 0) return;
275
276   codeBufIndex_t current = getIndex();
277   setIndex(index);
278   copy(b, size);
279   setIndex(current);
280
281 }
282
283 void codeGen::copy(const void *b, const unsigned size) {
284   if (size == 0) return;
285
286   assert(buffer_);
287   
288   realloc(used() + size);
289
290   memcpy(cur_ptr(), b, size);
291
292   moveIndex(size);
293 }
294
295 void codeGen::copy(const std::vector<unsigned char> &buf) {
296   if (buf.empty()) return;
297
298    assert(buffer_);
299    realloc(used() + buf.size());
300    
301    unsigned char * ptr = (unsigned char *)cur_ptr();
302         assert(ptr);
303
304    std::copy(buf.begin(), buf.end(), ptr);
305
306    moveIndex(buf.size());
307 }
308
309 void codeGen::copy(codeGen &gen) {
310   if ((used() + gen.used()) >= size_) {
311     realloc(used() + gen.used()); 
312   }
313
314   memcpy((void *)cur_ptr(), (void *)gen.start_ptr(), gen.used());
315   offset_ += gen.offset_;
316   assert(used() <= size_);
317 }
318
319 void codeGen::copyAligned(const void *b, const unsigned size) {
320   if (size == 0) return;
321
322   assert(buffer_);
323   
324   realloc(used() + size);
325
326   memcpy(cur_ptr(), b, size);
327
328   unsigned alignedSize = size;
329   alignedSize += (CODE_GEN_OFFSET_SIZE - (alignedSize % CODE_GEN_OFFSET_SIZE));
330
331   moveIndex(alignedSize);
332 }
333
334
335
336 // codeBufIndex_t stores in platform-specific units.
337 unsigned codeGen::used() const {
338     return offset_ * CODE_GEN_OFFSET_SIZE;
339 }
340
341 void *codeGen::start_ptr() const {
342     return (void *)buffer_;
343 }
344
345 void *codeGen::cur_ptr() const {
346     assert(buffer_);
347     if (sizeof(codeBuf_t) != CODE_GEN_OFFSET_SIZE)
348         fprintf(stderr, "ERROR: sizeof codeBuf %ld, OFFSET %d\n",
349                 (long) sizeof(codeBuf_t), CODE_GEN_OFFSET_SIZE);
350     assert(sizeof(codeBuf_t) == CODE_GEN_OFFSET_SIZE);
351     codeBuf_t *ret = buffer_;
352     ret += offset_;
353     return (void *)ret;
354 }
355
356 void *codeGen::get_ptr(unsigned offset) const {
357     assert(buffer_);
358     assert(offset < size_);
359     assert(sizeof(codeBuf_t) == CODE_GEN_OFFSET_SIZE);
360     assert((offset % CODE_GEN_OFFSET_SIZE) == 0);
361     unsigned index = offset / CODE_GEN_OFFSET_SIZE;
362     codeBuf_t *ret = buffer_;
363     ret += index;
364     return (void *)ret;
365 }
366
367 void codeGen::update(codeBuf_t *ptr) {
368     assert(buffer_);
369     assert(sizeof(unsigned char) == 1);
370     unsigned diff = ((unsigned char *)ptr) - ((unsigned char *)buffer_);
371     
372     // Align...
373     if (diff % CODE_GEN_OFFSET_SIZE) {
374         diff += CODE_GEN_OFFSET_SIZE - (diff % CODE_GEN_OFFSET_SIZE);
375         assert ((diff % CODE_GEN_OFFSET_SIZE) == 0);
376     }
377     // and integer division rules
378     offset_ = diff / CODE_GEN_OFFSET_SIZE;
379
380     // Keep the pad
381     if (used() >= size_) {
382         if ((used() - size_) >= codeGenPadding) {
383           cerr << "Used too much extra: " << used() - size_ << " bytes" << endl;
384           assert(0 && "Overflow in codeGen");
385         }
386         realloc(2*used());
387     }
388
389     assert(used() <= size_);
390 }
391
392 void codeGen::setIndex(codeBufIndex_t index) {
393     offset_ = index;
394     
395     // Keep the pad
396     if (used() >= size_) {
397       //fprintf(stderr, "WARNING: overflow of codeGen structure (%d requested, %d actual), trying to enlarge\n", used(), size_);
398
399         if ((used() - size_) > codeGenPadding) {
400             assert(0 && "Overflow in codeGen");
401         }
402         realloc(used());
403     }
404     assert(used() <= size_);
405 }
406
407 codeBufIndex_t codeGen::getIndex() const {
408     return offset_;
409 }
410
411 void codeGen::moveIndex(int disp) {
412
413     int cur = getIndex() * CODE_GEN_OFFSET_SIZE;
414     cur += disp;
415     if (cur % CODE_GEN_OFFSET_SIZE) {
416         fprintf(stderr, "Error in codeGen: current index %d/%d, moving by %d, mod %d\n",
417                 getIndex(), cur, disp, cur % CODE_GEN_OFFSET_SIZE);
418     }
419     assert((cur % CODE_GEN_OFFSET_SIZE) == 0);
420     setIndex(cur / CODE_GEN_OFFSET_SIZE);
421 }
422
423 long codeGen::getDisplacement(codeBufIndex_t from, codeBufIndex_t to) {
424    long from_l = (long) from;
425    long to_l = (long) to;
426    return ((to_l - from_l) * CODE_GEN_OFFSET_SIZE);
427 }
428
429 Address codeGen::currAddr() const {
430   if(addr_ == (Address) -1) return (Address) -1;
431   assert(addr_ != (Address) -1);
432   return currAddr(addr_);
433 }
434
435 Address codeGen::currAddr(Address base) const { 
436     return (offset_ * CODE_GEN_OFFSET_SIZE) + base;
437 }
438
439 void codeGen::fill(unsigned fillSize, int fillType) {
440     switch(fillType) {
441     case cgNOP:
442         insnCodeGen::generateNOOP(*this, fillSize);
443         break;
444     case cgTrap: {
445         unsigned curUsed = used();
446         while ((used() - curUsed) < (unsigned) fillSize)
447             insnCodeGen::generateTrap(*this);
448         assert((used() - curUsed) == (unsigned) fillSize);
449         break;
450     }
451     case cgIllegal: {
452         unsigned curUsed = used();
453         while ((used() - curUsed) < (unsigned) fillSize)
454             insnCodeGen::generateIllegal(*this);
455         if ((used() - curUsed) != fillSize) {
456           cerr << "ABORTING: " << used() << " - " << curUsed << " != " << fillSize << endl;
457         }
458         assert((used() - curUsed) == (unsigned) fillSize);
459         break;
460     }
461     default:
462         assert(0 && "unimplemented");
463     }
464 }
465
466 void codeGen::fillRemaining(int fillType) {
467     if (fillType == cgNOP) {
468         insnCodeGen::generateNOOP(*this,
469                                   size_ - used());
470     }
471     else {
472         assert(0 && "unimplemented");
473     }
474 }
475
476 void codeGen::applyTemplate(const codeGen &c) {
477     // Copy off necessary bits...
478
479   emitter_ = c.emitter_;
480   aSpace_ = c.aSpace_;
481   thr_ = c.thr_;
482   rs_ = c.rs_;
483   t_ = c.t_;
484   ip_ = c.ip_;
485   f_ = c.f_;
486   bt_ = c.bt_;
487   inInstrumentation_ = c.inInstrumentation_;
488   insertNaked_ = c.insertNaked_;
489   modifiedStackFrame_ = c.modifiedStackFrame_;
490 }
491
492 void codeGen::setAddrSpace(AddressSpace *a)
493
494    aSpace_ = a; 
495    setCodeEmitter(a->getEmitter());
496 }
497
498 void codeGen::realloc(unsigned newSize) {  
499    if (newSize <= size_) return;
500
501    unsigned increment = newSize - size_;
502    if (increment < codeGenMinAlloc) increment = codeGenMinAlloc;
503
504    size_ += increment;
505    max_ += increment;
506    buffer_ = (codeBuf_t *)::realloc(buffer_, max_);
507    
508    assert(buffer_);
509 }
510
511 void codeGen::addPCRelRegion(pcRelRegion *reg) {
512 #if !defined(cap_noaddr_gen)
513    assert(0);
514 #endif
515    reg->gen = this;
516    reg->cur_offset = used();
517
518    if (startAddr() != (Address) -1 && reg->canPreApply()) {
519      //If we already have addressess for everything (usually when relocating a function)
520      // then don't bother creating the region, just generate the code.
521      reg->apply(startAddr() + reg->cur_offset);
522      delete reg;
523    }
524    else {
525      reg->cur_size = reg->maxSize();
526      fill(reg->cur_size, cgNOP);
527      pcrels_.push_back(reg);
528    }
529 }
530
531 void codeGen::applyPCRels(Address base)
532 {
533    vector<pcRelRegion *>::iterator i;
534
535    codeBufIndex_t orig_position = used();
536    for (i = pcrels_.begin(); i != pcrels_.end(); i++) {
537       pcRelRegion *cur = *i;
538       bool is_last_entry = ((cur->cur_offset + cur->cur_size) >= orig_position);
539
540       //Apply the patch
541       setIndex(cur->cur_offset / CODE_GEN_OFFSET_SIZE);
542       unsigned patch_size = cur->apply(base + cur->cur_offset);
543       assert(patch_size <= cur->cur_size);
544       unsigned size_change = cur->cur_size - patch_size;
545
546       if (size_change) {
547          if (is_last_entry) {
548             //If we resized the last object in the codeGen, then change the
549             // codeGen's end address
550             orig_position = cur->cur_offset + patch_size;
551          }
552          //Fill in any size changes with nops
553          fill(size_change, cgNOP);
554       }
555       delete cur;
556    }
557    setIndex(orig_position / CODE_GEN_OFFSET_SIZE);
558    pcrels_.clear();
559 }
560
561 bool codeGen::hasPCRels() const {
562    return (pcrels_.size() != 0);
563 }
564
565
566 pcRelRegion::pcRelRegion(const instruction &i) :
567    gen(NULL),
568    orig_instruc(i),
569    cur_offset(0),
570    cur_size(0)
571 {
572 }
573
574 pcRelRegion::~pcRelRegion()
575 {
576 }
577
578 std::vector<relocPatch>& codeGen::allPatches() {
579    return patches_;
580 }
581
582 void codeGen::addPatch(codeBufIndex_t index, patchTarget *source, 
583                        unsigned size,
584                        relocPatch::patch_type_t ptype,
585                        Dyninst::Offset off)
586 {
587    relocPatch p(index, source, ptype, this, off, size);
588    patches_.push_back(p);
589 }
590
591 void codeGen::addPatch(const relocPatch &p)
592 {
593    patches_.push_back(p);
594 }
595
596 void codeGen::applyPatches()
597 {
598    std::vector<relocPatch>::iterator i;
599    for (i = patches_.begin(); i != patches_.end(); i++)
600       (*i).applyPatch();
601 }
602
603
604 relocPatch::relocPatch(codeBufIndex_t index, patchTarget *s, patch_type_t ptype,
605                        codeGen *gen, Dyninst::Offset off, unsigned size) :
606   dest_(index),
607   source_(s),
608   size_(size),
609   ptype_(ptype),
610   gen_(gen),
611   offset_(off),
612   applied_(false)
613 {
614
615 }
616
617 void relocPatch::applyPatch()
618 {
619    if (applied_)
620       return;
621
622    Address addr = source_->get_address();
623
624
625    switch (ptype_) {
626       case pcrel:
627         addr = addr - (gen_->startAddr() + offset_);
628       case abs:
629         gen_->copy(&addr, size_, dest_);
630         break;
631       default:
632          assert(0);
633    }
634    applied_ = true;
635 }
636
637 bool relocPatch::isApplied()
638 {
639    return applied_;
640 }
641
642 bool pcRelRegion::canPreApply()
643 {
644   return false;
645 }
646
647 std::string patchTarget::get_name() const {
648    return std::string("UNNAMED");
649 }
650
651 patchTarget::~patchTarget()
652 {
653 }
654
655 toAddressPatch::~toAddressPatch() {
656 }
657
658 Address toAddressPatch::get_address() const 
659
660   return addr; 
661 }
662
663 unsigned toAddressPatch::get_size() const { 
664   return 0; 
665 }
666
667 void toAddressPatch::set_address(Address a) {
668    addr = a;
669 }
670
671 codeGen codeGen::baseTemplate;
672
673 PCThread *codeGen::thread() {
674     return thr_;
675 }
676
677 unsigned codeGen::width() const {
678   return addrSpace()->getAddressWidth();
679 }
680
681 AddressSpace *codeGen::addrSpace() const {
682     if (aSpace_) { return aSpace_; }
683     if (f_) { return f_->proc(); }
684     if (ip_) { return ip_->proc(); }
685     if (thr_) { return thr_->getProc(); }
686     return NULL;
687 }
688
689 instPoint *codeGen::point() const {
690     return ip_;
691 }
692
693 func_instance *codeGen::func() const {
694     if (f_) return f_;
695     if (ip_) return ip_->func();
696     return NULL;
697 }
698
699 registerSpace *codeGen::rs()  const{
700     return rs_;
701 }
702
703 regTracker_t *codeGen::tracker() const {
704     return t_; 
705 }
706
707 Emitter *codeGen::codeEmitter() const {
708     return emitter_;
709 }
710
711 void codeGen::beginTrackRegDefs()
712 {
713    trackRegDefs_ = true;
714 #if defined(arch_x86) || defined(arch_x86_64)
715     regsDefined_ = bitArray(REGNUM_IGNORED+1);
716 #elif defined(arch_power)
717     regsDefined_ = bitArray(registerSpace::lastReg);
718 #elif defined(arch_aarch64)
719     regsDefined_ = bitArray(registerSpace::fpsr);
720 #else
721     regsDefined_ = bitArray();
722 #endif
723
724 }
725
726 void codeGen::endTrackRegDefs()
727 {
728    trackRegDefs_ = false;
729 }
730  
731 const bitArray &codeGen::getRegsDefined()
732 {
733    return regsDefined_;
734 }
735
736 void codeGen::markRegDefined(Register r) {
737    if (!trackRegDefs_)
738       return;
739    regsDefined_[r] = true;
740 }
741
742 bool codeGen::isRegDefined(Register r) {
743    assert(trackRegDefs_);
744    return regsDefined_[r];
745 }
746
747 Dyninst::Architecture codeGen::getArch() const {
748   // Try whatever's defined
749   if (func()) {
750     return func()->ifunc()->isrc()->getArch();
751   }
752   if (addrSpace()) {
753      return addrSpace()->getArch();
754   }
755
756   assert(0);
757   return Arch_none;
758 }
759
760 void codeGen::registerDefensivePad(block_instance *callBlock, Address padStart, unsigned padSize) {
761   // Register a match between a call instruction
762   // and a padding area post-reloc-call for
763   // control flow interception purposes.
764   // This is kind of hacky, btw.
765     //cerr << "Registering pad [" << hex << padStart << "," << padStart + padSize << "], for block @ " << callBlock->start() << dec << endl;
766   defensivePads_[callBlock] = Extent(padStart, padSize);
767 }
768
769
770 #include "InstructionDecoder.h"
771 using namespace InstructionAPI;
772
773 std::string codeGen::format() const {
774    if (!aSpace_) return "<codeGen>";
775
776    stringstream ret;
777
778    Address base = (addr_ != (Address)-1) ? addr_ : 0;
779    InstructionDecoder deco
780       (buffer_,used(),aSpace_->getArch());
781    Instruction::Ptr insn = deco.decode();
782    ret << hex;
783    while(insn) {
784      ret << "\t" << base << ": " << insn->format(base) << " / " << *((const unsigned *)insn->ptr()) << endl;
785       base += insn->size();
786       insn = deco.decode();
787    }
788    ret << dec;
789    return ret.str();
790 };
791