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