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