Identify shared code regions
[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 static const int ParseAPI_major_version = 1;
56 static const int ParseAPI_minor_version = 0;
57 static const int ParseAPI_maintenance_version = 0;
58
59 void CodeObject::version(int& major, int& minor, int& maintenance)
60 {
61     major = ParseAPI_major_version;
62     minor = ParseAPI_minor_version;
63     maintenance = ParseAPI_maintenance_version;
64 }
65
66
67 CodeObject::CodeObject(CodeSource *cs, 
68                        CFGFactory *fact, 
69                        ParseCallback * cb, 
70                        bool defMode) :
71     _cs(cs),
72     _fact(__fact_init(fact)),
73     _pcb(__pcb_init(cb)),
74     parser(new Parser(*this,*_fact,*_pcb) ),
75     owns_factory(fact == NULL),
76     owns_pcb(cb == NULL),
77     defensive(defMode),
78     flist(parser->sorted_funcs)
79 {
80     process_hints(); // if any
81 }
82
83 void
84 CodeObject::process_hints()
85 {
86     Function * f = NULL;
87     const vector<Hint> & hints = cs()->hints();
88     vector<Hint>::const_iterator hit;
89
90     for(hit = hints.begin();hit!=hints.end();++hit) {
91         CodeRegion * cr = (*hit)._reg;
92         if(!cs()->regionsOverlap())
93             f = parser->factory().mkfunc(
94                 (*hit)._addr,HINT,(*hit)._name,this,cr,cs());
95         else
96             f = parser->factory().mkfunc(
97                 (*hit)._addr,HINT,(*hit)._name,this,cr,cr);
98         if(f) {
99             parsing_printf("[%s] adding hint %lx\n",FILE__,f->addr());
100             parser->add_hint(f);
101         }
102     }
103 }
104
105 CodeObject::~CodeObject() {
106     if(owns_factory)
107         delete _fact;
108     if(owns_pcb)
109         delete _pcb;
110     if(parser)
111         delete parser;
112 }
113
114 Function *
115 CodeObject::findFuncByEntry(CodeRegion * cr, Address entry)
116 {
117     return parser->findFuncByEntry(cr,entry);
118 }
119
120 int
121 CodeObject::findFuncs(CodeRegion * cr, Address addr, set<Function*> & funcs)
122 {
123     return parser->findFuncs(cr,addr,funcs);
124 }
125 int
126 CodeObject::findFuncs(CodeRegion * cr, Address start, Address end, set<Function*> & funcs)
127 {
128         return parser->findFuncs(cr,start,end,funcs);
129 }
130
131 Block *
132 CodeObject::findBlockByEntry(CodeRegion * cr, Address addr)
133 {
134     return parser->findBlockByEntry(cr, addr);
135 }
136
137 int
138 CodeObject::findBlocks(CodeRegion * cr, Address addr, set<Block*> & blocks)
139 {
140     return parser->findBlocks(cr,addr,blocks);
141 }
142
143 void
144 CodeObject::parse() {
145     if(!parser) {
146         fprintf(stderr,"FATAL: internal parser undefined\n");
147         return;
148     }
149     parser->parse();
150 }
151
152 void
153 CodeObject::parse(Address target, bool recursive) {
154     if(!parser) {
155         fprintf(stderr,"FATAL: internal parser undefined\n");
156         return;
157     }
158     parser->parse_at(target,recursive,HINT);
159 }
160
161 void
162 CodeObject::parseGaps(CodeRegion *cr) {
163     if(!parser) {
164         fprintf(stderr,"FATAL: internal parser undefined\n");
165         return;
166     }
167     parser->parse_gap_heuristic(cr);
168 }
169
170 void
171 CodeObject::add_edge(Block * src, Block * trg, EdgeTypeEnum et)
172 {
173     parser->link(src,trg,et,false);
174 }
175
176 void
177 CodeObject::finalize() {
178     parser->finalize();
179 }
180
181 void 
182 CodeObject::deleteFunc(Function *func)
183 {
184     assert(func->_cache_valid);
185     parser->remove_func(func);
186     func->deleteBlocks(func->_blocks, NULL);
187     fact()->free_func(func);
188 }
189
190 // create work elements and pass them to the parser
191 bool 
192 CodeObject::parseNewEdges( vector<Block*> & sources, 
193                            vector<Address> & targets,
194                            vector<EdgeTypeEnum> & edge_types )
195 {
196     vector< ParseWorkElem * > work_elems;
197     for (unsigned idx=0; idx < sources.size(); idx++) {
198         ParseWorkElem *elem = new ParseWorkElem
199             ( NULL, 
200               parser->link_tempsink(sources[idx], edge_types[idx]),
201               targets[idx],
202               true,
203               false );
204         work_elems.push_back(elem);
205     }
206
207     parser->parse_edges( work_elems );
208
209     return true;
210 }