2 * Copyright (c) 1996-2009 Barton P. Miller
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.
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.
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.
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.
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
31 #include "dynutil/h/SymReader.h"
32 #include "dynutil/h/dyntypes.h"
33 #include "common/h/SymLite-elf.h"
39 #include "common/h/linuxKludges.h"
40 #elif defined(os_freebsd)
41 #include "common/h/freebsdKludges.h"
48 using namespace Dyninst;
51 SymbolReaderFactory *sysv_process::symreader_factory = NULL;
52 int_breakpoint *sysv_process::lib_trap = NULL;
54 sysv_process::sysv_process(Dyninst::PID p, string e, vector<string> a) :
57 lib_initialized(false),
62 sysv_process::sysv_process(Dyninst::PID pid_, int_process *p) :
65 sysv_process *sp = static_cast<sysv_process *>(p);
66 breakpoint_addr = sp->breakpoint_addr;
67 lib_initialized = sp->lib_initialized;
69 procreader = new PCProcReader(this);
71 translator = AddressTranslate::createAddressTranslator(pid_,
76 sysv_process::~sysv_process()
88 PCProcReader::PCProcReader(int_process *proc_) :
93 PCProcReader::~PCProcReader()
97 bool PCProcReader::start()
99 word_cache_valid = false;
103 bool PCProcReader::done()
105 word_cache_valid = true;
109 bool PCProcReader::ReadMem(Address addr, void *buffer, unsigned size)
112 bool result = proc->readMem(buffer, addr, size);
114 pthrd_printf("Failed to read memory for proc reader\n");
119 //Try to optimially handle a case where the calling code
120 // reads a string one char at a time.
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));
126 pthrd_printf("Failed to read memory for proc reader\n");
129 word_cache_addr = aligned_addr;
130 word_cache_valid = true;
132 *((char *) buffer) = ((char *) &word_cache)[addr - aligned_addr];
136 bool PCProcReader::GetReg(MachRegister /*reg*/, MachRegisterVal & /*val*/)
138 assert(0); //Not needed
142 bool sysv_process::initLibraryMechanism()
144 if (lib_initialized) {
147 lib_initialized = true;
149 pthrd_printf("Initializing library mechanism for process %d\n", getPid());
151 procreader = new PCProcReader(this);
152 if (!symreader_factory) {
153 symreader_factory = (SymbolReaderFactory *) new SymElfFactory();
154 assert(symreader_factory);
158 translator = AddressTranslate::createAddressTranslator(getPid(),
162 perr_printf("Error creating address translator object\n");
167 lib_trap = new int_breakpoint(Breakpoint::ptr());
170 breakpoint_addr = translator->getLibraryTrapAddrSysV();
171 pthrd_printf("Installing library breakpoint at %lx\n", breakpoint_addr);
173 if (breakpoint_addr) {
174 result = addBreakpoint(breakpoint_addr, lib_trap);
180 bool sysv_process::refresh_libraries(set<int_library *> &added_libs,
181 set<int_library *> &rmd_libs)
183 pthrd_printf("Refreshing list of loaded libraries\n");
184 bool result = initLibraryMechanism();
186 pthrd_printf("refresh_libraries failed to init the libraries\n");
190 result = translator->refresh();
192 pthrd_printf("Failed to refresh library list for %d\n", getPid());
196 for (set<int_library *>::iterator i = mem->libs.begin();
197 i != mem->libs.end(); i++)
199 (*i)->setMark(false);
202 vector<LoadedLib *> ll_libs;
203 translator->getLibs(ll_libs);
204 for (vector<LoadedLib *>::iterator i = ll_libs.begin(); i != ll_libs.end(); 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());
211 pthrd_printf("Creating new library object for %s\n", ll->getName().c_str());
212 lib = new int_library(ll->getName(), ll->getCodeLoadAddr());
214 added_libs.insert(lib);
215 ll->setUpPtr((void *) lib);
216 mem->libs.insert(lib);
221 set<int_library *>::iterator i = mem->libs.begin();
222 while (i != mem->libs.end()) {
223 int_library *lib = *i;
224 if (lib->isMarked()) {
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++);
237 Dyninst::Address sysv_process::getLibBreakpointAddr() const
239 return breakpoint_addr;
242 bool sysv_process::plat_execed()
244 pthrd_printf("Rebuilding library trap mechanism after exec on %d\n", getPid());
253 breakpoint_addr = 0x0;
254 lib_initialized = false;
255 return initLibraryMechanism();
261 * The following functions are common to both Linux and FreeBSD.
263 * If there is another SysV platform that needs different versions of these
264 * functions, the following functions should be factored somehow.
266 void sysv_process::plat_execv() {
268 typedef const char * const_str;
270 const_str *new_argv = (const_str *) calloc(argv.size()+3, sizeof(char *));
271 new_argv[0] = executable.c_str();
273 for (i=1; i<argv.size()+1; i++) {
274 new_argv[i] = argv[i-1].c_str();
276 new_argv[i+1] = (char *) NULL;
278 execv(executable.c_str(), const_cast<char * const*>(new_argv));
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");
287 setLastError(err_internal, "Unable to exec process");
291 void int_notify::writeToPipe()
297 ssize_t result = write(pipe_out, &c, 1);
300 setLastError(err_internal, "Could not write to notification pipe\n");
301 perr_printf("Error writing to notification pipe: %s\n", strerror(error));
304 pthrd_printf("Wrote to notification pipe %d\n", pipe_out);
307 void int_notify::readFromPipe()
316 result = read(pipe_in, &c, 1);
318 } while (result == -1 && error == EINTR);
321 if (error == EAGAIN) {
322 pthrd_printf("Notification pipe had no data available\n");
325 setLastError(err_internal, "Could not read from notification pipe\n");
326 perr_printf("Error reading from notification pipe: %s\n", strerror(error));
328 assert(result == 1 && c == 'e');
329 pthrd_printf("Cleared notification pipe %d\n", pipe_in);
332 bool int_notify::createPipe()
334 if (pipe_in != -1 || pipe_out != -1)
338 int result = pipe(fds);
341 setLastError(err_internal, "Error creating notification pipe\n");
342 perr_printf("Error creating notification pipe: %s\n", strerror(error));
345 assert(fds[0] != -1);
346 assert(fds[1] != -1);
348 result = fcntl(fds[0], F_SETFL, O_NONBLOCK);
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));
359 pthrd_printf("Created notification pipe: in = %d, out = %d\n", pipe_in, pipe_out);
363 unsigned sysv_process::getTargetPageSize() {
364 static unsigned pgSize = 0;
365 if( !pgSize ) pgSize = getpagesize();
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());
373 switch (proc->getTargetArch())
382 assert((unsigned) buffer_size < sizeof(buffer));
384 bool result = proc->readMem(&buffer, addr, buffer_size);
386 pthrd_printf("Error reading from process\n");
392 switch (proc->getTargetArch())
396 unsigned char trap_insn = 0xcc;
397 result = proc->writeMem(&trap_insn, addr, 1);
404 pthrd_printf("Error writing breakpoint to process\n");
411 bool iRPCMgr::collectAllocationResult(int_thread *thr, Dyninst::Address &addr, bool &err)
413 switch (thr->llproc()->getTargetArch())
416 Dyninst::MachRegisterVal val = 0;
417 bool result = thr->getRegister(x86_64::rax, val);
423 Dyninst::MachRegisterVal val = 0;
424 bool result = thr->getRegister(x86::eax, val);
433 //TODO: check addr vs. possible mmap return values.
439 #ifndef MAP_ANONYMOUS
440 #define MAP_ANONYMOUS MAP_ANON
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)
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;
454 int flags = MAP_ANONYMOUS | MAP_PRIVATE;
460 switch (proc->getTargetArch())
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;
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;
484 buffer = malloc(buffer_size);
485 memcpy(buffer, buf_tmp, buffer_size);
487 //Assuming endianess of debugger and debugee match.
488 *((unsigned int *) (((char *) buffer)+size_pos)) = size;
489 *((unsigned int *) (((char *) buffer)+flags_pos)) = flags;
491 *((unsigned long *) (((char *) buffer)+addr_pos)) = addr;
492 else if (addr_size == 4)
493 *((unsigned *) (((char *) buffer)+addr_pos)) = (unsigned) addr;
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)
504 const void *buf_tmp = NULL;
505 unsigned addr_size = 0;
506 unsigned addr_pos = 0;
507 unsigned size_pos = 0;
509 switch (proc->getTargetArch())
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;
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;
531 buffer = malloc(buffer_size);
532 memcpy(buffer, buf_tmp, buffer_size);
534 //Assuming endianess of debugger and debugee match.
535 *((unsigned int *) (((char *) buffer)+size_pos)) = size;
537 *((unsigned long *) (((char *) buffer)+addr_pos)) = addr;
538 else if (addr_size == 4)
539 *((unsigned *) (((char *) buffer)+addr_pos)) = (unsigned) addr;
545 Dyninst::Address sysv_process::plat_mallocExecMemory(Dyninst::Address min, unsigned size) {
546 Dyninst::Address result = 0x0;
547 bool found_result = false;
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))
554 if (min + size > maps[i].end)
556 if (maps[i].end - maps[i].start < size)
559 if (maps[i].start > min)
560 result = maps[i].start;
566 assert(found_result);