Define cap_stack_mods and properly limit stack mods to x86,x86_64
[dyninst.git] / dyninstAPI / src / Relocation / Widgets / StackModWidget.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 #include "StackModWidget.h"
32 #include "instructionAPI/h/Instruction.h"
33 #include "../dyninstAPI/src/debug.h"
34 #include "CFG.h"
35 #include "../CFG/RelocBlock.h"
36
37 #include "../CodeTracker.h"
38 #include "../CodeBuffer.h"
39
40 using namespace Dyninst;
41 using namespace Relocation;
42 using namespace InstructionAPI;
43
44 StackModWidget::Ptr StackModWidget::create(Instruction::Ptr insn,
45                                            Address addr,
46                        signed long newDisp,
47                        Architecture arch) {
48   assert(addr);
49   return Ptr(new StackModWidget(insn, addr, newDisp, arch));
50 }
51
52 TrackerElement *StackModWidget::tracker(const RelocBlock *t) const {
53    EmulatorTracker *e = new EmulatorTracker(addr_, t->block(), t->func());
54   return e;
55 }
56
57 bool StackModWidget::generate(const codeGen &, 
58                               const RelocBlock *t, 
59                               CodeBuffer &buffer) {
60     relocation_cerr << "  Generating a stackframe-sensitive memory access (" << insn_->format()
61         << "," << std::hex << addr_ 
62         <<", newDisp " << newDisp_ << std::dec << ")" << endl;
63
64     StackModPatch *newPatch = new StackModPatch(insn_, newDisp_, arch_, addr_);
65     buffer.addPatch(newPatch, tracker(t));
66
67   return true;
68 }
69
70 string StackModWidget::format() const {
71   stringstream ret;
72   ret << "MemRel(" << insn_->format() << ")";
73   return ret.str();
74 }
75
76 bool StackModPatch::apply(codeGen &gen, CodeBuffer *) {
77 #if defined(cap_stack_mods)
78     instruction ugly_insn(orig_insn->ptr());
79     if (gen.modifiedStackFrame()) {
80         relocation_cerr << "  Calling modifyDisp" << endl;
81         if (!insnCodeGen::modifyDisp(newDisp, ugly_insn, gen, arch, addr)) return false;
82         return true;
83     } else {
84         relocation_cerr << "  Preserving orig" << endl;
85         // Preserve the original instruction
86         GET_PTR(newInsn, gen);
87         const unsigned char* origInsn = ugly_insn.ptr();
88         for (unsigned iter = 0; iter < ugly_insn.size(); iter++) {
89             *newInsn++ = *origInsn++;
90         }
91         SET_PTR(newInsn, gen);
92     }
93     return true;
94 #else
95     return false;
96 #endif
97 }
98
99 unsigned StackModPatch::estimate(codeGen &) {
100    // Underestimate if possible
101    return orig_insn->size();
102 }