Update copyright to LGPL on all files
[dyninst.git] / depGraphAPI / src / Absloc.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 "Absloc.h"
33 #include "Graph.h"
34 #include "Edge.h"
35 #include "Node.h"
36 #include <assert.h>
37
38 #include "Register.h"
39 #include "InstructionAST.h"
40 #include "Instruction.h"
41 #include "Expression.h"
42
43 #include "dyninstAPI/src/stackanalysis.h"
44 #include "dyninstAPI/src/function.h"
45 #include "dyninstAPI/src/image-func.h"
46
47 #include "BPatch_function.h"
48
49 using namespace Dyninst;
50 using namespace Dyninst::DepGraphAPI;
51 using namespace Dyninst::InstructionAPI;
52 using namespace dyn_detail::boost;
53
54 void Absloc::getAbslocs(AbslocSet &locs) {
55     RegisterLoc::getRegisterLocs(locs);
56     StackLoc::getStackLocs(locs);
57     //HeapLoc::getHeapLocs(locs);
58     MemLoc::getMemLocs(locs);
59     ImmLoc::getImmLocs(locs);
60 }
61
62 RegisterLoc::RegisterMap RegisterLoc::allRegLocs_;
63 Absloc::Ptr RegisterLoc::pc_;
64
65 void RegisterLoc::getRegisterLocs(AbslocSet &locs) {
66     for (RegisterMap::iterator iter = allRegLocs_.begin(); iter != allRegLocs_.end(); iter++) {
67         locs.insert((*iter).second);
68     }
69 }
70
71 Absloc::Ptr RegisterLoc::getRegLoc(const InstructionAPI::RegisterAST::Ptr reg) {
72     // Upconvert the register to its canonical container
73     InstructionAPI::RegisterAST::Ptr container = dynamic_pointer_cast<InstructionAPI::RegisterAST>(RegisterAST::promote(reg));
74     if (!container) {
75         assert(0);
76         return Absloc::Ptr();
77     }
78
79     // Look up by name and return    
80     if (allRegLocs_.find(*container) == allRegLocs_.end()) {
81         RegisterLoc::Ptr rP = RegisterLoc::Ptr(new RegisterLoc(container));
82         allRegLocs_[*container] = rP;
83 // Make sure we have a canonical PC, since < on a shared pointer is only
84 // pointer uniqueness and nothing else...
85         if (rP->isPC())
86             pc_ = rP;
87
88     }
89     
90     return allRegLocs_[*container];
91 }
92
93 Absloc::Ptr RegisterLoc::makePC() {
94     if (pc_) return pc_;
95     
96     // Make the register...
97     RegisterAST rPC = RegisterAST::makePC();
98     RegisterAST::Ptr rpPC = RegisterAST::Ptr(new RegisterAST(rPC));
99     pc_ = RegisterLoc::Ptr(new RegisterLoc(rpPC));
100     return pc_;
101 }
102
103 const int StackLoc::STACK_GLOBAL = MININT;
104 const int StackLoc::STACK_REGION_DEFAULT = 0;
105
106 StackLoc::StackMap StackLoc::stackLocs_;
107
108 std::string StackLoc::format() const {
109     std::stringstream ret;
110
111     if (slot_ == STACK_GLOBAL) {
112         return std::string("STACK");
113     }
114     
115     ret << "STACK_" << slot_ << "_" << region_;
116
117     return ret.str(); 
118 }
119
120 void StackLoc::getStackLocs(AbslocSet &locs) {
121     for (StackMap::iterator iter = stackLocs_.begin();
122          iter != stackLocs_.end(); iter++) {
123         locs.insert((*iter).second);
124     }
125 }
126
127 Absloc::Ptr StackLoc::getStackLoc(int slot, int region) {
128     if (stackLocs_.find(std::make_pair(slot, region)) == stackLocs_.end()) {
129         StackLoc::Ptr sP = StackLoc::Ptr(new StackLoc(slot, region));
130         
131         stackLocs_[std::make_pair(slot, region)] = sP;
132     }
133     
134     return stackLocs_[std::make_pair(slot, region)];
135 }
136
137 Absloc::Ptr StackLoc::getStackLoc() {
138     // Look up by name and return    
139     return getStackLoc(STACK_GLOBAL, STACK_REGION_DEFAULT);
140 }
141
142 StackLoc::AbslocSet StackLoc::getAliases() const{
143     AbslocSet ret;
144
145     // If we're a specific stack slot, return the generic
146     // stack slot(s)
147     if (slot_ == STACK_GLOBAL) {
148         for (StackMap::const_iterator iter = stackLocs_.begin();
149              iter != stackLocs_.end(); iter++) {
150             if ((*iter).first.first != STACK_GLOBAL)
151                 ret.insert((*iter).second);
152         }
153     } 
154     else {
155         ret.insert(getStackLoc());
156     }
157     
158     // Global memory references might touch the stack...
159     ret.insert(MemLoc::getMemLoc());
160
161     return ret;
162 }
163
164 #if 0
165 Absloc::Ptr HeapLoc::heapLoc_;
166
167 void HeapLoc::getHeapLocs(AbslocSet &locs) {
168     if (heapLoc_) locs.insert(heapLoc_);
169     return;
170 }
171
172 Absloc::Ptr HeapLoc::getHeapLoc() {
173     if (!heapLoc_) {
174         heapLoc_ = HeapLoc::Ptr(new HeapLoc());
175     }
176     return heapLoc_;
177 }
178
179 HeapLoc::AbslocSet HeapLoc::getAliases() {
180     AbslocSet ret;
181     // Global memory reference is included...
182     ret.insert(MemLoc::getMemLoc());
183     return ret;
184 }
185 #endif
186
187 const Address MemLoc::MEM_GLOBAL = (Address) -1;
188 MemLoc::MemMap MemLoc::memLocs_;
189
190 std::string MemLoc::format() const { 
191     if (addr_ == MEM_GLOBAL) {
192         return "Mem_UNKNOWN_";
193     }
194     std::stringstream ret;
195
196     ret << "Mem_" << std::hex << addr_;
197     return ret.str();
198 }
199
200 void MemLoc::getMemLocs(AbslocSet &locs) {
201     for (MemMap::iterator iter = memLocs_.begin();
202          iter != memLocs_.end(); iter++) {
203         locs.insert((*iter).second);
204     }
205 }
206
207 Absloc::Ptr MemLoc::getMemLoc(Address addr) {
208     // Look up by name and return    
209     if (memLocs_.find(addr) == memLocs_.end()) {
210         MemLoc::Ptr mP = MemLoc::Ptr(new MemLoc(addr));
211         
212         memLocs_[addr] = mP;
213     }
214     
215     return memLocs_[addr];
216 }
217
218 Absloc::Ptr MemLoc::getMemLoc() {
219     return getMemLoc(MEM_GLOBAL);
220 }
221
222 MemLoc::AbslocSet MemLoc::getAliases() const {
223     AbslocSet ret;
224     if (addr_ != MEM_GLOBAL) {
225         ret.insert(getMemLoc());
226     }
227     else {
228         // All known memory locations
229         for (MemMap::const_iterator iter = memLocs_.begin();
230              iter != memLocs_.end(); iter++) {
231             if ((*iter).first != MEM_GLOBAL)
232                 ret.insert((*iter).second);
233         }
234         // All stack locations
235         StackLoc::getStackLocs(ret);
236     }
237
238     return ret;
239 }
240
241 ImmLoc::Ptr ImmLoc::immLoc_; 
242
243 std::string ImmLoc::format() const { 
244     return "Immediate";
245 }
246
247 Absloc::Ptr ImmLoc::getImmLoc() {
248     if (immLoc_) return immLoc_;
249
250     immLoc_ = ImmLoc::Ptr(new ImmLoc());
251
252     return immLoc_;
253 }
254
255 bool RegisterLoc::isSP() const { 
256     return ((reg_->getID() == r_ESP) || (reg_->getID() == r_RSP)); 
257 }
258
259 bool RegisterLoc::isPC() const {
260     return ((reg_->getID() == r_EIP) || (reg_->getID() == r_RIP));
261 }
262
263 bool RegisterLoc::isFlag() const {
264     return ((reg_->getID() >= r_OF) && (reg_->getID() <= r_RF));
265 }
266
267 bool RegisterLoc::isSP(RegisterAST::Ptr reg) { 
268     RegisterAST::Ptr reg_ = dynamic_pointer_cast<RegisterAST>(RegisterAST::promote(reg));
269     return ((reg_->getID() == r_ESP) ||
270             (reg_->getID() == r_RSP)); 
271 }
272
273 bool RegisterLoc::isPC(RegisterAST::Ptr reg) {
274     RegisterAST::Ptr reg_ = dynamic_pointer_cast<RegisterAST>(RegisterAST::promote(reg));
275     return ((reg_->getID() == r_EIP) || 
276             (reg_->getID() == r_RIP));
277 }
278
279 bool RegisterLoc::isFlag(RegisterAST::Ptr reg) {
280     RegisterAST::Ptr reg_ = dynamic_pointer_cast<RegisterAST>(RegisterAST::promote(reg));
281     return ((reg_->getID() >= r_OF) && 
282             (reg_->getID() <= r_RF));
283 }