Version goes to 9.2. All independent defines/constants for version should be replaced...
[dyninst.git] / parseAPI / src / CodeObject.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30 #include "symtabAPI/h/Symtab.h"
31 #include "symtabAPI/h/Function.h"
32
33 #include "CodeObject.h"
34 #include "CFG.h"
35 #include "Parser.h"
36 #include "debug_parse.h"
37
38 #include "version.h"
39
40 using namespace std;
41 using namespace Dyninst;
42 using namespace Dyninst::ParseAPI;
43
44 namespace {
45     // initialization help
46     static inline CFGFactory * __fact_init(CFGFactory * fact) {
47         if(fact) return fact;
48         return new CFGFactory();
49     }
50 }
51
52 static const int ParseAPI_major_version = DYNINST_MAJOR_VERSION;
53 static const int ParseAPI_minor_version = DYNINST_MINOR_VERSION;
54 static const int ParseAPI_maintenance_version = DYNINST_PATCH_VERSION;
55
56 void CodeObject::version(int& major, int& minor, int& maintenance)
57 {
58     major = ParseAPI_major_version;
59     minor = ParseAPI_minor_version;
60     maintenance = ParseAPI_maintenance_version;
61 }
62
63
64 CodeObject::CodeObject(CodeSource *cs, 
65                        CFGFactory *fact, 
66                        ParseCallback * cb, 
67                        bool defMode) :
68     _cs(cs),
69     _fact(__fact_init(fact)),
70     _pcb(new ParseCallbackManager(cb)),
71     parser(new Parser(*this,*_fact,*_pcb) ),
72     owns_factory(fact == NULL),
73     defensive(defMode),
74     flist(parser->sorted_funcs)
75 {
76     process_hints(); // if any
77 }
78
79 void
80 CodeObject::process_hints()
81 {
82     Function * f = NULL;
83     const vector<Hint> & hints = cs()->hints();
84     vector<Hint>::const_iterator hit;
85
86     for(hit = hints.begin();hit!=hints.end();++hit) {
87         CodeRegion * cr = (*hit)._reg;
88         if(!cs()->regionsOverlap())
89             f = parser->factory()._mkfunc(
90                (*hit)._addr,HINT,(*hit)._name,this,cr,cs());
91         else
92             f = parser->factory()._mkfunc(
93                 (*hit)._addr,HINT,(*hit)._name,this,cr,cr);
94         if(f) {
95             parsing_printf("[%s] adding hint %lx\n",FILE__,f->addr());
96             parser->add_hint(f);
97         }
98     }
99 }
100
101 CodeObject::~CodeObject() {
102     if(owns_factory)
103         delete _fact;
104     delete _pcb;
105     if(parser)
106         delete parser;
107 }
108
109 Function *
110 CodeObject::findFuncByEntry(CodeRegion * cr, Address entry)
111 {
112     return parser->findFuncByEntry(cr,entry);
113 }
114
115 int
116 CodeObject::findFuncs(CodeRegion * cr, Address addr, set<Function*> & funcs)
117 {
118     return parser->findFuncs(cr,addr,funcs);
119 }
120 int
121 CodeObject::findFuncs(CodeRegion * cr, Address start, Address end, set<Function*> & funcs)
122 {
123         return parser->findFuncs(cr,start,end,funcs);
124 }
125
126 Block *
127 CodeObject::findBlockByEntry(CodeRegion * cr, Address addr)
128 {
129     return parser->findBlockByEntry(cr, addr);
130 }
131
132 Block *
133 CodeObject::findNextBlock(CodeRegion * cr, Address addr)
134 {
135     return parser->findNextBlock(cr, addr);
136 }
137
138 int
139 CodeObject::findBlocks(CodeRegion * cr, Address addr, set<Block*> & blocks)
140 {
141     return parser->findBlocks(cr,addr,blocks);
142 }
143
144 // find without parsing.
145 int CodeObject::findCurrentBlocks(CodeRegion * cr, Address addr, set<Block*> & blocks)
146 {
147     return parser->findCurrentBlocks(cr,addr,blocks);
148 }
149
150 void
151 CodeObject::parse() {
152     if(!parser) {
153         fprintf(stderr,"FATAL: internal parser undefined\n");
154         return;
155     }
156     parser->parse();
157 }
158
159 void
160 CodeObject::parse(Address target, bool recursive) {
161     if(!parser) {
162         fprintf(stderr,"FATAL: internal parser undefined\n");
163         return;
164     }
165     parser->parse_at(target,recursive,ONDEMAND);
166 }
167
168 void
169 CodeObject::parse(CodeRegion *cr, Address target, bool recursive) {
170    if (!parser) {
171       fprintf(stderr, "FATAL: internal parser undefined\n");
172       return;
173    }
174    parser->parse_at(cr, target, recursive, ONDEMAND);
175 }
176
177 void
178 CodeObject::parseGaps(CodeRegion *cr, GapParsingType type /* PreambleMatching 0 */) {
179     if(!parser) {
180         fprintf(stderr,"FATAL: internal parser undefined\n");
181         return;
182     }
183     if (type == PreambleMatching) {
184         parser->parse_gap_heuristic(cr);
185     }
186     else {
187         //Try the probabilistic gap parsing
188         parser->probabilistic_gap_parsing(cr);
189     }
190 }
191
192 void
193 CodeObject::add_edge(Block * src, Block * trg, EdgeTypeEnum et)
194 {
195     if (trg == NULL) {
196         parser->link(src, parser->_sink, et, true);
197     } else {
198         parser->link(src,trg,et,false);
199     }
200 }
201
202 void
203 CodeObject::finalize() {
204     parser->finalize();
205 }
206
207 // Call this function on the CodeObject corresponding to the targets,
208 // not the sources, if the edges are inter-module ones
209 // 
210 // create work elements and pass them to the parser
211 bool 
212 CodeObject::parseNewEdges( vector<NewEdgeToParse> & worklist )
213 {
214     vector< ParseWorkElem * > work_elems;
215     vector<std::pair<Address,CodeRegion*> > parsedTargs;
216     for (unsigned idx=0; idx < worklist.size(); idx++) {
217         // see if the target block already exists, in which case we can use
218         // add_edge
219         set<CodeRegion*> regs;
220         cs()->findRegions(worklist[idx].target,regs);
221         assert(1 == regs.size()); // at present this function doesn't support 
222                                   // ambiguous regions for the target address
223         Block *trgB = findBlockByEntry(*(regs.begin()), worklist[idx].target);
224
225         if (trgB) {
226             // don't add edges that already exist 
227             // (this could happen because of shared code)
228             bool edgeExists = false;
229             const Block::edgelist & existingTs = worklist[idx].source->targets();
230             for (Block::edgelist::const_iterator tit = existingTs.begin();
231                  tit != existingTs.end();
232                  tit++)
233             {
234                 if ((*tit)->trg() == trgB && 
235                     (*tit)->type() == worklist[idx].edge_type) 
236                 {
237                     edgeExists = true;
238                 }
239             }
240             if (!edgeExists) {
241                 add_edge(worklist[idx].source, trgB, worklist[idx].edge_type);
242                 if (CALL == worklist[idx].edge_type) {
243                     // if it's a call edge, add it to Function::_call_edge_list
244                     // since we won't re-finalize the function
245                     vector<Function*> funcs;
246                     worklist[idx].source->getFuncs(funcs);
247                     for(vector<Function*>::iterator fit = funcs.begin();
248                         fit != funcs.end();
249                         fit++) 
250                     {
251                         const Block::edgelist & tedges = worklist[idx].source->targets();
252                         for(Block::edgelist::const_iterator eit = tedges.begin();
253                             eit != tedges.end();
254                             eit++)
255                         {
256                             if ((*eit)->trg() == trgB) {
257                                 (*fit)->_call_edge_list.insert(*eit);
258                             }
259                         }
260                     }
261                 }
262             }
263         } 
264         else {
265             parsedTargs.push_back(pair<Address,CodeRegion*>(worklist[idx].target,
266                                                             *regs.begin()));
267             // FIXME this is a memory leak; bundles need to go in a frame or
268             // they will never get reclaimed. Flag for Kevin or Drew
269             //
270             // The inline comment was added after I made this observation
271             // but before the commit; I still don't see it, but if I'm
272             // wrong ignore my warning. --nate
273             //
274             ParseWorkBundle *bundle = new ParseWorkBundle(); //parse_frames will delete when done
275             ParseWorkElem *elem;
276             // created checked_call_ft frames if appropriate.
277             if (worklist[idx].checked && worklist[idx].edge_type == CALL_FT) {
278                 elem = bundle->add(new ParseWorkElem
279                 ( bundle, 
280                   ParseWorkElem::checked_call_ft,
281                   parser->link_tempsink(worklist[idx].source, worklist[idx].edge_type),
282                   worklist[idx].target,
283                   true,
284                   false ));
285             } else {
286                 elem = bundle->add(new ParseWorkElem
287                 ( bundle, 
288                   parser->link_tempsink(worklist[idx].source, worklist[idx].edge_type),
289                   worklist[idx].target,
290                   true,
291                   false ));
292             }
293             
294             work_elems.push_back(elem);
295         }
296     }
297
298     parser->_pcb.batch_begin(); // must batch callbacks and deliver after parsing structures are stable
299     parser->parse_edges( work_elems );
300     parser->_pcb.batch_end(_fact);
301
302     if (defensiveMode()) {
303         // update tampersStack for modified funcs
304         for (unsigned idx=0; idx < parsedTargs.size(); idx++) {
305             set<Function*> tfuncs;
306             findFuncs(parsedTargs[idx].second, parsedTargs[idx].first, tfuncs);
307             for (set<Function*>::iterator fit = tfuncs.begin();
308                  fit != tfuncs.end();
309                  fit++) 
310             {
311                 (*fit)->tampersStack(true);
312             }
313         }
314     }
315     return true;
316 }
317
318 // set things up to pass through to IA_IAPI
319 bool CodeObject::isIATcall(Address insnAddr, std::string &calleeName)
320 {
321    // find region
322    std::set<CodeRegion*> regs;
323    cs()->findRegions(insnAddr, regs);
324    if (regs.size() != 1) {
325       return false;
326    }
327    CodeRegion *reg = *regs.begin();
328
329    // find block
330    std::set<Block*> blocks;
331    findBlocks(reg, insnAddr, blocks);
332    if (blocks.empty()) {
333       return false;
334    }
335    Block *blk = *blocks.begin();
336
337    const unsigned char* bufferBegin = 
338       (const unsigned char *)(cs()->getPtrToInstruction(insnAddr));
339    using namespace InstructionAPI;
340    InstructionDecoder dec = InstructionDecoder(bufferBegin,
341       InstructionDecoder::maxInstructionLength, reg->getArch());
342    InstructionAdapter_t ah = InstructionAdapter_t(
343       dec, insnAddr, this, reg, cs(), blk);
344
345    return ah.isIATcall(calleeName);
346 }
347
348 void CodeObject::startCallbackBatch() {
349    _pcb->batch_begin();
350 }
351
352 void CodeObject::finishCallbackBatch() {
353    _pcb->batch_end(_fact);
354 }
355
356 void CodeObject::destroy(Edge *e) {
357    // The callback deletes the object so that we can
358    // be sure to allow users to access its data before
359    // its freed.
360    // We hand in a CFGFactory so that we have customized
361    // deletion methods.
362    _pcb->destroy(e, _fact);
363 }
364
365 void CodeObject::destroy(Block *b) {
366    parser->remove_block(b);
367    _pcb->destroy(b, _fact);
368 }
369
370 void CodeObject::destroy(Function *f) {
371    parser->remove_func(f);
372    _pcb->destroy(f, _fact);
373 }
374
375 void CodeObject::registerCallback(ParseCallback *cb) {
376    assert(_pcb);
377    _pcb->registerCallback(cb);
378 }
379
380 void CodeObject::unregisterCallback(ParseCallback *cb) {
381    _pcb->unregisterCallback(cb);
382 }
383
384 Address CodeObject::getFreeAddr() const {
385    // Run over the code regions and return the highest address. We do this
386    // so we can allocate more space...
387    Address hi = 0;
388    const std::vector<CodeRegion *> &regions = _cs->regions();
389    for (std::vector<CodeRegion *>::const_iterator iter = regions.begin();
390         iter != regions.end(); ++iter) {
391       hi = (hi > (*iter)->high()) ? hi : (*iter)->high();
392    }
393    return hi;
394 }