Have StackwalkerAPI use ProcControlAPI for debug interface, works on x86 family
[dyninst.git] / stackwalk / src / linux-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/symlookup.h"
34 #include "stackwalk/h/walker.h"
35 #include "stackwalk/h/steppergroup.h"
36 #include "stackwalk/h/procstate.h"
37 #include "stackwalk/h/frame.h"
38
39 #include "stackwalk/src/linux-swk.h"
40 #include "stackwalk/src/sw.h"
41 #include "stackwalk/src/symtab-swk.h"
42 #include "stackwalk/src/libstate.h"
43
44 #include "common/h/linuxKludges.h"
45 #include "common/h/parseauxv.h"
46 #include "common/h/Types.h"
47
48 #include <string>
49 #include <sstream>
50
51 #include <string.h>
52 #include <sys/syscall.h>
53 #include <unistd.h>
54 #include <errno.h>
55 #include <assert.h>
56 #include <signal.h>
57 #include <sys/types.h>
58 #include <sys/wait.h>
59 #include <sys/mman.h>
60 #include <fcntl.h>
61 #include <poll.h>
62
63 #include "common/h/SymLite-elf.h"
64 #include "common/h/parseauxv.h"
65 #include "dynutil/h/dyn_regs.h"
66
67 using namespace Dyninst;
68 using namespace Dyninst::Stackwalker;
69
70 #ifndef SYS_tkill
71 #define SYS_tkill 238
72 #endif
73
74 //These should be defined on all modern linux's, turn these off
75 // if porting to some linux-like platform that doesn't support 
76 // them.
77 #include <sys/ptrace.h>
78 #include <linux/ptrace.h>
79 typedef enum __ptrace_request pt_req;
80 #define cap_ptrace_traceclone
81 #define cap_ptrace_setoptions
82
83 static int P_gettid()
84 {
85   static int gettid_not_valid = 0;
86   long int result;
87
88   if (gettid_not_valid)
89     return getpid();
90
91   result = syscall(SYS_gettid);
92   if (result == -1 && errno == ENOSYS)
93   {
94     gettid_not_valid = 1;
95     return getpid();
96   }
97   return (int) result;
98 }
99
100 SymbolReaderFactory *Dyninst::Stackwalker::getDefaultSymbolReader()
101 {
102    static SymElfFactory symelffact;
103    return &symelffact;
104 }
105
106 class Elf_X;
107 Elf_X *getElfHandle(std::string s)
108 {
109    SymReader *reader = LibraryWrapper::getLibrary(s);
110    if (!reader) {
111       SymbolReaderFactory *fact = getDefaultSymbolReader();
112       reader = fact->openSymbolReader(s);
113    }
114    SymElf *symelf = dynamic_cast<SymElf *>(reader);
115    if (symelf)
116       return symelf->getElfHandle();
117    return NULL;
118 }
119
120 static void registerLibSpotterSelf(ProcSelf *pself);
121 ProcSelf::ProcSelf() :
122    ProcessState(getpid())
123 {
124 }
125
126 void ProcSelf::initialize()
127 {
128    setDefaultLibraryTracker();
129    assert(library_tracker);
130    registerLibSpotterSelf(this);
131 }
132
133 #if defined(cap_sw_catchfaults)
134
135 #include <setjmp.h>
136
137 static bool registered_handler = false;
138 static bool reading_memory = false;
139 sigjmp_buf readmem_jmp;
140
141 void handle_fault(int /*sig*/)
142 {
143    if (!reading_memory) {
144       //The instruction that caused this fault was not from
145       // ProcSelf::readMem.  Restore the SIGSEGV handler, and 
146       // the faulting instruction should restart after we return.
147       fprintf(stderr, "[%s:%u] - Caught segfault that didn't come " \
148               "from stackwalker memory read!", __FILE__, __LINE__);
149       signal(SIGSEGV, SIG_DFL);
150       return;
151    }
152    siglongjmp(readmem_jmp, 1);
153 }
154
155 bool ProcSelf::readMem(void *dest, Address source, size_t size)
156 {
157    if (!registered_handler) {
158       signal(SIGSEGV, handle_fault);
159       registered_handler = true;
160    }
161    reading_memory = true;
162    if (sigsetjmp(readmem_jmp, 1)) {
163       sw_printf("[%s:%u] - Caught fault while reading from %lx to %lx\n", 
164                 __FILE__, __LINE__, source, source + size);
165       setLastError(err_procread, "Could not read from process");
166       return false;
167    }
168    
169    memcpy(dest, (const void *) source, size);
170    reading_memory = false;
171    return true;
172 }
173 #else
174 bool ProcSelf::readMem(void *dest, Address source, size_t size)
175 {
176   memcpy(dest, (const void *) source, size);
177   return true;
178 }
179 #endif
180
181 bool ProcSelf::getThreadIds(std::vector<THR_ID> &threads)
182 {
183   bool result;
184   THR_ID tid;
185
186   result = getDefaultThread(tid);
187   if (!result) {
188     sw_printf("[%s:%u] - Could not read default thread\n",
189                __FILE__, __LINE__);
190     return false;
191   }
192   threads.clear();
193   threads.push_back(tid);
194   return true;
195 }
196
197 bool ProcSelf::getDefaultThread(THR_ID &default_tid)
198 {
199   THR_ID tid = P_gettid();
200   if (tid == -1) {
201     const char *sys_err_msg = strerror(errno);
202     sw_printf("[%s:%u] - gettid syscall failed with %s\n",
203                __FILE__, __LINE__, sys_err_msg);
204     std::string errmsg("gettid syscall failed with ");
205     errmsg += sys_err_msg;
206     setLastError(err_internal, errmsg.c_str());
207     return false;
208   }
209
210   default_tid = tid;
211   return true;
212 }
213
214 vsys_info *Dyninst::Stackwalker::getVsysInfo(ProcessState *ps)
215 {
216 #if defined(arch_x86_64)
217    if (ps->getAddressWidth() == 8)
218       return NULL;
219 #endif
220
221    static std::map<ProcessState *, vsys_info *> vsysmap;
222    vsys_info *ret = NULL;
223    Address start, end;
224    char *buffer = NULL;
225    SymReader *reader = NULL;
226    SymbolReaderFactory *fact = NULL;
227    bool result;
228
229    std::map<ProcessState *, vsys_info *>::iterator i = vsysmap.find(ps);
230    if (i != vsysmap.end())
231       return i->second;
232    
233    AuxvParser *parser = AuxvParser::createAuxvParser(ps->getProcessId(),
234                                                      ps->getAddressWidth());
235    if (!parser) {
236       sw_printf("[%s:%u] - Unable to parse auxv for %d\n", __FILE__, __LINE__,
237                 ps->getProcessId());
238       goto done;
239    }
240
241    start = parser->getVsyscallBase();
242    end = parser->getVsyscallEnd();
243    sw_printf("[%s:%u] - Found vsyscall over range %lx to %lx\n",
244              __FILE__, __LINE__, start, end);   
245    parser->deleteAuxvParser();
246    
247    if (!start || !end || end == start)
248    {
249       sw_printf("[%s:%u] - Error collecting vsyscall base and end\n",
250                 __FILE__, __LINE__);
251       goto done;
252    }
253
254    ret = new vsys_info();
255    assert(ret);
256    ret->start = start;
257    ret->end = end;
258
259    buffer = (char *) malloc(end - start);
260    assert(buffer);
261    result = ps->readMem(buffer, start, end - start);
262    if (!result) {
263       sw_printf("[%s:%u] - Error reading vsys memory\n", __FILE__, __LINE__);
264       goto done;
265    }
266    ret->vsys_mem = buffer;
267
268    fact = getDefaultSymbolReader();
269    if (!fact) {
270       sw_printf("[%s:%u] - No symbol reading capability\n",
271                 __FILE__, __LINE__);
272       goto done;
273    }   
274    reader = fact->openSymbolReader(buffer, end - start);
275    if (!reader) {
276       sw_printf("[%s:%u] - Error reading symbol info\n");
277       goto done;
278    }
279    ret->syms = reader;
280
281   done:
282    vsysmap[ps] = ret;
283    return ret;
284 }
285
286 SigHandlerStepperImpl::SigHandlerStepperImpl(Walker *w, SigHandlerStepper *parent) :
287    FrameStepper(w),
288    parent_stepper(parent),
289    init_libc(false),
290    init_libthread(false)
291 {
292 }
293
294 unsigned SigHandlerStepperImpl::getPriority() const
295 {
296    return sighandler_priority;
297 }
298
299 SigHandlerStepperImpl::~SigHandlerStepperImpl()
300 {
301 }
302
303 void SigHandlerStepperImpl::newLibraryNotification(LibAddrPair *, lib_change_t change)
304 {
305    if (change == library_unload)
306       return;
307    StepperGroup *group = getWalker()->getStepperGroup();
308    registerStepperGroup(group);
309 }
310
311
312 static LibraryState *local_lib_state = NULL;
313 extern "C" {
314    static void lib_trap_handler(int sig);
315 }
316 static void lib_trap_handler(int /*sig*/)
317 {
318    local_lib_state->notifyOfUpdate();
319 }
320
321 static Address lib_trap_addr_self = 0x0;
322 static bool lib_trap_addr_self_err = false;
323 static void registerLibSpotterSelf(ProcSelf *pself)
324 {
325    if (lib_trap_addr_self)
326       return;
327    if (lib_trap_addr_self_err)
328       return;
329
330    //Get the address to install a trap to
331    LibraryState *libs = pself->getLibraryTracker();
332    if (!libs) {
333       sw_printf("[%s:%u] - Not using lib tracker, don't know how "
334                 "to get library load address\n", __FILE__, __LINE__);
335       lib_trap_addr_self_err = true;
336       return;
337    }   
338    lib_trap_addr_self = libs->getLibTrapAddress();
339    if (!lib_trap_addr_self) {
340       sw_printf("[%s:%u] - Error getting trap address, can't install lib tracker",
341                 __FILE__, __LINE__);
342       lib_trap_addr_self_err = true;
343       return;
344    }
345
346    //Use /proc/PID/maps to make sure that this address is valid and writable
347    unsigned maps_size;
348    map_entries *maps = getLinuxMaps(getpid(), maps_size);
349    if (!maps) {
350       sw_printf("[%s:%u] - Error reading proc/%d/maps.  Can't install lib tracker",
351                 __FILE__, __LINE__, getpid());
352       lib_trap_addr_self_err = true;
353       return;
354    }
355
356    bool found = false;
357    for (unsigned i=0; i<maps_size; i++) {
358       if (maps[i].start <= lib_trap_addr_self && 
359           maps[i].end > lib_trap_addr_self)
360       {
361          found = true;
362          if (maps[i].prems & PREMS_WRITE) {
363             break;
364          }
365          int pgsize = getpagesize();
366          Address first_page = (lib_trap_addr_self / pgsize) * pgsize;
367          unsigned size = pgsize;
368          if (first_page + size < lib_trap_addr_self+MAX_TRAP_LEN)
369             size += pgsize;
370          int result = mprotect((void*) first_page,
371                                size, 
372                                PROT_READ|PROT_WRITE|PROT_EXEC);
373          if (result == -1) {
374             int errnum = errno;
375             sw_printf("[%s:%u] - Error setting premissions for page containing %lx. "
376                       "Can't install lib tracker: %s\n", __FILE__, __LINE__, 
377                       lib_trap_addr_self, strerror(errnum));
378             free(maps);
379             lib_trap_addr_self_err = true;
380             return;
381          }
382       }
383    }
384    free(maps);
385    if (!found) {
386       sw_printf("[%s:%u] - Couldn't find page containing %lx.  Can't install lib "
387                 "tracker.", __FILE__, __LINE__, lib_trap_addr_self);
388       lib_trap_addr_self_err = true;
389       return;
390    }
391
392    char trap_buffer[MAX_TRAP_LEN];
393    unsigned actual_len;
394    getTrapInstruction(trap_buffer, MAX_TRAP_LEN, actual_len, true);
395
396    local_lib_state = libs;
397    signal(SIGTRAP, lib_trap_handler);
398
399    memcpy((void*) lib_trap_addr_self, trap_buffer, actual_len);   
400    sw_printf("[%s:%u] - Successfully install lib tracker at 0x%lx\n",
401             __FILE__, __LINE__, lib_trap_addr_self);
402 }
403
404 bool LibraryState::updateLibsArch(std::vector<std::pair<LibAddrPair, unsigned int> > &alibs)
405 {
406    if (arch_libs.size()) {
407       alibs = arch_libs;
408       return true;
409    }
410    vsys_info *vsys = getVsysInfo(procstate);
411    if (!vsys) {
412       return false;
413    }
414    std::stringstream ss;
415    ss << "[vsyscall-" << procstate->getProcessId() << "]";
416    LibAddrPair vsyscall_page;
417    vsyscall_page.first = ss.str();
418    vsyscall_page.second = vsys->start;
419    
420    SymbolReaderFactory *fact = getDefaultSymbolReader();
421    SymReader *reader = fact->openSymbolReader((char *) vsys->vsys_mem,
422                                               vsys->end - vsys->start);
423    if (reader)
424       LibraryWrapper::registerLibrary(reader, vsyscall_page.first);
425
426    std::pair<LibAddrPair, unsigned int> vsyscall_lib_pair;
427    vsyscall_lib_pair.first = vsyscall_page;
428    vsyscall_lib_pair.second = static_cast<unsigned int>(vsys->end - vsys->start);
429    arch_libs.push_back(vsyscall_lib_pair);
430    alibs = arch_libs;
431
432    return true;
433 }
434
435 #define NUM_VSYS_SIGRETURNS 3
436 static const char* vsys_sigreturns[] = {
437    "_sigreturn",
438    "__kernel_sigreturn",
439    "__kernel_rt_sigreturn"
440 };
441
442 void SigHandlerStepperImpl::registerStepperGroup(StepperGroup *group)
443 {
444    ProcessState *ps = getProcessState();
445    assert(ps);
446
447    LibraryState *libs = getProcessState()->getLibraryTracker();
448    if (!libs) {
449       sw_printf("[%s:%u] - Custom library tracker.  Don't know how to"
450                 " to get libc\n", __FILE__, __LINE__);
451       return;
452    }
453    SymbolReaderFactory *fact = getDefaultSymbolReader();
454    if (!fact) {
455       sw_printf("[%s:%u] - Failed to get symbol reader\n", __FILE__, __LINE__);
456       return;
457    }
458
459    if (!init_libc) {
460       /**
461        * Get __restore_rt out of libc
462        **/
463       LibAddrPair libc_addr;
464       Dyninst::SymReader *libc = NULL;
465       Symbol_t libc_restore;
466       bool result = libs->getLibc(libc_addr);
467       if (!result) {
468          sw_printf("[%s:%u] - Unable to find libc, not registering restore_rt"
469                    "tracker.\n", __FILE__, __LINE__);
470       }
471       if (result) {
472          init_libc = true;
473          libc = fact->openSymbolReader(libc_addr.first);
474          if (!libc) {
475             sw_printf("[%s:%u] - Unable to open libc, not registering restore_rt\n",
476                       __FILE__, __LINE__);
477          }   
478       }
479       if (libc) {
480          libc_restore = libc->getSymbolByName("__restore_rt");
481          if (!libc->isValidSymbol(libc_restore)) {
482             sw_printf("[%s:%u] - Unable to find restore_rt in libc\n",
483                       __FILE__, __LINE__);
484          }
485          else {
486             Dyninst::Address start = libc->getSymbolOffset(libc_restore);
487             Dyninst::Address end = libc->getSymbolSize(libc_restore) + start;
488             if (start == end)
489                end = start + 16; //Estimate--annoying
490             sw_printf("[%s:%u] - Registering libc restore_rt as at %lx to %lx\n",
491                       __FILE__, __LINE__, start, end);
492             group->addStepper(parent_stepper, start, end);
493          }
494       }
495    }
496
497    if (!init_libthread) {
498       /**
499        * Get __restore_rt out of libpthread
500        **/
501       LibAddrPair libpthread_addr;
502       Dyninst::SymReader *libpthread = NULL;
503       Symbol_t libpthread_restore;
504       bool result  = libs->getLibthread(libpthread_addr);
505       if (!result) {
506          sw_printf("[%s:%u] - Unable to find libpthread, not registering restore_rt"
507                    "pthread tracker.\n", __FILE__, __LINE__);
508       }
509       if (result) {
510          libpthread = fact->openSymbolReader(libpthread_addr.first);
511          if (!libpthread) {
512             sw_printf("[%s:%u] - Unable to open libc, not registering restore_rt\n",
513                       __FILE__, __LINE__);
514          }
515          init_libthread = true;
516       }
517       if (libpthread) {
518          libpthread_restore = libpthread->getSymbolByName("__restore_rt");
519          if (!result) {
520             sw_printf("[%s:%u] - Unable to find restore_rt in libc\n",
521                       __FILE__, __LINE__);
522          }
523          else {
524             Dyninst::Address start = libpthread->getSymbolOffset(libpthread_restore);
525             Dyninst::Address end = libpthread->getSymbolSize(libpthread_restore) + start;
526             if (start == end)
527                end = start + 16; //Estimate--annoying
528             sw_printf("[%s:%u] - Registering libpthread restore_rt as at %lx to %lx\n",
529                       __FILE__, __LINE__, start, end);
530             group->addStepper(parent_stepper, start, end);
531          }
532       }   
533    }
534
535    /**
536     * Get symbols out of vsyscall page
537     **/
538    vsys_info *vsyscall = getVsysInfo(ps);
539    if (!vsyscall)
540    {
541 #if !defined(arch_x86_64)
542       sw_printf("[%s:%u] - Odd.  Couldn't find vsyscall page. Signal handler"
543                 " stepping may not work\n", __FILE__, __LINE__);
544 #endif
545    }
546    else
547    {
548       SymReader *vsys_syms = vsyscall->syms;
549       if (!vsys_syms) {
550          sw_printf("[%s:%u] - Vsyscall page wasn't parsed\n", __FILE__, __LINE__);
551       }
552       else {
553          for (unsigned i=0; i<NUM_VSYS_SIGRETURNS; i++)
554          {
555             Symbol_t sym;
556             sym = vsys_syms->getSymbolByName(vsys_sigreturns[i]);
557             if (!vsys_syms->isValidSymbol(sym))
558                continue;
559             
560             Dyninst::Offset offset = vsys_syms->getSymbolOffset(sym);
561             Dyninst::Address addr;
562             if (offset < vsyscall->start)
563                addr = offset + vsyscall->start;
564             else
565                addr = offset;
566             unsigned long size = vsys_syms->getSymbolSize(sym);
567             if (!size) 
568                size = ps->getAddressWidth();
569             
570             group->addStepper(parent_stepper, addr, addr + size);
571          }
572       }
573    }
574 }
575
576 void BottomOfStackStepperImpl::initialize()
577 {
578    ProcessState *proc = walker->getProcessState();
579    assert(proc);
580
581    sw_printf("[%s:%u] - Initializing BottomOfStackStepper\n", __FILE__, __LINE__);
582    
583    LibraryState *libs = proc->getLibraryTracker();
584    if (!libs) {
585       sw_printf("[%s:%u] - Error initing StackBottom.  No library state for process.\n",
586                 __FILE__, __LINE__);
587       return;
588    }
589    SymbolReaderFactory *fact = getDefaultSymbolReader();
590    if (!fact) {
591       sw_printf("[%s:%u] - Failed to get symbol reader\n");
592       return;
593    }
594
595    if (!aout_init)
596    {
597       LibAddrPair aout_addr;
598       SymReader *aout = NULL;
599       Symbol_t start_sym;
600       bool result = libs->getAOut(aout_addr);
601       if (result) {
602          aout = fact->openSymbolReader(aout_addr.first);
603          aout_init = true;
604       }
605       if (aout) {
606          start_sym = aout->getSymbolByName("_start");
607          if (aout->isValidSymbol(start_sym)) {
608             Dyninst::Address start = aout->getSymbolOffset(start_sym)+aout_addr.second;
609             Dyninst::Address end = aout->getSymbolSize(start_sym) + start;
610             if (start == end)
611                end = start + 43;
612             sw_printf("[%s:%u] - Bottom stepper taking %lx to %lx for start\n", 
613                       __FILE__, __LINE__, start, end);
614             ra_stack_tops.push_back(std::pair<Address, Address>(start, end));
615          }
616       }
617    }
618
619    if (!libthread_init)
620    {
621       LibAddrPair libthread_addr;
622       SymReader *libthread = NULL;
623       Symbol_t clone_sym, startthread_sym;
624       bool result = libs->getLibthread(libthread_addr);
625       if (result) {
626          libthread = fact->openSymbolReader(libthread_addr.first);
627          libthread_init = true;
628       }
629       if (libthread) {
630          clone_sym = libthread->getSymbolByName("__clone");
631          if (libthread->isValidSymbol(clone_sym)) {
632             Dyninst::Address start = libthread->getSymbolOffset(clone_sym) + 
633                libthread_addr.second;
634             Dyninst::Address end = libthread->getSymbolSize(clone_sym) + start;
635             sw_printf("[%s:%u] - Bottom stepper taking %lx to %lx for clone\n", 
636                       __FILE__, __LINE__, start, end);
637             ra_stack_tops.push_back(std::pair<Address, Address>(start, end));
638          }
639          startthread_sym = libthread->getSymbolByName("start_thread");
640          if (libthread->isValidSymbol(startthread_sym)) {
641             Dyninst::Address start = libthread->getSymbolOffset(startthread_sym) + 
642                libthread_addr.second;
643             Dyninst::Address end = libthread->getSymbolSize(startthread_sym) + start;
644             sw_printf("[%s:%u] - Bottom stepper taking %lx to %lx for start_thread\n", 
645                       __FILE__, __LINE__, start, end);
646             ra_stack_tops.push_back(std::pair<Address, Address>(start, end));
647          }
648       }
649    }
650 }
651
652 void BottomOfStackStepperImpl::newLibraryNotification(LibAddrPair *, lib_change_t change)
653 {
654    if (change == library_unload)
655       return;
656    if (!libthread_init || !aout_init) {
657       initialize();
658    }
659 }
660