fixing stuff
[dyninst.git] / parseAPI / src / CodeObject.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 #include "symtabAPI/h/Symtab.h"
32 #include "symtabAPI/h/Function.h"
33
34 #include "CodeObject.h"
35 #include "CFG.h"
36 #include "Parser.h"
37 #include "debug_parse.h"
38
39 using namespace std;
40 using namespace Dyninst;
41 using namespace Dyninst::ParseAPI;
42
43 namespace {
44     // initialization help
45     static inline CFGFactory * __fact_init(CFGFactory * fact) {
46         if(fact) return fact;
47         return new CFGFactory();
48     }
49     static inline ParseCallback * __pcb_init(ParseCallback * cb) {
50         if(cb) return cb;
51         return new ParseCallback();
52     }
53 }
54
55 CodeObject::CodeObject(CodeSource *cs, 
56                        CFGFactory *fact, 
57                        ParseCallback * cb, 
58                        bool defMode) :
59     _cs(cs),
60     _fact(__fact_init(fact)),
61     _pcb(__pcb_init(cb)),
62     parser(new Parser(*this,*_fact,*_pcb) ),
63     owns_factory(fact == NULL),
64     owns_pcb(cb == NULL),
65     defensive(defMode),
66     flist(parser->sorted_funcs)
67 {
68     process_hints(); // if any
69 }
70
71 void
72 CodeObject::process_hints()
73 {
74     Function * f = NULL;
75     const vector<Hint> & hints = cs()->hints();
76     vector<Hint>::const_iterator hit;
77
78     for(hit = hints.begin();hit!=hints.end();++hit) {
79         CodeRegion * cr = (*hit)._reg;
80         if(!cs()->regionsOverlap())
81             f = parser->factory().mkfunc(
82                 (*hit)._addr,HINT,(*hit)._name,this,cr,cs());
83         else
84             f = parser->factory().mkfunc(
85                 (*hit)._addr,HINT,(*hit)._name,this,cr,cr);
86         if(f) {
87             parsing_printf("[%s] adding hint %lx\n",FILE__,f->addr());
88             parser->add_hint(f);
89         }
90     }
91 }
92
93 CodeObject::~CodeObject() {
94     if(owns_factory)
95         delete _fact;
96     if(owns_pcb)
97         delete _pcb;
98     if(parser)
99         delete parser;
100 }
101
102 Function *
103 CodeObject::findFuncByEntry(CodeRegion * cr, Address entry)
104 {
105     return parser->findFuncByEntry(cr,entry);
106 }
107
108 int
109 CodeObject::findFuncs(CodeRegion * cr, Address addr, set<Function*> & funcs)
110 {
111     return parser->findFuncs(cr,addr,funcs);
112 }
113
114 Block *
115 CodeObject::findBlockByEntry(CodeRegion * cr, Address addr)
116 {
117     return parser->findBlockByEntry(cr, addr);
118 }
119
120 int
121 CodeObject::findBlocks(CodeRegion * cr, Address addr, set<Block*> & blocks)
122 {
123     return parser->findBlocks(cr,addr,blocks);
124 }
125
126 void
127 CodeObject::parse() {
128     if(!parser) {
129         fprintf(stderr,"FATAL: internal parser undefined\n");
130         return;
131     }
132     parser->parse();
133 }
134
135 void
136 CodeObject::parse(Address target, bool recursive) {
137     if(!parser) {
138         fprintf(stderr,"FATAL: internal parser undefined\n");
139         return;
140     }
141     parser->parse_at(target,recursive,HINT);
142 }
143
144 void
145 CodeObject::parseGaps(CodeRegion *cr) {
146     if(!parser) {
147         fprintf(stderr,"FATAL: internal parser undefined\n");
148         return;
149     }
150     parser->parse_gap_heuristic(cr);
151 }
152
153 void
154 CodeObject::add_edge(Block * src, Block * trg, EdgeTypeEnum et)
155 {
156     parser->link(src,trg,et,false);
157 }
158
159 void
160 CodeObject::finalize() {
161     parser->finalize();
162 }
163
164 void 
165 CodeObject::deleteFunc(Function *func)
166 {
167     assert(func->_cache_valid);
168     parser->remove_func(func);
169     func->deleteBlocks(func->_blocks, NULL);
170     fact()->free_func(func);
171 }
172
173 // create work elements and pass them to the parser
174 bool 
175 CodeObject::parseNewEdges( vector<Block*> & sources, 
176                            vector<Address> & targets,
177                            vector<EdgeTypeEnum> & edge_types )
178 {
179     map< Function * , FuncReturnStatus > modfuncs;
180
181     vector< ParseWorkElem * > work_elems;
182     for (unsigned idx=0; idx < sources.size(); idx++) {
183         ParseWorkElem *elem = new ParseWorkElem
184             ( NULL, 
185               parser->link_tempsink(sources[idx], edge_types[idx]),
186               targets[idx],
187               true,
188               false );
189         work_elems.push_back(elem);
190
191         if (defensiveMode()) {
192             vector< Function * > funcs;
193             sources[idx]->getFuncs(funcs);
194             for (unsigned fidx=0; fidx < funcs.size(); fidx++) {
195                 modfuncs[funcs[fidx]] = funcs[fidx]->retstatus();
196             }
197         }
198     }
199
200     parser->parse_edges( work_elems );
201
202     // the only functions whose parses could have been extended are those
203     // that have had new edges added to them, but stack tamper calculations 
204     // should be re-done on the extended functions and callers to those 
205     // functions can now be determined to be returning
206     for (map<Function*,FuncReturnStatus>::iterator fit = modfuncs.begin(); 
207          modfuncs.end() != fit; 
208          fit++) 
209     {
210         InstructionAdapter(Address start, ParseAPI::CodeObject *o , 
211             ParseAPI::CodeRegion* r, InstructionSource * isrc);
212         InstructionAdapter ah ((*fit).first->addr(), 
213                                this, 
214                                (*fit).first->region(), cs());
215         if ((*fit).first->retstatus() != (*fit).second) {
216             Address tamperAddr=0;
217             StackTamper st = ah.tampersStack((*fit).first, tamperAddr);
218             if (TAMPER_NONE == st || TAMPER_REL == st || TAMPER_ABS == st) {
219                 vector<Block*> newsrcs;
220                 vector<Address> newtrgs;
221                 vector<edge_type> newtypes;
222                 Function::edgelist calls = (*fit).first->callEdges();
223                 for (Function::edgelist::iterator cit = calls.begin();
224                      cit != calls.end();
225                      cit++) 
226                 {
227                      newsrcs.push_back((*cit)->src());
228                 }
229                 if (TAMPER_NONE == st) {
230                     for (unsigned idx=0; idx < calls.size(); idx++) {
231                         add calls;
232                     }
233                 }
234                 if (TAMPER_REL == st) {
235                 }
236                 if (TAMPER_ABS == st) {
237                 }
238             }
239         }
240     }
241
242     return true;
243 }