Prototype of shared-block relocation system.
[dyninst.git] / dyninstAPI / src / Relocation / Transformers / Modification.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 "Transformer.h"
33 #include "Modification.h"
34 #include "../patchapi_debug.h"
35 #include "../Atoms/Target.h"
36 #include "../Atoms/Atom.h"
37 #include "../Atoms/CFAtom.h"
38 #include "../Atoms/ASTAtom.h"
39 #include "../Atoms/InstAtom.h"
40 #include "dyninstAPI/src/instPoint.h"
41 #include "dyninstAPI/src/function.h"
42
43 using namespace std;
44 using namespace Dyninst;
45 using namespace Relocation;
46
47 Modification::Modification(const CallModMap &callMod,
48                            const FuncReplaceMap &funcRepl) :
49    callMods_(callMod), 
50    funcReps_(funcRepl) {};
51
52 bool Modification::processTrace(TraceList::iterator &iter, const TraceMap &traceMap) {
53   // We define three types of program modification:
54   // 1) Function call replacement; change the target of the corresponding
55   //    call element
56   // 2) Function call removal; modify the CFelement to have only a
57   //    fallthrough edge
58   // 3) Function replacement; TODO
59
60   Trace::Ptr trace = *iter;
61
62   replaceCall(trace, traceMap); 
63   replaceFunction(trace, traceMap);
64   return true;
65 }
66
67 void Modification::replaceCall(Trace::Ptr trace, const TraceMap &traceMap) {
68    // See if we have a modification for this point
69    CallModMap::const_iterator iter = callMods_.find(trace->block());
70    if (iter == callMods_.end()) return;
71    std::map<func_instance *, func_instance *>::const_iterator iter2 = iter->second.find(trace->func());
72    if (iter2 == iter->second.end()) return;
73
74    func_instance *repl = iter2->second;
75    
76    // Replace the call at the end of this trace /w/ repl (if non-NULL),
77    // or elide completely (if NULL)
78    // We do this via edge twiddling in the Trace
79    
80    if (!repl) {
81       trace->removeTargets(ParseAPI::CALL);
82       return;
83    }
84    Trace::Targets &targets = trace->getTargets(ParseAPI::CALL);
85    for (Trace::Targets::iterator d_iter = targets.begin();
86         d_iter != targets.end(); ++d_iter) {
87       delete *d_iter;
88    }
89    targets.clear();
90    
91    block_instance *entry = repl->entryBlock();
92    assert(entry);
93
94    targets.push_back(getTarget(entry, traceMap));
95 }
96
97 void Modification::replaceFunction(Trace::Ptr trace, const TraceMap &traceMap) {
98    FuncReplaceMap::const_iterator iter = funcReps_.find(trace->func());
99    if (iter == funcReps_.end()) return;
100
101    // See if we're the entry block
102    if (trace->block() != trace->func()->entryBlock()) return;
103
104    // Okay, time to do work. 
105    // Just update the out-edges (removing everything except
106    // a... fallthrough, why not... to the replacement function)
107    trace->removeTargets();
108    trace->getTargets(ParseAPI::FALLTHROUGH).push_back(getTarget(iter->second->entryBlock(), traceMap));
109
110    // And erase anything in the trace to be sure we immediately jump.
111    // Amusingly? Entry instrumentation of the function will still execute...
112    // Need to determine semantics of this and FIXME TODO
113    trace->elements().clear();
114
115    CFAtom::Ptr newCF = CFAtom::create(trace->block()->start());
116    trace->elements().push_back(newCF);
117    trace->cfAtom() = newCF;
118 }
119
120 TargetInt *Modification::getTarget(block_instance *block, const TraceMap &traceMap) {
121    // See if there's a reloc copy
122    TraceMap::const_iterator t_iter = traceMap.find(block);
123    if (t_iter != traceMap.end()) {
124       return new Target<Trace *>(t_iter->second.get());
125    }
126    else {
127       return new Target<block_instance *>(block);
128    }
129 }