Clean warnings in StackwalkerAPI
[dyninst.git] / stackwalk / src / linux-x86-swk.C
1 /*
2  * Copyright (c) 1996-2011 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
32 #include "stackwalk/h/swk_errors.h"
33 #include "stackwalk/h/walker.h"
34 #include "stackwalk/h/procstate.h"
35 #include "stackwalk/h/framestepper.h"
36 #include "stackwalk/h/basetypes.h"
37 #include "stackwalk/h/frame.h"
38
39 #include "stackwalk/src/symtab-swk.h"
40 #include "stackwalk/src/linux-swk.h"
41 #include "stackwalk/src/dbgstepper-impl.h"
42 #include "stackwalk/src/x86-swk.h"
43
44 #include "common/h/Types.h"
45
46 #include <sys/user.h>
47 #include <sys/ptrace.h>
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include <fcntl.h>
51 #include <string.h>
52 #include <errno.h>
53
54 using namespace Dyninst;
55 using namespace Dyninst::Stackwalker;
56
57 #if defined(arch_x86_64)
58
59 static int computeAddrWidth(int pid)
60 {
61    /**
62     * It's surprisingly difficult to figure out the word size of a process
63     * without looking at the files it loads (we want to avoid disk accesses).
64     *
65     * /proc/PID/auxv offers a hackish opportunity to do this.  auxv contains
66     * a list of name value pairs.  On 64 bit processes these name values are
67     * a uint64/uint64 combo and on 32 bit processes they're uint32/uint32.
68     *
69     * The names are from a set of small integers (ranging from 0 to 37 at
70     * the time of this writing).  Since these are small numbers, the top half
71     * of name word will be 0x0 on 64 bit processes.  On 32-bit process this
72     * word will contain a value, of which some should be non-zero.  
73     *
74     * We'll thus check ever word that is 1 mod 4.  If all are 0x0 we assume we're
75     * looking at a 64-bit process.
76     **/
77    uint32_t buffer[256];
78    char auxv_name[64];
79    
80    snprintf(auxv_name, 64, "/proc/%d/auxv", pid);
81    int fd = open(auxv_name, O_RDONLY);
82    if (fd == -1) { 
83       sw_printf("[%s:%u] - Couldn't open %s to determine address width: %s",
84                 __FILE__, __LINE__, auxv_name, strerror(errno));      
85       return -1;
86    }
87
88    long int result = read(fd, buffer, sizeof(buffer));
89    long int words_read = result / sizeof(uint32_t);
90    int word_size = 8;
91    for (unsigned i=1; i<words_read; i+= 4)
92    {
93       if (buffer[i] != 0) {
94          word_size = 4;
95          break;
96       }
97    }
98    close(fd);
99    return word_size;
100 }
101
102 unsigned ProcDebugLinux::getAddressWidth()
103 {
104    if (cached_addr_width)
105       return cached_addr_width;
106
107    sw_printf("[%s:%u] - Computing address size of proc %d\n",
108              __FILE__, __LINE__, pid);
109    
110    int addr_width = computeAddrWidth(pid);
111    if (addr_width == -1)
112    {
113       sw_printf("[%s:%u] - **ERROR** Failed to calculate address width, guessing 8\n",
114                 __FILE__, __LINE__);
115       cached_addr_width = 8;
116    }
117    else
118       cached_addr_width = addr_width;
119    
120    return cached_addr_width;
121 }
122
123 #else
124
125 unsigned ProcDebugLinux::getAddressWidth() 
126 {
127    return sizeof(void*);
128 }
129
130 #endif
131
132 Dyninst::Architecture ProcDebugLinux::getArchitecture()
133 {
134    unsigned addr_width = getAddressWidth();
135    if (addr_width == 4)
136       return Dyninst::Arch_x86;
137    else if (addr_width == 8) 
138       return Dyninst::Arch_x86_64;
139    else
140       assert(0);
141 }
142
143 #if defined(arch_x86_64)
144
145 struct user32_regs_struct
146 {
147   int ebx;
148   int ecx;
149   int edx;
150   int esi;
151   int edi;
152   int ebp;
153   int eax;
154   int xds;
155   int xes;
156   int xfs;
157   int xgs;
158   int orig_eax;
159   int eip;
160   int xcs;
161   int eflags;
162   int esp;
163   int xss;
164 };
165
166 struct user32 {
167    struct user32_regs_struct regs;
168    //Rest don't matter to StackwalkerAPI
169 };
170
171 #define USER64_OFFSET_OF(register) ((signed)(long) &(((struct user *) NULL)->regs.register))
172 #define USER32_OFFSET_OF(register) ((signed)(long) &(((struct user32 *) NULL)->regs.register))
173
174 #else
175
176 #define USER32_OFFSET_OF(register) ((signed int) &(((struct user *) NULL)->regs.register))
177
178 #endif
179
180 bool ProcDebugLinux::getRegValue(Dyninst::MachRegister reg, Dyninst::THR_ID t, 
181                                  Dyninst::MachRegisterVal &val)
182 {
183    long result;
184    signed offset = -1;
185    
186    if (getAddressWidth() == 4)
187    {
188       switch (reg.val()) {
189          case Dyninst::x86::ieip:
190          case Dyninst::iReturnAddr:
191             offset = USER32_OFFSET_OF(eip);
192             break;
193          case Dyninst::iStackTop:
194          case Dyninst::x86::iesp:
195             offset = USER32_OFFSET_OF(esp);
196             break;
197          case Dyninst::iFrameBase:
198          case Dyninst::x86::iebp:
199             offset = USER32_OFFSET_OF(ebp);
200             break;
201          case Dyninst::x86::ieax:
202             offset = USER32_OFFSET_OF(eax);
203             break;
204          case Dyninst::x86::iebx:
205             offset = USER32_OFFSET_OF(ebx);
206             break;
207          case Dyninst::x86::iecx:
208             offset = USER32_OFFSET_OF(ecx);
209             break;
210          case Dyninst::x86::iedx:
211             offset = USER32_OFFSET_OF(edx);
212             break;
213          case Dyninst::x86::iesi:
214             offset = USER32_OFFSET_OF(esi);
215             break;
216          case Dyninst::x86::iedi:
217             offset = USER32_OFFSET_OF(edi);
218             break;            
219       }
220    }
221 #if defined(arch_x86_64)
222    else 
223    {
224       switch (reg) {
225          case Dyninst::iReturnAddr:
226          case Dyninst::x86_64::irip:
227             offset = USER64_OFFSET_OF(rip);
228             break;
229          case Dyninst::iStackTop:
230          case Dyninst::x86_64::irsp:
231             offset = USER64_OFFSET_OF(rsp);
232             break;
233          case Dyninst::iFrameBase:
234          case Dyninst::x86_64::irbp:
235             offset = USER64_OFFSET_OF(rbp);
236             break;
237          case Dyninst::x86_64::irax:
238             offset = USER64_OFFSET_OF(rax);
239             break;
240          case Dyninst::x86_64::irbx:
241             offset = USER64_OFFSET_OF(rbx);
242             break;
243          case Dyninst::x86_64::ircx:
244             offset = USER64_OFFSET_OF(rcx);
245             break;
246          case Dyninst::x86_64::irdx:
247             offset = USER64_OFFSET_OF(rdx);
248             break;
249          case Dyninst::x86_64::irsi:
250             offset = USER64_OFFSET_OF(rsi);
251             break;
252          case Dyninst::x86_64::irdi:
253             offset = USER64_OFFSET_OF(rdi);
254             break;
255          case Dyninst::x86_64::ir8:
256             offset = USER64_OFFSET_OF(r8);
257             break;
258          case Dyninst::x86_64::ir9:
259             offset = USER64_OFFSET_OF(r9);
260             break;
261          case Dyninst::x86_64::ir10:
262             offset = USER64_OFFSET_OF(r10);
263             break;
264          case Dyninst::x86_64::ir11:
265             offset = USER64_OFFSET_OF(r11);
266             break;
267          case Dyninst::x86_64::ir12:
268             offset = USER64_OFFSET_OF(r12);
269             break;
270          case Dyninst::x86_64::ir13:
271             offset = USER64_OFFSET_OF(r13);
272             break;
273          case Dyninst::x86_64::ir14:
274             offset = USER64_OFFSET_OF(r14);
275             break;
276          case Dyninst::x86_64::ir15:
277             offset = USER64_OFFSET_OF(r15);
278             break;
279          break;
280       }
281    }
282 #endif
283    if (offset == -1) {
284          sw_printf("[%s:%u] - Request for unsupported register %s\n",
285                    __FILE__, __LINE__, reg.name().c_str());
286          setLastError(err_badparam, "Unknown register passed in reg field");
287          return false;
288    }
289    
290    errno = 0;
291    result = ptrace(PTRACE_PEEKUSER, (pid_t) t, (void*) offset, NULL);
292    if (errno)
293    {
294       int errnum = errno;
295       sw_printf("[%s:%u] - Could not read gprs in %d: %s\n", 
296                 __FILE__, __LINE__, t, strerror(errnum));
297       setLastError(err_procread, "Could not read registers from process");
298       return false;
299    }
300
301    val = result;
302    return true;
303 }
304
305 bool ProcDebugLinux::setRegValue(Dyninst::MachRegister, 
306                                  Dyninst::THR_ID, 
307                                  Dyninst::MachRegisterVal)
308 {
309   //Not needed on x86
310   assert(0);
311   return false;
312 }
313
314
315 bool Walker::createDefaultSteppers()
316 {
317   FrameStepper *stepper;
318   WandererHelper *whelper_x86;
319   LookupFuncStart *frameFuncHelper_x86;
320   bool result = true;
321
322   stepper = new DebugStepper(this);
323   result = addStepper(stepper);
324   if (!result)
325      goto error;
326   sw_printf("[%s:%u] - Stepper %p is DebugStepper\n",
327             __FILE__, __LINE__, stepper);
328
329   frameFuncHelper_x86 = LookupFuncStart::getLookupFuncStart(getProcessState());
330   stepper = new FrameFuncStepper(this, frameFuncHelper_x86);
331   result = addStepper(stepper);
332   if (!result)
333      goto error;
334   sw_printf("[%s:%u] - Stepper %p is FrameFuncStepper\n",
335             __FILE__, __LINE__, stepper);
336
337   //Call getLookupFuncStart twice to get reference counts correct.
338   frameFuncHelper_x86 = LookupFuncStart::getLookupFuncStart(getProcessState());
339   whelper_x86 = new WandererHelper(getProcessState());
340   stepper = new StepperWanderer(this, whelper_x86, frameFuncHelper_x86);
341   result = addStepper(stepper);
342   if (!result)
343      goto error;
344   sw_printf("[%s:%u] - Stepper %p is StepperWanderer\n",
345             __FILE__, __LINE__, stepper);
346
347   stepper = new SigHandlerStepper(this);
348   result = addStepper(stepper);
349   if (!result)
350      goto error;
351   sw_printf("[%s:%u] - Stepper %p is SigHandlerStepper\n",
352             __FILE__, __LINE__, stepper);
353
354   stepper = new BottomOfStackStepper(this);
355   result = addStepper(stepper);
356   if (!result)
357      goto error;
358   sw_printf("[%s:%u] - Stepper %p is BottomOfStackStepper\n",
359             __FILE__, __LINE__, stepper);
360
361   return true;
362  error:
363   sw_printf("[%s:%u] - Error adding stepper %p\n", stepper);
364     return false;
365 }
366
367 static const int fp_offset_32 = 28;
368 static const int pc_offset_32 = 60;
369 static const int frame_size_32 = 728;
370 static const int fp_offset_64 = 120;
371 static const int pc_offset_64 = 168;
372 static const int frame_size_64 = 1096;
373
374 gcframe_ret_t SigHandlerStepperImpl::getCallerFrame(const Frame &in, Frame &out)
375 {
376    int fp_offset;
377    int pc_offset;
378    int frame_size;
379    bool result;
380    int addr_size = getProcessState()->getAddressWidth();
381    if (addr_size == 4) {
382       fp_offset = fp_offset_32;
383       pc_offset = pc_offset_32;
384       frame_size = frame_size_32;
385    }
386    else {
387       fp_offset = fp_offset_64;
388       pc_offset = pc_offset_64;
389       frame_size = frame_size_64;
390   }
391
392    location_t fp_loc;
393    Address fp = 0x0;
394    fp_loc.location = loc_address;
395    fp_loc.val.addr = in.getSP() + fp_offset;
396    sw_printf("[%s:%u] - SigHandler Reading FP from %lx\n",
397              __FILE__, __LINE__, fp_loc.val.addr);
398    result = getProcessState()->readMem(&fp, fp_loc.val.addr, addr_size);
399    if (!result) {
400       return gcf_error;
401    }
402
403    location_t pc_loc;
404    Address pc = 0x0;
405    pc_loc.location = loc_address;
406    pc_loc.val.addr = in.getSP() + pc_offset;
407    sw_printf("[%s:%u] - SigHandler Reading PC from %lx\n",
408              __FILE__, __LINE__, pc_loc.val.addr);
409    result = getProcessState()->readMem(&pc, pc_loc.val.addr, addr_size);
410    if (!result) {
411       return gcf_error;
412    }
413
414    Address sp = in.getSP() + frame_size;
415
416    out.setRA((Dyninst::MachRegisterVal) pc);
417    out.setFP((Dyninst::MachRegisterVal) fp);
418    out.setSP((Dyninst::MachRegisterVal) sp);
419    out.setRALocation(pc_loc);
420    out.setFPLocation(fp_loc);
421
422    return gcf_success;
423 }
424
425 bool DebugStepperImpl::isFrameRegister(MachRegister reg)
426 {
427    if (getProcessState()->getAddressWidth() == 4)
428       return (reg == x86::ebp);
429    else 
430       return (reg == x86_64::rbp);
431 }
432
433 bool DebugStepperImpl::isStackRegister(MachRegister reg)
434 {
435    if (getProcessState()->getAddressWidth() == 4)
436       return (reg == x86::esp);
437    else 
438       return (reg == x86_64::rsp);
439 }
440
441 void ProcDebugLinux::detach_arch_cleanup()
442 {
443    LookupFuncStart::clear_func_mapping(getProcessId());
444 }