More ppc32_bgp changes
[dyninst.git] / dyninstAPI / src / Parsing.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 <stdio.h>
32
33 #if defined(cap_instruction_api)
34 #include "InstructionDecoder.h"
35 #include "Instruction.h"
36 #else
37 #include "parseAPI/src/InstrucIter.h"
38 #endif
39
40 #include "symtab.h"
41 #include "image-func.h"
42 #include "instPoint.h"
43 #include "Parsing.h"
44 #include "debug.h"
45
46 #if defined(os_aix) || defined(os_solaris)
47 #include "parRegion.h"
48 #endif
49
50 using namespace Dyninst;
51 using namespace Dyninst::ParseAPI;
52 using namespace Dyninst::InstructionAPI;
53
54 // windows.h pollutes namespace with min/max macros
55 #undef min
56 #undef max
57
58 #if defined(VERBOSE_CFG_FACTORY)
59 #define record_func_alloc(x) do { _record_func_alloc(x); } while(0)
60 #define record_edge_alloc(x,s) do { _record_edge_alloc(x,s); } while(0)
61 #define record_block_alloc(s) do { _record_block_alloc(s); } while(0)
62 #else
63 #define record_func_alloc(x) do { } while(0)
64 #define record_edge_alloc(x,s) do { } while(0)
65 #define record_block_alloc(s) do { } while(0)
66 #endif
67
68 void DynCFGFactory::dump_stats()
69 {
70     fprintf(stderr,"===DynCFGFactory for image %p===\n",_img);
71     fprintf(stderr,"   Functions:\n");
72     fprintf(stderr,"   %-12s src\n","cnt");
73     for(int i=0;i<_funcsource_end_;++i) {
74         fprintf(stderr,"   %-12d %3d\n",_func_allocs[i],i);
75     }
76     fprintf(stderr,"   Edges:\n");
77     fprintf(stderr,"   %-12s type\n","cnt");
78     for(int i=0;i<_edgetype_end_;++i) {
79         fprintf(stderr,"   %-12d %4d\n",_edge_allocs[i],i);
80     }
81     fprintf(stderr,"   Blocks:\n");
82     fprintf(stderr,"   %-12d total\n",_block_allocs);
83     fprintf(stderr,"   %-12d sink\n",_sink_block_allocs);
84 }
85
86 DynCFGFactory::DynCFGFactory(image * im) :
87     _img(im),
88     _func_allocs(_funcsource_end_),
89     _edge_allocs(_edgetype_end_),
90     _block_allocs(0),
91     _sink_block_allocs(0)
92 {
93
94 }
95
96 DynCFGFactory::~DynCFGFactory()
97 {
98     free_all();
99 }
100
101 Function *
102 DynCFGFactory::mkfunc(
103     Address addr, 
104     FuncSource src, 
105     std::string name,
106     CodeObject * obj,
107     CodeRegion * reg,
108     InstructionSource * isrc)
109 {
110     image_func * ret;
111     SymtabAPI::Symtab * st;
112     SymtabAPI::Function * stf;
113     pdmodule * pdmod;
114     image_instPoint * entry;
115
116     record_func_alloc(src);
117
118     st = _img->getObject();
119     if(!st->findFuncByEntryOffset(stf,addr)) {
120         pdmod = _img->getOrCreateModule(st->getDefaultModule());
121         stf = st->createFunction(
122             name,addr,std::numeric_limits<size_t>::max(),pdmod->mod());
123     } else
124         pdmod = _img->getOrCreateModule(stf->getModule());
125     assert(stf);
126
127     ret = new image_func(stf,pdmod,_img,obj,reg,isrc,src);
128     funcs_.add(*ret);
129
130     if(obj->cs()->linkage().find(ret->addr()) != obj->cs()->linkage().end())
131         ret->isPLTFunction_ = true;
132
133     // make an entry instpoint
134     size_t insn_size = 0;
135     unsigned char * insn_buf = (unsigned char *)isrc->getPtrToInstruction(addr);
136 #if defined(cap_instruction_api)
137     InstructionDecoder dec(insn_buf,InstructionDecoder::maxInstructionLength,
138         isrc->getArch());
139     Instruction::Ptr insn = dec.decode();
140     if(insn)
141         insn_size = insn->size();
142 #else
143    InstrucIter ah(addr,isrc);
144    instruction insn = ah.getInstruction();
145    insn_size = insn.size();
146 #endif
147
148 #if defined(os_vxworks)
149    // Relocatable objects (kernel modules) are instrumentable on VxWorks.
150     if(!ret->isInstrumentableByFunctionName())
151 #else
152     if(!ret->isInstrumentableByFunctionName() || _img->isRelocatableObj())
153 #endif
154         ret->setInstLevel(UNINSTRUMENTABLE);
155     else {
156         // Create instrumentation points for non-plt functions 
157         if(obj->cs()->linkage().find(addr) == obj->cs()->linkage().end()) { 
158             entry = new image_instPoint(addr,insn_buf,insn_size,
159                                         _img,functionEntry);
160             _img->addInstPoint(entry);
161         } else {
162             ret->setInstLevel(UNINSTRUMENTABLE);
163         }
164     }
165
166     /*
167      * OMP parallel regions support
168      */
169 #if defined(os_solaris)
170     if(strstr(stf->getAllMangledNames()[0].c_str(), "_$") != NULL){
171         image_parRegion * pR = new image_parRegion(stf->getOffset(),ret);
172         _img->parallelRegions.push_back(pR);
173     }
174 #elif defined(os_aix)
175     if(strstr(stf->getAllMangledNames()[0].c_str(), "@OL@") != NULL){
176         image_parRegion * pR = new image_parRegion(stf->getOffset(),ret);
177         _img->parallelRegions.push_back(pR);
178     }
179 #endif
180
181     return ret;
182 }
183
184 Block *
185 DynCFGFactory::mkblock(Function * f, CodeRegion *r, Address addr) {
186     image_basicBlock * ret;
187
188     record_block_alloc(false);
189
190     ret = new image_basicBlock((image_func*)f,r,addr);
191     //fprintf(stderr,"mkbloc(%lx, %lx) produced %p\n",f->addr(),addr,ret);
192     blocks_.add(*ret);
193
194     //fprintf(stderr,"mkbloc(%lx, %lx) returning %p\n",f->addr(),addr,ret);
195
196     if ( _img->trackNewBlocks_ ) 
197     {
198         _img->newBlocks_.push_back(ret);
199     }
200     return ret;
201 }
202 Block *
203 DynCFGFactory::mksink(CodeObject *obj, CodeRegion *r) {
204     image_basicBlock * ret;
205
206     record_block_alloc(true);
207
208     ret = new image_basicBlock(obj,r,numeric_limits<Address>::max());
209     blocks_.add(*ret);
210     return ret;
211 }
212
213 Edge *
214 DynCFGFactory::mkedge(Block * src, Block * trg, EdgeTypeEnum type) {
215     image_edge * ret;
216
217     record_edge_alloc(type,false); // FIXME can't tell if it's a sink
218
219     ret = new image_edge((image_basicBlock*)src,
220                          (image_basicBlock*)trg,
221                          type);
222
223     //fprintf(stderr,"mkedge between Block %p and %p, img_bb: %p and %p\n",
224         //src,trg,(image_basicBlock*)src,(image_basicBlock*)trg);
225     edges_.add(*ret);
226
227     return ret;
228 }
229
230 void
231 DynParseCallback::unresolved_cf(Function *f,Address addr,default_details*det)
232 {
233     image_instPoint * p =
234         new image_instPoint(
235             addr,
236             det->ibuf,
237             det->isize,
238             _img,
239             otherPoint,
240             true);
241
242     if (det->isbranch)
243         static_cast<image_func*>(f)->setInstLevel(UNINSTRUMENTABLE);
244
245     _img->addInstPoint(p);
246 }
247
248 void
249 DynParseCallback::abruptEnd_cf(Address addr,default_details*det)
250 {
251     image_instPoint * p =
252         new image_instPoint(
253             addr,
254             det->ibuf,
255             det->isize,
256             _img,
257             abruptEnd,
258             false);
259
260     // check for instrumentability? FIXME
261     // ah.getInstLevel or something
262
263     _img->addInstPoint(p);
264 }
265
266 void
267 DynParseCallback::newfunction_retstatus(Function *func)
268 {
269     dynamic_cast<image_func*>(func)->setinit_retstatus( func->retstatus() );
270 }
271
272 void
273 DynParseCallback::block_split(Block * /*first_*/, Block *second_)
274 {
275     image_basicBlock *second = (image_basicBlock*) second_;
276     _img->addSplitBlock(second);
277 }
278
279 void
280 DynParseCallback::patch_jump_neg1(Address addr)
281 {
282     Architecture arch = _img->codeObject()->cs()->getArch();
283     assert( Arch_x86 == arch || Arch_x86_64 == arch );
284
285     unsigned char * ptr = (unsigned char *) _img->getPtrToInstruction(addr);
286     ptr[0] = 0x90;
287 }
288
289 void
290 DynParseCallback::interproc_cf(Function*f,Address addr,interproc_details*det)
291 {
292     image_instPoint * p = NULL;
293     switch(det->type) {
294         case interproc_details::ret:
295             p = new image_instPoint(
296                     addr,
297                     det->ibuf,
298                     det->isize,
299                     _img,
300                     functionExit);
301             break;
302         case interproc_details::call:
303             p = new image_instPoint(
304                     addr,
305                     det->ibuf,
306                     det->isize,
307                     _img,
308                     det->data.call.target,
309                     det->data.call.dynamic_call,
310                     det->data.call.absolute_address,
311                     callSite);                    
312             break;
313         case interproc_details::branch_interproc:
314             p = new image_instPoint(
315                     addr,
316                     det->ibuf,
317                     det->isize,
318                     _img,
319                     functionExit);
320             break;
321         default:
322             assert(0);
323     };
324
325     if(p)
326         _img->addInstPoint(p);
327
328 #if defined(ppc32_linux) || defined(ppc32_bgp)
329     if(det->type == interproc_details::call) {
330         image_func * ifunc = static_cast<image_func*>(f);
331         _img->updatePltFunc(ifunc,det->data.call.target);
332     }
333 #else
334     f = f; // compiler warning
335 #endif
336 }
337
338 void
339 DynParseCallback::overlapping_blocks(Block*b1,Block*b2)
340 {
341     parsing_printf("[%s:%d] blocks [%lx,%lx) and [%lx,%lx) overlap"
342                    "inconsistently\n",
343         FILE__,__LINE__,b1->start(),b1->end(),b2->start(),b2->end());
344     static_cast<image_basicBlock*>(b1)->markAsNeedingRelocation();
345     static_cast<image_basicBlock*>(b2)->markAsNeedingRelocation();
346 }