Function wrapping implementation and Symtab extensions for undefined symbols
[dyninst.git] / dyninstAPI / src / Relocation / CodeMover.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 #include "Relocation.h"
33 #include "CodeMover.h"
34 #include "Widgets/Widget.h"
35 #include "CFG/RelocBlock.h"
36
37 #include "instructionAPI/h/InstructionDecoder.h" // for debug
38
39 #include "dyninstAPI/src/addressSpace.h" // Also for debug
40 #include "dyninstAPI/src/function.h"
41
42 #include "patchapi_debug.h"
43 #include "CodeTracker.h"
44 #include "CFG/RelocGraph.h"
45
46 using namespace std;
47 using namespace Dyninst;
48 using namespace InstructionAPI;
49 using namespace Relocation;
50
51 CodeMover::CodeMover(CodeTracker *t) :
52    cfg_(new RelocGraph()),
53    addr_(0),
54    tracker_(t),
55    finalized_(false) {};
56
57 CodeMover::Ptr CodeMover::create(CodeTracker *t) {
58    init_debug_patchapi();
59
60    // Make a CodeMover
61    Ptr ret = Ptr(new CodeMover(t));
62    if (!ret) 
63       return Ptr();
64
65    return ret;
66 }  
67
68 CodeMover::~CodeMover() {
69    delete cfg_;
70    // Do not delete codeTracker
71 }
72
73 bool CodeMover::addFunctions(FuncSet::const_iterator begin, 
74                              FuncSet::const_iterator end) {
75    // A vector of Functions is just an extended vector of basic blocks...
76    for (; begin != end; ++begin) {
77       func_instance *func = *begin;
78       if (!func->isInstrumentable()) {
79          continue;
80       }
81       relocation_cerr << "\tAdding function " << func->symTabName() << endl;
82       //if (!addRelocBlocks(func->blocks().begin(), func->blocks().end(), func)) {
83       if (!addRelocBlocks(func->getAllBlocks().begin(), func->getAllBlocks().end(), func)) {
84          return false;
85       }
86     
87       // Add the function entry as Required in the priority map
88       block_instance *entry = func->entryBlock();
89       priorityMap_[entry] = std::make_pair(Required,func);
90    }
91
92    return true;
93 }
94
95 template <typename RelocBlockIter>
96 bool CodeMover::addRelocBlocks(RelocBlockIter begin, RelocBlockIter end, func_instance *f) {
97    for (; begin != end; ++begin) {
98      addRelocBlock(SCAST_BI(*begin), f);
99    }
100    return true;
101 }
102
103 bool CodeMover::addRelocBlock(block_instance *bbl, func_instance *f) {
104    RelocBlock * block = RelocBlock::createReloc(bbl, f);
105    if (!block)
106       return false;
107    cfg_->addRelocBlock(block);
108
109    priorityMap_[bbl] = std::make_pair(Suggested,f);
110       
111    return true;
112 }
113
114 void CodeMover::finalizeRelocBlocks() {
115    if (finalized_) return;
116
117    finalized_ = true;
118    
119    for (RelocBlock *iter = cfg_->begin(); iter != cfg_->end(); iter = iter->next()) {
120       iter->linkRelocBlocks(cfg_);
121       iter->determineSpringboards(priorityMap_);
122    }
123 }
124    
125
126
127 ///////////////////////
128
129
130 bool CodeMover::transform(Transformer &t) {
131    if (!finalized_)
132       finalizeRelocBlocks();
133
134    bool ret = true; 
135
136    t.processGraph(cfg_);
137
138    return ret;
139 }
140
141 bool CodeMover::initialize(const codeGen &templ) {
142    buffer_.initialize(templ, cfg_->size);
143
144    // If they never called transform() this can get missed.
145    if (!finalized_)
146       finalizeRelocBlocks();
147    
148    // Tell all the blocks to do their generation thang...
149    for (RelocBlock *iter = cfg_->begin(); iter != cfg_->end(); iter = iter->next()) {
150       if (!iter->finalizeCF()) return false;
151       
152       if (!iter->generate(templ, buffer_))
153          return false; // Catastrophic failure
154    }
155    return true;
156 }
157
158 // And now the fun begins
159 // 
160 // We wish to minimize the space required by the relocated code. Since some platforms
161 // may have varying space requirements for certain instructions (e.g., branches) this
162 // requires a fixpoint calculation. We start with the original size and increase from
163 // there. 
164 // 
165 // Reasons for size increase:
166 //   1) Instrumentation. It tends to use room. Odd.
167 //   2) Transformed instructions. We may need to replace a single instruction with a
168 //      sequence to emulate its original behavior
169 //   3) Variable-sized instructions. If we increase branch displacements we may need
170 //      to increase the corresponding branch instruction sizes.
171
172 bool CodeMover::relocate(Address addr) {
173    addr_ = addr;
174
175    if (!buffer_.generate(addr)) return false;
176    return true;
177 }
178
179 bool CodeMover::finalize() {     
180    buffer_.extractTrackers(tracker_);
181    return true;
182 }
183
184 void CodeMover::disassemble() const {
185    buffer_.disassemble();
186 }
187
188 unsigned CodeMover::size() const {
189    return buffer_.size();
190 }
191
192 void *CodeMover::ptr() const {
193    return buffer_.ptr();
194 }
195
196 codeGen &CodeMover::gen() {
197    return buffer_.gen();
198 }
199
200 ///////////////////////
201
202 PriorityMap &CodeMover::priorityMap() {
203    return priorityMap_;
204 }
205
206 ///////////////////////
207
208 SpringboardMap &CodeMover::sBoardMap(AddressSpace *as) {
209    // Take the current PriorityMap, digest it,
210    // and return a sorted list of where we need 
211    // patches (from and to)
212
213    //relocation_cerr << "Creating springboard request map" << endl;
214
215    if (sboardMap_.empty()) {
216       for (PriorityMap::const_iterator iter = priorityMap_.begin();
217            iter != priorityMap_.end(); ++iter) {
218          block_instance *bbl = iter->first;
219          const Priority &p = iter->second.first;
220          func_instance *func = iter->second.second;
221
222          // the priority map may include things not in the block
223          // map...
224          RelocBlock * trace = cfg_->findSpringboard(bbl);
225          if (!trace) continue;
226          int labelID = trace->getLabel();
227          Address to = buffer_.getLabelAddr(labelID);
228          
229          sboardMap_.addFromOrigCode(bbl->start(), to, p, func, bbl);
230          //relocation_cerr << "Added map " << hex
231 //                            << bbl->firstInsnAddr() << " -> " 
232 //                            << to << ", " << p << dec << endl;
233       }
234       
235       // And instrumentation that needs updating
236       createInstrumentationSpringboards(as);
237    }
238
239    return sboardMap_;
240 }
241
242 string CodeMover::format() const {
243    stringstream ret;
244   
245    ret << "CodeMover() {" << endl;
246
247    for (RelocBlock *iter = cfg_->begin(); iter != cfg_->end(); iter = iter->next()) {
248       ret << iter->format();
249    }
250    ret << "}" << endl;
251    return ret.str();
252
253 }
254
255 void CodeMover::extractDefensivePads(AddressSpace *AS) {
256    // Needs to be reworked for PatchAPI separation; possibly unnecessary due to 
257    // augmented address lookup capability.
258    const CodeTracker::TrackerList &trackers = tracker_->trackers();
259    for (CodeTracker::TrackerList::const_iterator iter = trackers.begin(); iter != trackers.end(); ++iter) {
260       if ((*iter)->type() == TrackerElement::padding) {
261          PaddingTracker *tmp = static_cast<PaddingTracker *>(*iter);
262          AS->addDefensivePad(tmp->block(), tmp->func(), tmp->reloc(), tmp->pad());
263       }
264    }
265 }
266
267 void CodeMover::createInstrumentationSpringboards(AddressSpace *as) {
268    return;
269 #if 0
270   for (std::map<baseTramp *, Address>::iterator iter = gen().getInstrumentation().begin();
271         iter != gen().getInstrumentation().end(); ++iter) {
272       std::set<Address>::iterator begin, end;
273       as->getPreviousInstrumentationInstances(iter->first, begin, end);
274       for (; begin != end; ++begin) {
275          sboardMap_.addFromRelocatedCode(*begin, iter->second, RelocSuggested);
276          //relocation_cerr << "\t Added inst SB " << hex
277 //                         << *begin << " -> " << iter->second << dec << endl;
278       }
279       as->addInstrumentationInstance(iter->first, iter->second);
280    }
281    for (std::map<baseTramp *, Address>::iterator iter = gen().getRemovedInstrumentation().begin();
282         iter != gen().getRemovedInstrumentation().end(); ++iter) {
283       // As above, without the add
284       std::set<Address>::iterator begin, end;
285       as->getPreviousInstrumentationInstances(iter->first, begin, end);
286       for (; begin != end; ++begin) {
287          sboardMap_.addFromRelocatedCode(*begin, iter->second, RelocSuggested);
288          //relocation_cerr << "\t Added inst SB " << hex
289 //                         << *begin << " -> " << iter->second << dec << endl;
290       }
291    }
292 #endif
293 }
294