First pass at thread_db integration for FreeBSD.
[dyninst.git] / proccontrol / src / sysv.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 #include "dynutil/h/SymReader.h"
32 #include "dynutil/h/dyntypes.h"
33 #include "common/h/SymLite-elf.h"
34 #include "sysv.h"
35 #include "irpc.h"
36 #include "snippets.h"
37
38 #if defined(os_linux)
39 #include "common/h/linuxKludges.h"
40 #elif defined(os_freebsd)
41 #include "common/h/freebsdKludges.h"
42 #endif
43
44 #include <vector>
45 #include <string>
46 #include <set>
47
48 using namespace Dyninst;
49 using namespace std;
50
51 SymbolReaderFactory *sysv_process::symreader_factory = NULL;
52 int_breakpoint *sysv_process::lib_trap = NULL;
53
54 sysv_process::sysv_process(Dyninst::PID p, string e, vector<string> a) :
55    int_process(p, e, a),
56    translator(NULL),
57    lib_initialized(false),
58    procreader(NULL)
59 {
60 }
61
62 sysv_process::sysv_process(Dyninst::PID pid_, int_process *p) :
63    int_process(pid_, p)
64 {
65    sysv_process *sp = static_cast<sysv_process *>(p);
66    breakpoint_addr = sp->breakpoint_addr;
67    lib_initialized = sp->lib_initialized;
68    if (sp->procreader)
69       procreader = new PCProcReader(this);
70    if (sp->translator)
71       translator = AddressTranslate::createAddressTranslator(pid_,
72                                                              procreader,
73                                                              symreader_factory);
74 }
75
76 sysv_process::~sysv_process()
77 {
78    if (translator) {
79       delete translator;
80       translator = NULL;
81    }
82    if (procreader) {
83       delete procreader;
84       procreader = NULL;
85    }
86 }
87
88 PCProcReader::PCProcReader(int_process *proc_) :
89    proc(proc_)
90 {
91 }
92
93 PCProcReader::~PCProcReader()
94 {
95 }
96
97 bool PCProcReader::start()
98 {
99    word_cache_valid = false;
100    return true;
101 }
102
103 bool PCProcReader::done()
104 {
105    word_cache_valid = true;
106    return true;
107 }
108
109 bool PCProcReader::ReadMem(Address addr, void *buffer, unsigned size)
110 {
111    if (size != 1) {
112       bool result = proc->readMem(buffer, addr, size);
113       if (!result) {
114          pthrd_printf("Failed to read memory for proc reader\n");
115       }
116       return result;
117    }
118
119    //Try to optimially handle a case where the calling code
120    // reads a string one char at a time.
121    assert(size == 1);
122    Address aligned_addr = addr - (addr % sizeof(word_cache));
123    if (!word_cache_valid || aligned_addr != word_cache_addr) {
124       bool result = proc->readMem(&word_cache, aligned_addr, sizeof(word_cache));
125       if (!result) {
126          pthrd_printf("Failed to read memory for proc reader\n");
127          return false;
128       }
129       word_cache_addr = aligned_addr;
130       word_cache_valid = true;
131    }
132    *((char *) buffer) = ((char *) &word_cache)[addr - aligned_addr];
133    return true;
134 }
135
136 bool PCProcReader::GetReg(MachRegister /*reg*/, MachRegisterVal & /*val*/)
137 {
138    assert(0); //Not needed
139    return true;
140 }
141
142 bool sysv_process::initLibraryMechanism()
143 {
144    if (lib_initialized) {
145       return true;
146    }
147    lib_initialized = true;
148
149    pthrd_printf("Initializing library mechanism for process %d\n", getPid());
150    assert(!procreader);
151    procreader = new PCProcReader(this);
152    if (!symreader_factory) {
153       symreader_factory = (SymbolReaderFactory *) new SymElfFactory();
154       assert(symreader_factory);
155    }
156
157    assert(!translator);
158    translator = AddressTranslate::createAddressTranslator(getPid(), 
159                                                           procreader,
160                                                           symreader_factory);
161    if (!translator) {
162       perr_printf("Error creating address translator object\n");
163       return false;
164    }
165
166    if (!lib_trap) {
167       lib_trap = new int_breakpoint(Breakpoint::ptr());
168    }
169
170    breakpoint_addr = translator->getLibraryTrapAddrSysV();
171    pthrd_printf("Installing library breakpoint at %lx\n", breakpoint_addr);
172    bool result = false;
173    if (breakpoint_addr) {
174       result = addBreakpoint(breakpoint_addr, lib_trap);
175    }
176
177    return true;
178 }
179
180 bool sysv_process::refresh_libraries(set<int_library *> &added_libs,
181                                      set<int_library *> &rmd_libs)
182 {
183    pthrd_printf("Refreshing list of loaded libraries\n");
184    bool result = initLibraryMechanism();
185    if (!result) {
186       pthrd_printf("refresh_libraries failed to init the libraries\n");
187       return false;
188    }
189
190    result = translator->refresh();
191    if (!result) {
192       pthrd_printf("Failed to refresh library list for %d\n", getPid());
193    }
194
195
196    for (set<int_library *>::iterator i = mem->libs.begin(); 
197         i != mem->libs.end(); i++) 
198    {
199       (*i)->setMark(false);
200    }
201
202    vector<LoadedLib *> ll_libs;
203    translator->getLibs(ll_libs);
204    for (vector<LoadedLib *>::iterator i = ll_libs.begin(); i != ll_libs.end(); i++)
205    {
206       LoadedLib *ll = *i;
207       int_library *lib = (int_library *) ll->getUpPtr();
208       pthrd_printf("Found library %s at %lx\n", ll->getName().c_str(), 
209                    ll->getCodeLoadAddr());
210       if (!lib) {
211          pthrd_printf("Creating new library object for %s\n", ll->getName().c_str());
212          lib = new int_library(ll->getName(), ll->getCodeLoadAddr());
213          assert(lib);
214          added_libs.insert(lib);
215          ll->setUpPtr((void *) lib);
216          mem->libs.insert(lib);
217       }
218       lib->setMark(true);
219    }
220
221    set<int_library *>::iterator i = mem->libs.begin();
222    while (i != mem->libs.end()) {
223       int_library *lib = *i;
224       if (lib->isMarked()) {
225          i++;
226          continue;
227       }
228       pthrd_printf("Didn't find old library %s at %lx, unloading\n",
229                    lib->getName().c_str(), lib->getAddr());
230       rmd_libs.insert(lib);
231       mem->libs.erase(i++);
232    }
233
234    return true;
235 }
236
237 Dyninst::Address sysv_process::getLibBreakpointAddr() const
238 {
239    return breakpoint_addr;
240 }
241
242 bool sysv_process::plat_execed()
243 {
244    pthrd_printf("Rebuilding library trap mechanism after exec on %d\n", getPid());
245    if (translator) {
246       delete translator;
247       translator = NULL;
248    }
249    if (procreader) {
250       delete procreader;
251       procreader = NULL;
252    }
253    breakpoint_addr = 0x0;
254    lib_initialized = false;
255    return initLibraryMechanism();
256 }
257
258 /*
259  * Note:
260  *
261  * The following functions are common to both Linux and FreeBSD.
262  *
263  * If there is another SysV platform that needs different versions of these
264  * functions, the following functions should be factored somehow.
265  */
266 void sysv_process::plat_execv() {
267     // Never returns
268     typedef const char * const_str;
269
270     const_str *new_argv = (const_str *) calloc(argv.size()+3, sizeof(char *));
271     new_argv[0] = executable.c_str();
272     unsigned i;
273     for (i=1; i<argv.size()+1; i++) {
274         new_argv[i] = argv[i-1].c_str();
275     }
276     new_argv[i+1] = (char *) NULL;
277
278     execv(executable.c_str(), const_cast<char * const*>(new_argv));
279     int errnum = errno;         
280     pthrd_printf("Failed to exec %s: %s\n", 
281                executable.c_str(), strerror(errnum));
282     if (errnum == ENOENT)
283         setLastError(err_nofile, "No such file");
284     if (errnum == EPERM || errnum == EACCES)
285         setLastError(err_prem, "Permission denied");
286     else
287         setLastError(err_internal, "Unable to exec process");
288     exit(-1);
289 }
290
291 void int_notify::writeToPipe()
292 {
293    if (pipe_out == -1) 
294       return;
295
296    char c = 'e';
297    ssize_t result = write(pipe_out, &c, 1);
298    if (result == -1) {
299       int error = errno;
300       setLastError(err_internal, "Could not write to notification pipe\n");
301       perr_printf("Error writing to notification pipe: %s\n", strerror(error));
302       return;
303    }
304    pthrd_printf("Wrote to notification pipe %d\n", pipe_out);
305 }
306
307 void int_notify::readFromPipe()
308 {
309    if (pipe_out == -1)
310       return;
311
312    char c;
313    ssize_t result;
314    int error;
315    do {
316       result = read(pipe_in, &c, 1);
317       error = errno;
318    } while (result == -1 && error == EINTR);
319    if (result == -1) {
320       int error = errno;
321       if (error == EAGAIN) {
322          pthrd_printf("Notification pipe had no data available\n");
323          return;
324       }
325       setLastError(err_internal, "Could not read from notification pipe\n");
326       perr_printf("Error reading from notification pipe: %s\n", strerror(error));
327    }
328    assert(result == 1 && c == 'e');
329    pthrd_printf("Cleared notification pipe %d\n", pipe_in);
330 }
331
332 bool int_notify::createPipe()
333 {
334    if (pipe_in != -1 || pipe_out != -1)
335       return true;
336
337    int fds[2];
338    int result = pipe(fds);
339    if (result == -1) {
340       int error = errno;
341       setLastError(err_internal, "Error creating notification pipe\n");
342       perr_printf("Error creating notification pipe: %s\n", strerror(error));
343       return false;
344    }
345    assert(fds[0] != -1);
346    assert(fds[1] != -1);
347
348    result = fcntl(fds[0], F_SETFL, O_NONBLOCK);
349    if (result == -1) {
350       int error = errno;
351       setLastError(err_internal, "Error setting properties of notification pipe\n");
352       perr_printf("Error calling fcntl for O_NONBLOCK on %d: %s\n", fds[0], strerror(error));
353       return false;
354    }
355    pipe_in = fds[0];
356    pipe_out = fds[1];
357
358
359    pthrd_printf("Created notification pipe: in = %d, out = %d\n", pipe_in, pipe_out);
360    return true;
361 }
362
363 unsigned sysv_process::getTargetPageSize() {
364     static unsigned pgSize = 0;
365     if( !pgSize ) pgSize = getpagesize();
366     return pgSize;
367 }
368
369 bool installed_breakpoint::plat_install(int_process *proc, bool should_save) {
370    pthrd_printf("Platform breakpoint install at %lx in %d\n", 
371                 addr, proc->getPid());
372    if (should_save) {
373      switch (proc->getTargetArch())
374      {
375        case Arch_x86_64:
376        case Arch_x86:
377          buffer_size = 1;
378          break;
379        default:
380          assert(0);
381      }
382      assert((unsigned) buffer_size < sizeof(buffer));
383      
384      bool result = proc->readMem(&buffer, addr, buffer_size);
385      if (!result) {
386        pthrd_printf("Error reading from process\n");
387        return result;
388      }
389    }
390    
391    bool result;
392    switch (proc->getTargetArch())
393    {
394       case Arch_x86_64:
395       case Arch_x86: {
396          unsigned char trap_insn = 0xcc;
397          result = proc->writeMem(&trap_insn, addr, 1);
398          break;
399       }
400       default:
401          assert(0);
402    }
403    if (!result) {
404       pthrd_printf("Error writing breakpoint to process\n");
405       return result;
406    }
407
408    return true;
409 }
410
411 bool iRPCMgr::collectAllocationResult(int_thread *thr, Dyninst::Address &addr, bool &err)
412 {
413    switch (thr->llproc()->getTargetArch())
414    {
415       case Arch_x86_64: {
416          Dyninst::MachRegisterVal val = 0;
417          bool result = thr->getRegister(x86_64::rax, val);
418          assert(result);
419          addr = val;
420          break;
421       }
422       case Arch_x86: {
423          Dyninst::MachRegisterVal val = 0;
424          bool result = thr->getRegister(x86::eax, val);
425          assert(result);
426          addr = val;
427          break;
428       }
429       default:
430          assert(0);
431          break;
432    }
433    //TODO: check addr vs. possible mmap return values.
434    err = false;
435    return true;
436 }
437
438 // For compatibility 
439 #ifndef MAP_ANONYMOUS
440 #define MAP_ANONYMOUS MAP_ANON
441 #endif
442
443 bool iRPCMgr::createAllocationSnippet(int_process *proc, Dyninst::Address addr, 
444                                       bool use_addr, unsigned long size, 
445                                       void* &buffer, unsigned long &buffer_size, 
446                                       unsigned long &start_offset)
447 {
448    const void *buf_tmp = NULL;
449    unsigned addr_size = 0;
450    unsigned addr_pos = 0;
451    unsigned flags_pos = 0;
452    unsigned size_pos = 0;
453
454    int flags = MAP_ANONYMOUS | MAP_PRIVATE;
455    if (use_addr) 
456       flags |= MAP_FIXED;
457    else
458       addr = 0x0;
459
460    switch (proc->getTargetArch())
461    {
462       case Arch_x86_64:
463          buf_tmp = x86_64_call_mmap;
464          buffer_size = x86_64_call_mmap_size;
465          start_offset = x86_64_mmap_start_position;
466          addr_pos = x86_64_mmap_addr_position;
467          flags_pos = x86_64_mmap_flags_position;
468          size_pos = x86_64_mmap_size_position;
469          addr_size = 8;
470          break;
471       case Arch_x86:
472          buf_tmp = x86_call_mmap;
473          buffer_size = x86_call_mmap_size;
474          start_offset = x86_mmap_start_position;
475          addr_pos = x86_mmap_addr_position;
476          flags_pos = x86_mmap_flags_position;
477          size_pos = x86_mmap_size_position;
478          addr_size = 4;
479          break;
480       default:
481          assert(0);
482    }
483    
484    buffer = malloc(buffer_size);
485    memcpy(buffer, buf_tmp, buffer_size);
486
487    //Assuming endianess of debugger and debugee match.
488    *((unsigned int *) (((char *) buffer)+size_pos)) = size;
489    *((unsigned int *) (((char *) buffer)+flags_pos)) = flags;
490    if (addr_size == 8)
491       *((unsigned long *) (((char *) buffer)+addr_pos)) = addr;
492    else if (addr_size == 4)
493       *((unsigned *) (((char *) buffer)+addr_pos)) = (unsigned) addr;
494    else 
495       assert(0);
496    return true;
497 }
498
499 bool iRPCMgr::createDeallocationSnippet(int_process *proc, Dyninst::Address addr, 
500                                         unsigned long size, void* &buffer, 
501                                         unsigned long &buffer_size, 
502                                         unsigned long &start_offset)
503 {
504    const void *buf_tmp = NULL;
505    unsigned addr_size = 0;
506    unsigned addr_pos = 0;
507    unsigned size_pos = 0;
508
509    switch (proc->getTargetArch())
510    {
511       case Arch_x86_64:
512          buf_tmp = x86_64_call_munmap;
513          buffer_size = x86_64_call_munmap_size;
514          start_offset = x86_64_munmap_start_position;
515          addr_pos = x86_64_munmap_addr_position;
516          size_pos = x86_64_munmap_size_position;
517          addr_size = 8;
518          break;
519       case Arch_x86:
520          buf_tmp = x86_call_munmap;
521          buffer_size = x86_call_munmap_size;
522          start_offset = x86_munmap_start_position;
523          addr_pos = x86_munmap_addr_position;
524          size_pos = x86_munmap_size_position;
525          addr_size = 4;
526          break;
527       default:
528          assert(0);
529    }
530    
531    buffer = malloc(buffer_size);
532    memcpy(buffer, buf_tmp, buffer_size);
533
534    //Assuming endianess of debugger and debugee match.
535    *((unsigned int *) (((char *) buffer)+size_pos)) = size;
536    if (addr_size == 8)
537       *((unsigned long *) (((char *) buffer)+addr_pos)) = addr;
538    else if (addr_size == 4)
539       *((unsigned *) (((char *) buffer)+addr_pos)) = (unsigned) addr;
540    else 
541       assert(0);
542    return true;
543 }
544
545 Dyninst::Address sysv_process::plat_mallocExecMemory(Dyninst::Address min, unsigned size) {
546     Dyninst::Address result = 0x0;
547     bool found_result = false;
548     unsigned maps_size;
549     map_entries *maps = getVMMaps(getPid(), maps_size);
550     assert(maps); //TODO, Perhaps go to libraries for address map if no /proc/
551     for (unsigned i=0; i<maps_size; i++) {
552         if (!(maps[i].prems & PREMS_EXEC))
553             continue;
554         if (min + size > maps[i].end)
555             continue;
556         if (maps[i].end - maps[i].start < size)
557             continue;
558
559         if (maps[i].start > min)
560             result = maps[i].start;
561         else
562             result = min;
563         found_result = true;
564         break;
565     }
566     assert(found_result);
567     free(maps);
568     return result;
569 }