Fixes compile error and Merge branch 'Defensive' of ssh://coriander.cs.wisc.edu/u...
[dyninst.git] / dyninstAPI / src / block.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 "function.h"
33 #include "parse-cfg.h"
34 #include "process.h"
35
36 #include "mapped_object.h"
37 #include "mapped_module.h"
38 #include "InstructionDecoder.h"
39 #include "PatchModifier.h"
40 #include <set>
41 #include <sstream>
42 #include "Relocation/Transformers/Movement-analysis.h"
43
44 using namespace Dyninst;
45 using namespace Dyninst::ParseAPI;
46
47 block_instance::block_instance(ParseAPI::Block *ib,
48                                mapped_object *obj)
49   : PatchBlock(ib, obj) {
50   // We create edges lazily
51 };
52
53 // Fork constructor
54 block_instance::block_instance(const block_instance *parent,
55                                mapped_object *childObj)
56   : PatchBlock(parent, childObj) {
57   // We also need to copy edges.
58   // Thing is, those blocks may not exist yet...
59   // So we wait, and do edges after all blocks have
60   // been created
61 }
62
63 // Edges are deleted at the mapped_object layer
64 block_instance::~block_instance() 
65 {
66 }
67
68 AddressSpace *block_instance::addrSpace() const {
69   return obj()->proc();
70 }
71
72 edge_instance *block_instance::getFallthrough() {
73   for (edgelist::const_iterator iter = getTargets().begin(); iter != getTargets().end(); ++iter) {
74     if ((*iter)->type() == FALLTHROUGH ||
75         (*iter)->type() == CALL_FT ||
76         (*iter)->type() == COND_NOT_TAKEN) {
77       return SCAST_EI(*iter);
78     }
79   }
80   return NULL;
81 }
82
83 block_instance *block_instance::getFallthroughBlock() {
84   edge_instance *ft = getFallthrough();
85   if (ft &&
86       !ft->sinkEdge())
87     return ft->trg();
88   else
89     return NULL;
90 }
91
92 edge_instance *block_instance::getTarget() {
93   for (edgelist::const_iterator iter = getTargets().begin(); iter != getTargets().end(); ++iter) {
94     if ((*iter)->type() == CALL ||
95         (*iter)->type() == DIRECT ||
96         (*iter)->type() == COND_TAKEN) {
97       return SCAST_EI(*iter);
98     }
99   }
100   return NULL;
101 }
102
103 int block_instance::id() const {
104   return llb()->id();
105 }
106
107 using namespace Dyninst::Relocation;
108 void block_instance::triggerModified() {
109     // KEVINTODO: implement this: remove block from Relocation info caching...
110    //PCSensitiveTransformer::invalidateCache(this);
111 }
112
113 void block_instance::setNotAbruptEnd()
114 {
115     llb()->setAbruptEnd(false);
116     vector<func_instance*> funcs;
117     getFuncs(std::back_inserter(funcs));
118     for (vector<func_instance*>::iterator fit = funcs.begin();
119          fit != funcs.end(); fit++)
120     {
121         (*fit)->removeAbruptEnd(this);
122     }
123 }
124
125 std::string block_instance::calleeName() {
126   // How the heck do we do this again?
127   return obj()->getCalleeName(this);
128 }
129
130 void block_instance::updateCallTarget(func_instance *func) {
131   // Update a sink-typed call edge to
132   // have an inter-module target
133    //
134    // Preserving original behavior on sink edges only
135    //
136   edge_instance *e = getTarget();
137   if (e && e->sinkEdge()) {
138      PatchAPI::PatchModifier::redirect(e, func->entryBlock());
139   } else {
140      mal_printf("WARNING: tried to update the call target of a block "
141         "[%lx %lx) with a non-sink target %lx to %lx %s[%d]\n", start(),
142         end(), e->target()->start(), func->addr(), FILE__,__LINE__);
143   }
144 }
145
146 func_instance *block_instance::entryOfFunc() const {
147   parse_block *b = SCAST_PB(llb());
148   parse_func *e = b->getEntryFunc();
149   if (!e) return NULL;
150   return obj()->findFunction(e);
151 }
152
153 bool block_instance::isFuncExit() const {
154   parse_block *b = SCAST_PB(llb());
155   return b->isExitBlock();
156 }
157
158 func_instance *block_instance::findFunction(ParseAPI::Function *p) {
159   return obj()->findFunction(p);
160 }
161
162
163 void *block_instance::getPtrToInstruction(Address addr) const {
164   if (addr < start()) return NULL;
165   if (addr > end()) return NULL;
166   return obj()->getPtrToInstruction(addr);
167 }
168