Clean compiler warnings
[dyninst.git] / stackwalk / src / ppc-swk.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
31 #include "stackwalk/h/swk_errors.h"
32 #include "stackwalk/h/procstate.h"
33 #include "stackwalk/h/framestepper.h"
34 #include "stackwalk/h/basetypes.h"
35 #include "stackwalk/h/frame.h"
36 #include "stackwalk/h/walker.h"
37
38 #include "stackwalk/src/sw.h"
39
40 #include "get_trap_instruction.h"
41 using namespace Dyninst;
42 using namespace Dyninst::Stackwalker;
43
44 #if defined(os_linux) || defined(os_bg)
45
46 #define GET_FRAME_BASE(spr) __asm__("or %0, %%r1, %%r1\n" : "=r"(spr))
47 typedef union {
48    struct {
49       uint32_t out_fp;
50       uint32_t out_ra;
51    } pair32;
52    struct {
53       uint64_t out_fp;
54       uint64_t unused_cr;
55       uint64_t out_ra;
56    } pair64;
57 } ra_fp_pair_t;
58
59 #else
60
61 #error Unknown platform
62
63 #endif
64
65 bool ProcSelf::getRegValue(Dyninst::MachRegister reg, THR_ID, Dyninst::MachRegisterVal &val)
66 {
67   ra_fp_pair_t **sp;
68   ra_fp_pair_t *fp_ra;
69
70   GET_FRAME_BASE(sp);
71
72   bool found_reg = false;
73   if (reg.isStackPointer()) {
74     val = (Dyninst::MachRegisterVal) sp;
75     found_reg = true;
76   }
77
78   fp_ra = *sp;
79   if (reg.isFramePointer()) {
80      val = (Dyninst::MachRegisterVal) fp_ra;
81      found_reg = true;
82   }
83
84   if (reg.isPC() || reg == Dyninst::ReturnAddr) {
85      if (getAddressWidth() == sizeof(uint64_t)) {
86        val = fp_ra->pair64.out_ra;
87      }
88      else {
89        val = fp_ra->pair32.out_ra;
90      }
91      found_reg = true;
92   }
93
94   sw_printf("[%s:%u] - Returning value %lx for reg %s\n", 
95             FILE__, __LINE__, val, reg.name().c_str());
96   return true;
97 }
98
99 Dyninst::Architecture ProcSelf::getArchitecture()
100 {
101    return Arch_ppc32;
102 }
103
104 bool Walker::checkValidFrame(const Frame & /*in*/, const Frame & /*out*/)
105 {
106    return true;
107 }
108
109 FrameFuncStepperImpl::FrameFuncStepperImpl(Walker *w, FrameStepper *parent_,
110                                            FrameFuncHelper *helper_) :
111    FrameStepper(w),
112    parent(parent_),
113    helper(helper_)
114 {
115 }
116
117 gcframe_ret_t FrameFuncStepperImpl::getCallerFrame(const Frame &in, Frame &out)
118 {
119   // TODO set RA location
120
121   Address in_fp, out_sp, out_ra;
122   bool result;
123
124   ra_fp_pair_t this_frame_pair;
125   ra_fp_pair_t last_frame_pair;
126   ra_fp_pair_t *actual_frame_pair_p;
127
128   unsigned addrWidth;
129
130   addrWidth = getProcessState()->getAddressWidth();
131
132   // Assume a standard frame layout if no analysis is available
133   FrameFuncHelper::alloc_frame_t alloc_frame =  make_pair(FrameFuncHelper::standard_frame,
134                                                           FrameFuncHelper::set_frame);
135
136   if (helper && in.isTopFrame())
137   {
138     alloc_frame = helper->allocatesFrame(in.getRA());
139     sw_printf("[%s:%u] - FrameFuncHelper for 0x%lx reports %d, %d\n", FILE__, __LINE__,
140               in.getRA(), alloc_frame.first, alloc_frame.second);
141   }
142
143   if (!in.getFP())
144     return gcf_stackbottom;
145
146   in_fp = in.getFP();
147
148   out_sp = in_fp;
149   out.setSP(out_sp);
150   
151   // Read the current frame
152   if (sizeof(uint64_t) == addrWidth) {
153      result = getProcessState()->readMem(&this_frame_pair.pair64, in_fp,
154                                          sizeof(this_frame_pair.pair64));
155   }
156   else {
157      result = getProcessState()->readMem(&this_frame_pair.pair32, in_fp, 
158                                          sizeof(this_frame_pair.pair32));
159   }
160   if (!result) {
161     sw_printf("[%s:%u] - Couldn't read from %lx\n", FILE__, __LINE__, in_fp);
162     return gcf_error;
163   }
164
165   // Read the previous frame
166   if (sizeof(uint64_t) == addrWidth) {
167     result = getProcessState()->readMem(&last_frame_pair.pair64, this_frame_pair.pair64.out_fp, 
168                                         sizeof(last_frame_pair.pair64));
169   }
170   else {
171     result = getProcessState()->readMem(&last_frame_pair.pair32, this_frame_pair.pair32.out_fp, 
172                                         sizeof(last_frame_pair.pair32));
173   }
174   if (!result) {
175     sw_printf("[%s:%u] - Couldn't read from %lx\n", FILE__, __LINE__,
176               out.getFP());
177     return gcf_error;
178   }
179
180   // Set actual stack frame based on
181   // whether the function creates a frame or not
182   if (FrameFuncHelper::no_frame == alloc_frame.first)
183   {
184     actual_frame_pair_p = &this_frame_pair;    
185   }
186   else
187   {
188     actual_frame_pair_p = &last_frame_pair;
189   }
190
191   // Handle leaf functions
192   if (FrameFuncHelper::unset_frame == alloc_frame.second)
193   {
194     // Leaf function - does not save return address
195     // Get the RA from the PC register
196     if (sizeof(uint64_t) == addrWidth)
197     {
198       result = getProcessState()->getRegValue(ppc64::lr, in.getThread(), out_ra);
199     }
200     else
201     {
202       result = getProcessState()->getRegValue(ppc32::lr, in.getThread(), out_ra);
203     }
204     if (!result) {
205         sw_printf("[%s:%u] - Error getting PC value for thrd %d\n",
206                   FILE__, __LINE__, (int) in.getThread());
207         return gcf_error;
208     }
209   }
210   else
211   {
212     // Function saves return address
213     if (sizeof(uint64_t) == addrWidth)
214     {
215       out_ra = actual_frame_pair_p->pair64.out_ra;
216     }
217     else {
218       out_ra = actual_frame_pair_p->pair32.out_ra;
219     }
220   }
221
222   // Set new frame pointer
223   if (FrameFuncHelper::no_frame == alloc_frame.first)
224   {
225     // frame pointer stays the same
226     out.setFP(in_fp);
227   }
228   else
229   {
230     if (sizeof(uint64_t) == addrWidth) {
231       out.setFP(this_frame_pair.pair64.out_fp); 
232     }
233     else {
234       out.setFP(this_frame_pair.pair32.out_fp);
235     }
236   }
237
238   if (!out_ra) {
239     return gcf_stackbottom;
240   }
241
242   out.setRA(out_ra);
243
244   return gcf_success;
245 }
246  
247 unsigned FrameFuncStepperImpl::getPriority() const
248 {
249    return frame_priority;
250 }
251
252 FrameFuncStepperImpl::~FrameFuncStepperImpl()
253 {
254 }
255
256 WandererHelper::WandererHelper(ProcessState *proc_) :
257    proc(proc_)
258 {
259 }
260
261 bool WandererHelper::isPrevInstrACall(Address, Address&)
262 {
263    sw_printf("[%s:%u] - Unimplemented on this platform!\n");
264    assert(0);
265    return false;
266 }
267
268 WandererHelper::pc_state WandererHelper::isPCInFunc(Address, Address)
269 {
270    sw_printf("[%s:%u] - Unimplemented on this platform!\n");
271    assert(0);
272    return unknown_s;
273 }
274
275 bool WandererHelper::requireExactMatch()
276 {
277    sw_printf("[%s:%u] - Unimplemented on this platform!\n");
278    assert(0);
279    return true;
280 }
281
282 WandererHelper::~WandererHelper()
283 {
284 }
285
286 gcframe_ret_t DyninstInstrStepperImpl::getCallerFrameArch(const Frame &/*in*/, Frame &/*out*/, 
287                                                           Address /*base*/, Address /*lib_base*/,
288                                                           unsigned /*size*/, unsigned /*stack_height*/)
289 {
290   return gcf_not_me;
291 }
292
293 gcframe_ret_t DyninstDynamicStepperImpl::getCallerFrameArch(const Frame &in, Frame &out, 
294                                                             Address /*base*/, Address /*lib_base*/,
295                                                             unsigned /*size*/, unsigned stack_height,
296                                                             bool /* aligned */,
297                                                             Address /*orig_ra*/, bool /*pEntryExit*/)
298 {
299   bool result;
300   Address in_fp, out_ra;
301   ra_fp_pair_t ra_fp_pair;
302   location_t raLocation;
303   unsigned addrWidth;
304
305   addrWidth = getProcessState()->getAddressWidth();
306
307   if (!in.getFP())
308     return gcf_stackbottom;
309
310   in_fp = in.getFP();
311   out.setSP(in_fp);
312   
313   if (sizeof(uint64_t) == addrWidth) {
314     result = getProcessState()->readMem(&ra_fp_pair.pair64, in_fp, 
315                                         sizeof(ra_fp_pair.pair64));
316   }
317   else {
318     result = getProcessState()->readMem(&ra_fp_pair.pair32, in_fp, 
319                                         sizeof(ra_fp_pair.pair32));
320   }
321   if (!result) {
322     sw_printf("[%s:%u] - Couldn't read frame from %lx\n", FILE__, __LINE__, in_fp);
323     return gcf_error;
324   }
325   if (sizeof(uint64_t) == addrWidth) {
326     out.setFP(ra_fp_pair.pair64.out_fp);
327   }
328   else {
329     out.setFP(ra_fp_pair.pair32.out_fp);
330   }
331   
332   raLocation.location = loc_address;
333   raLocation.val.addr = in_fp + stack_height; // stack_height is the offset to the saved RA
334   out.setRALocation(raLocation);
335   
336   // TODO make 32-bit compatible
337   result = getProcessState()->readMem(&out_ra, raLocation.val.addr, 
338                                       sizeof(out_ra));
339   if (!result) {
340     sw_printf("[%s:%u] - Couldn't read instrumentation RA from %lx\n", FILE__, __LINE__, raLocation.val.addr);
341     return gcf_error;
342   }
343   out.setRA(out_ra);
344
345   return gcf_success;
346 }
347
348 namespace Dyninst {
349   namespace Stackwalker {
350
351     void getTrapInstruction(char *buffer, unsigned buf_size, 
352                             unsigned &actual_len, bool include_return)
353     {
354       assert(buf_size >= 4);
355       buffer[0] = 0x7d;
356       buffer[1] = 0x82;
357       buffer[2] = 0x10;
358       buffer[3] = 0x08;
359       actual_len = 4;
360       if (include_return)
361       {   
362         assert(buf_size >= 8);
363         buffer[4] = 0x4e;
364         buffer[5] = 0x80;
365         buffer[6] = 0x00;
366         buffer[7] = 0x20;
367         actual_len = 8;
368         return;
369       }
370   
371       assert(buf_size >= 1);
372       actual_len = 1;
373       return;
374     }
375   }
376 }
377