Initial commit of StackwalkerAPI
[dyninst.git] / stackwalk / src / bluegene-swk.C
1 /*
2  * Copyright (c) 1996-2007 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/framestepper.h"
36
37 #include "stackwalk/h/procstate.h"
38 #include "stackwalk/src/bluegene-swk.h"
39
40 #include "common/h/linuxKludges.h"
41
42 #include <string>
43
44 #include <string.h>
45 #include <sys/syscall.h>
46 #include <unistd.h>
47 #include <errno.h>
48 #include <signal.h>
49 #include <sys/poll.h>
50 #include <assert.h>
51
52 using namespace Dyninst;
53 using namespace Dyninst::Stackwalker;
54 using namespace DebuggerInterface;
55 using namespace std;
56
57 SymbolLookup *Walker::createDefaultSymLookup(const std::string &exec_name)
58 {
59    SymbolLookup *new_lookup = new SwkDynSymtab(this, exec_name);
60    return new_lookup;
61 }
62
63 bool SymbolLookup::lookupLibrary(Address, Address &load_addr,
64                                  std::string &out_library)
65 {
66    load_addr = 0;
67    out_library = executable_path;
68    return true;
69 }
70
71 bool ProcSelf::getThreadIds(std::vector<THR_ID> &threads)
72 {
73   bool result;
74   THR_ID tid;
75
76   result = getDefaultThread(tid);
77   if (!result) {
78     sw_printf("[%s:%u] - Could not read default thread\n",
79                __FILE__, __LINE__);
80     return false;
81   }
82   threads.clear();
83   threads.push_back(tid);
84   return true;
85 }
86
87 ProcSelf::ProcSelf()
88 {
89   mypid = getpid();
90 }
91
92 bool ProcSelf::getDefaultThread(THR_ID &default_tid)
93 {
94   default_tid = 0;
95   return true;
96 }
97
98 static bool fdHasData(int fd)
99 {
100    int result;
101    struct pollfd fds;
102    fds.fd = fd;
103    fds.events = POLLIN;
104    fds.revents = 0;
105    result = poll(&fds, 1, 0);
106    if (result == -1) {
107       int errnum = errno;
108       sw_printf("[%s:%u] - Unable to poll fd %d: %s\n", __FILE__, __LINE__, 
109                 fd, strerror(errnum));
110       return false;
111    }
112    return (bool) (fds.revents & POLLIN);
113 }
114
115 #define SINGLE_STEP_SIG 32064
116
117 DebugEvent ProcDebug::debug_get_event(bool block)
118 {
119    DebugEvent ev;
120    pid_t pid;
121    int sig_encountered;
122    
123    BGL_Debugger_Msg msg;
124
125
126    if (!block && !fdHasData(BGL_DEBUGGER_READ_PIPE))
127    {
128       ev.dbg = dbg_noevent;
129       return ev;
130    }
131
132    sw_printf("[%s:%u] - Waiting for debug event\n", __FILE__, __LINE__);
133    bool result = BGL_Debugger_Msg::readFromFd(BGL_DEBUGGER_READ_PIPE, msg);
134    if (!result) {
135       sw_printf("[%s:%u] - Unable to wait for debug event on process\n",
136                 __FILE__, __LINE__);
137       ev.dbg = dbg_err;
138       return ev;
139    }
140    
141    pid = msg.header.nodeNumber;   
142    sw_printf("[%s:%u] - Recieved debug event %d on %d\n", __FILE__, __LINE__,
143              msg.header.messageType, pid);
144    std::map<PID, ProcDebug *, procdebug_ltint>::iterator i = proc_map.find(pid);
145    if (i == proc_map.end())
146    {
147       sw_printf("[%s:%u] - Error, recieved unknown pid %d\n",
148                 __FILE__, __LINE__, pid);
149       setLastError(err_internal, "Error waiting for debug event");
150       ev.dbg = dbg_err;
151       return ev;
152    }
153    ev.proc = i->second;
154    ProcDebugBG *procbg = dynamic_cast<ProcDebugBG *>(ev.proc);
155    assert(procbg);
156
157    switch (msg.header.messageType)
158    {
159       case PROGRAM_EXITED:
160          ev.proc->isRunning = false;
161          
162          if (msg.dataArea.PROGRAM_EXITED.type == 0) {
163             ev.dbg = dbg_exited;
164          }
165          else if (msg.dataArea.PROGRAM_EXITED.type == 1) {
166             ev.dbg = dbg_crashed;
167          }
168          else {
169             sw_printf("[%s:%u] - Unknown exit code (%d) on process %d\n",
170                       __FILE__, __LINE__, msg.dataArea.PROGRAM_EXITED.type, pid);
171             ev.dbg = dbg_err;
172          }
173          ev.data.idata = msg.dataArea.PROGRAM_EXITED.rc;
174          sw_printf("[%s:%u] - Process %d %s with %d\n", 
175                    __FILE__, __LINE__, pid, 
176                    ev.dbg == dbg_exited ? "exited" : "crashed",
177                    ev.data.idata);
178          break;
179       case SIGNAL_ENCOUNTERED:
180          sw_printf("[%s:%u] - Process %d stopped with %d\n",
181                    __FILE__, __LINE__, pid, msg.dataArea.SIGNAL_ENCOUNTERED.signal);
182          ev.proc->isRunning = false;
183          
184          ev.dbg = dbg_stopped;
185          sig_encountered = msg.dataArea.SIGNAL_ENCOUNTERED.signal;
186          if (sig_encountered == SINGLE_STEP_SIG)
187             sig_encountered = 0;
188          ev.data.idata = msg.dataArea.SIGNAL_ENCOUNTERED.signal;
189          break;
190       case ATTACH_ACK:
191          sw_printf("[%s:%u] - Process %d acknowledged attach\n",
192                    __FILE__, __LINE__, pid);
193          ev.dbg = dbg_attached;
194          break;
195       case CONTINUE_ACK:
196          sw_printf("[%s:%u] - Process %d acknowledged continue\n", 
197                    __FILE__, __LINE__, pid);
198          ev.dbg = dbg_continued;
199          break;
200       case KILL_ACK:
201          sw_printf("[%s:%u] - Process %d acknowledged kill\n", 
202                    __FILE__, __LINE__, pid);
203          ev.dbg = dbg_other;
204          break;
205       case GET_ALL_REGS_ACK:
206          sw_printf("[%s:%u] - RegisterAll ACK on pid %d\n", 
207                    __FILE__, __LINE__, pid);
208          ev.dbg = dbg_allregs_ack;
209          ev.size = msg.header.dataLength;
210          procbg->gprs = msg.dataArea.GET_ALL_REGS_ACK.gprs;
211          break;
212       case GET_MEM_ACK:
213          sw_printf("[%s:%u] - Memread ACK on pid %d\n", 
214                    __FILE__, __LINE__, pid);
215          ev.dbg = dbg_mem_ack;
216          ev.size = msg.header.dataLength;
217          ev.data.pdata = (void *) malloc(msg.header.dataLength);
218          assert(ev.data.pdata);
219          memcpy(ev.data.pdata, &msg.dataArea, msg.header.dataLength);
220          break;
221       case SINGLE_STEP_ACK:
222          sw_printf("[%s:%u] - Process %d recieved SINGLE_STEP\n",
223                    __FILE__, __LINE__, pid, ev.data);
224          assert(ev.proc->isRunning);
225          ev.proc->isRunning = false;
226          
227          ev.dbg = dbg_stopped;
228          ev.data.idata = 0;
229          break;
230       default:
231          sw_printf("[%s:%u] - Unknown debug message: %d\n",
232                    __FILE__, __LINE__, msg.header.messageType);
233          ev.dbg = dbg_noevent;
234          break;
235    }
236    return ev;
237 }
238
239 bool ProcDebugBG::debug_handle_event(DebugEvent ev)
240 {
241   bool result;
242
243   switch (ev.dbg)
244   {
245      case dbg_stopped:
246         isRunning = false;
247         
248         if (state == ps_attached_intermediate) {
249            sw_printf("[%s:%u] - Moving %d to state running\n", 
250                      __FILE__, __LINE__, pid);
251            state = ps_attached;
252            return true;
253         }
254         
255         if (ev.data.idata == SINGLE_STEP_SIG) {
256            if (user_isRunning) {
257               ev.data.idata = 0;
258               result = debug_handle_signal(&ev);
259            }
260         }
261
262         if (ev.data.idata != SIGSTOP) {
263            result = debug_handle_signal(&ev);
264            if (!result) {
265               sw_printf("[%s:%u] - Debug continue failed on %d with %d\n", 
266                         __FILE__, __LINE__, pid, ev.data.idata);
267               return false;
268            }
269         }
270         return true;
271     case dbg_crashed:
272       sw_printf("[%s:%u] - Handling process crash on %d\n",
273                 __FILE__, __LINE__, pid);
274     case dbg_exited:
275       sw_printf("[%s:%u] - Handling process death on %d\n",
276                 __FILE__, __LINE__, pid);
277       state = ps_exited;
278       return true;
279     case dbg_continued:
280        sw_printf("[%s:%u] - Process %d continued\n", __FILE__, __LINE__, pid);
281        clear_cache();
282        assert(!isRunning);
283        isRunning = true;
284        break;
285     case dbg_attached:
286        sw_printf("[%s:%u] - Process %d attached\n", __FILE__, __LINE__, pid);
287        assert(state == ps_neonatal);
288        state = ps_attached_intermediate;
289        debug_pause(); //TODO or not TODO?
290        break;
291     case dbg_mem_ack:
292        sw_printf("[%s:%u] - Process %d returned a memory chunck of size %u", 
293                  __FILE__, __LINE__, pid, ev.size);
294        assert(!mem_data);
295        mem_data = ev.data.pdata;
296        mem_data_size = ev.size;
297     case dbg_allregs_ack:
298        sw_printf("[%s:%u] - Process %d returned a register chunck of size %u", 
299                  __FILE__, __LINE__, pid, ev.size);
300        gprs_set = true;
301        break;
302     case dbg_other:
303        sw_printf("[%s:%u] - Skipping unimportant event\n", __FILE__, __LINE__);
304        break;
305     case dbg_err:
306     case dbg_noevent:       
307     default:
308       sw_printf("[%s:%u] - Unexpectedly handling an error event %d on %d\n", 
309                 __FILE__, __LINE__, ev.dbg, pid);
310       setLastError(err_internal, "Told to handle an unexpected event.");
311       return false;
312   }
313   return true;
314 }
315
316 bool ProcDebugBG::debug_create(const std::string &, 
317                                const std::vector<std::string> &)
318 {
319   setLastError(err_unsupported, "Create mode not supported on BlueGene");
320   return false;
321 }
322
323 bool ProcDebugBG::debug_attach()
324 {
325    BGL_Debugger_Msg msg(ATTACH, pid, 0, 0, 0);
326    msg.header.dataLength = sizeof(msg.dataArea.ATTACH);
327
328    sw_printf("[%s:%u] - Attaching to pid\n", __FILE__, __LINE__, pid);
329    bool result = BGL_Debugger_Msg::writeOnFd(BGL_DEBUGGER_WRITE_PIPE, msg);
330    if (!result) {
331       sw_printf("[%s:%u] - Unable to attach to process %d\n",
332                 __FILE__, __LINE__, pid);
333       return false;
334    }
335    return true;
336 }
337
338 bool ProcDebugBG::debug_pause() 
339 {
340    BGL_Debugger_Msg msg(KILL, pid, 0, 0, 0);
341    msg.dataArea.KILL.signal = SIGSTOP;
342    msg.header.dataLength = sizeof(msg.dataArea.KILL);
343
344    sw_printf("[%s:%u] - Sending SIGSTOP to pid %d\n", __FILE__, __LINE__, pid);
345    bool result = BGL_Debugger_Msg::writeOnFd(BGL_DEBUGGER_WRITE_PIPE, msg);
346
347    if (!result) {
348       sw_printf("[%s:%u] - Unable to send SIGSTOP to process %d\n",
349                 __FILE__, __LINE__, pid);
350       return false;
351    }
352    return true;
353 }
354
355 bool ProcDebugBG::debug_continue()
356 {
357    return debug_continue_with(0);
358 }
359
360 bool ProcDebugBG::debug_continue_with(long sig)
361 {
362    assert(!isRunning);
363    BGL_Debugger_Msg msg(CONTINUE, pid, 0, 0, 0);
364    msg.dataArea.CONTINUE.signal = sig;
365    msg.header.dataLength = sizeof(msg.dataArea.CONTINUE);
366
367
368    sw_printf("[%s:%u] - Sending signal %d to pid %d\n", __FILE__, __LINE__, sig, pid);
369    bool result = BGL_Debugger_Msg::writeOnFd(BGL_DEBUGGER_WRITE_PIPE, msg);
370    if (!result) {
371       sw_printf("[%s:%u] - Unable to send %d to process %d\n",
372                 __FILE__, __LINE__, sig, pid);
373       return false;
374    }
375    return true;
376 }
377
378 bool ProcDebugBG::debug_handle_signal(DebugEvent *ev)
379 {
380    assert(ev->dbg == dbg_stopped);
381    sw_printf("[%s:%u] - Handling signal for pid %d\n", 
382              __FILE__, __LINE__, pid);
383    return debug_continue_with(ev->data.idata);
384 }
385
386 #if !defined(BGL_READCACHE_SIZE)
387 #define BGL_READCACHE_SIZE 2048
388 #endif
389
390 bool ProcDebugBG::readMem(void *dest, Address source, size_t size)
391 {
392    unsigned char *ucdest = (unsigned char *) dest;
393    bool result;
394
395    for (;;)
396    {
397       if (size == 0)
398          return true;
399
400       sw_printf("[%s:%u] - Reading memory from 0x%lx to 0x%lx (into %p)\n",
401                 __FILE__, __LINE__, source, source+size, ucdest);
402       if (source >= read_cache_start && 
403           source+size < read_cache_start + read_cache_size)
404       {
405          //Lucky us, we have everything cached.
406          memcpy(ucdest, read_cache + (source - read_cache_start), size);
407          return true;
408       }
409       if (source >= read_cache_start &&
410           source < read_cache_start + read_cache_size)
411       {
412          //The beginning is in the cache, read those bytes
413          long cached_bytes = read_cache_start + read_cache_size - source;
414          memcpy(ucdest, read_cache + (source - read_cache_start), cached_bytes);
415          //Change the parameters and continue the read (this is a kind of
416          // optimized tail call).
417          ucdest += cached_bytes;
418          source = read_cache_start + read_cache_size;
419          size -= cached_bytes;
420          continue;
421       }
422       if (source+size > read_cache_start &&
423           source+size <= read_cache_start + read_cache_size)
424       {
425          //The end is in the cache, read those bytes
426          long cached_bytes = (source+size) - read_cache_start;
427          memcpy(ucdest + read_cache_start - source, read_cache, cached_bytes);
428          //Change the parameters and continue the read (this is a kind of
429          // optimized tail call).
430          size -= cached_bytes;
431          continue;
432       }
433       if (source < read_cache_start &&
434           source+size >= read_cache_start+read_cache_size)
435       {
436          //The middle is in the cache
437          unsigned char *dest_start = ucdest + read_cache_start - source;
438          Address old_read_cache_start = read_cache_start;
439          memcpy(dest_start, read_cache, read_cache_size);
440          //Use actual recursion here, as we need to queue up two reads
441          // First read out of the high memory with recursion
442          result = readMem(dest_start + read_cache_size, 
443                           read_cache_start+read_cache_size,
444                           source+size - read_cache_start+read_cache_size);
445          if (!result) {
446             return false;
447          }
448          // Now read out of the low memory
449          size = old_read_cache_start - source;
450          continue;
451       }
452       //The memory isn't cached, read a new cache'd page.
453       assert(source < read_cache_start || 
454              source >= read_cache_start+read_cache_size);
455       
456       if (!read_cache) {
457          read_cache = (unsigned char *) malloc(BGL_READCACHE_SIZE);
458          assert(read_cache);
459       }
460
461       read_cache_size = BGL_READCACHE_SIZE;
462       read_cache_start = source - (source % read_cache_size);
463       sw_printf("[%s:%u] - Caching memory from 0x%lx to 0x%lx\n",
464              __FILE__, __LINE__, read_cache_start, 
465              read_cache_start+read_cache_size);
466                     
467       //Read read_cache_start to read_cache_start+read_cache_size into our
468       // cache.
469       assert(!mem_data);
470       assert(read_cache_size < BGL_Debugger_Msg_MAX_MEM_SIZE);
471
472       BGL_Debugger_Msg msg(GET_MEM, pid, 0, 0, 0);
473       msg.header.dataLength = sizeof(msg.dataArea.GET_MEM);
474       msg.dataArea.GET_MEM.addr = read_cache_start;
475       msg.dataArea.GET_MEM.len = read_cache_size;
476       bool result = BGL_Debugger_Msg::writeOnFd(BGL_DEBUGGER_WRITE_PIPE, msg);
477       if (!result) {
478          sw_printf("[%s:%u] - Unable to write to process %d\n",
479                    __FILE__, __LINE__, pid);
480          return true;
481       }
482       
483       //Wait for the read to return
484       sw_printf("[%s:%u] - Waiting for read to return on pid %d\n",
485                 __FILE__, __LINE__);
486       do {
487          bool handled, result;
488          result = debug_wait_and_handle(true, handled);
489          if (!result)
490          {
491             sw_printf("[%s:%u] - Error while waiting for read to return\n",
492                       __FILE__, __LINE__);
493             return false;
494          }
495       } while (!mem_data);
496
497       //TODO: How do we detect errors?
498       BGL_Debugger_Msg::DataArea *da = (BGL_Debugger_Msg::DataArea *) mem_data;
499       assert(da->GET_MEM_ACK.addr == read_cache_start);
500       assert(da->GET_MEM_ACK.len == read_cache_size);
501       memcpy(read_cache, da->GET_MEM_ACK.data, read_cache_size);
502       
503       //Free up the memory data
504       free(mem_data);
505       mem_data = NULL;
506    }
507 }   
508
509 bool ProcDebugBG::getThreadIds(std::vector<THR_ID> &threads)
510 {
511    threads.clear();
512    threads.push_back((THR_ID) 0);
513    return true;
514 }
515
516 bool ProcDebugBG::getDefaultThread(THR_ID &default_tid)
517 {
518    default_tid = (THR_ID) 0;
519    return true;
520 }
521
522 unsigned ProcDebugBG::getAddressWidth()
523 {
524    return sizeof(long);
525 }
526
527 bool ProcDebugBG::getRegValue(reg_t reg, Dyninst::THR_ID, regval_t &val)
528 {
529
530    if (!gprs_set)
531    {
532       BGL_Debugger_Msg msg(GET_ALL_REGS, pid, 0, 0, 0);
533       msg.header.dataLength = sizeof(msg.dataArea.GET_ALL_REGS);
534       bool result = BGL_Debugger_Msg::writeOnFd(BGL_DEBUGGER_WRITE_PIPE, msg);
535       if (!result) {
536          sw_printf("[%s:%u] - Unable to write to process %d\n",
537                    __FILE__, __LINE__, pid);
538          return true;
539       }
540       
541       //Wait for the read to return
542       sw_printf("[%s:%u] - Waiting for read to return on pid %d\n",
543                 __FILE__, __LINE__);
544       do {
545          bool handled, result;
546          result = debug_wait_and_handle(true, handled);
547          if (!result)
548          {
549             sw_printf("[%s:%u] - Error while waiting for read to return\n",
550                       __FILE__, __LINE__);
551             return false;
552          }
553       } while (!gprs_set);
554    }
555    
556    switch(reg)
557    {
558       case REG_SP:
559          val = 0x0;
560          break;
561       case REG_FP:
562          val = gprs.gpr[BGL_GPR1];
563          break;
564       case REG_PC:
565          val = gprs.iar;
566          break;
567       default:
568          sw_printf("[%s:%u] - Request for unsupported register %d\n",
569                    __FILE__, __LINE__, reg);
570          setLastError(err_badparam, "Unknown register passed in reg field");
571          return false;
572    }   
573    return true;
574 }
575
576 ProcDebugBG::~ProcDebugBG()
577 {
578 }
579
580 ProcDebugBG::ProcDebugBG(PID pid)
581    : ProcDebug(pid),
582      mem_data(NULL),
583      mem_data_size(0),
584      gprs_set(false),
585      read_cache(NULL),
586      read_cache_start(0x0),
587      read_cache_size(0x0)
588 {
589 }
590
591 ProcDebug *ProcDebug::newProcDebug(const std::string &, 
592                                    const std::vector<std::string> &)
593 {
594   setLastError(err_unsupported, "Executable launch not supported on BlueGene");
595   return NULL;
596 }
597
598 ProcDebug *ProcDebug::newProcDebug(PID pid)
599 {
600    ProcDebug *pd = new ProcDebugBG(pid);
601    if (!pd)
602    {
603       sw_printf("[%s:%u] - Error creating new ProcDebug object\n",
604                 __FILE__, __LINE__);
605       if (pd)
606          delete pd;
607       return NULL;
608    }
609
610    bool result = pd->attach();
611    if (!result || pd->state != ps_running) {
612      pd->state = ps_errorstate;
613      proc_map.erase(pid);
614      sw_printf("[%s:%u] - Error attaching to process %d\n",
615                __FILE__, __LINE__, pid);
616      delete pd;
617      return NULL;
618    }
619
620    return pd;
621 }
622
623 bool ProcDebug::newProcDebugSet(const vector<Dyninst::PID> &pids,
624                                 vector<ProcDebug *> &out_set)
625 {
626    bool result;
627    vector<Dyninst::PID>::const_iterator i;
628    for (i=pids.begin(); i!=pids.end(); i++)
629    {
630       Dyninst::PID pid = *i;
631       ProcDebug *new_pd = new ProcDebugBG(pid);
632       if (!new_pd) {
633          fprintf(stderr, "[%s:%u] - Unable to allocate new ProcDebugBG\n",
634                  __FILE__, __LINE__);
635          return false;
636       }
637       out_set.push_back(new_pd);
638    }
639
640    result = multi_attach(out_set);
641    return result;
642 }
643
644 bool Walker::createDefaultSteppers()
645 {
646   FrameStepper *stepper;
647   bool result;
648
649   stepper = new FrameFuncStepper(this);
650   result = addStepper(stepper);
651   if (!result) {
652     sw_printf("[%s:%u] - Error adding stepper %p\n", __FILE__, __LINE__,
653               stepper);
654     return false;
655   }
656
657   return true;
658 }
659
660 bool BGL_Debugger_Msg::writeOnFd(int fd, 
661                                  DebuggerInterface::BGL_Debugger_Msg &msg)
662 {
663    int result;
664    result = write(fd, &msg.header, sizeof(msg.header));
665    if (result != -1) {
666       result = write(fd, &msg.dataArea, msg.header.dataLength);
667    }
668
669    if (result == -1) {
670       int errnum = errno;
671       sw_printf("[%s:%u] - Error writing to process: %s\n", 
672                 __FILE__, __LINE__, strerror(errnum));
673       setLastError(err_internal, "Error writing message to process");
674       return false;
675    }
676    
677    return true;
678 }
679
680 bool BGL_Debugger_Msg::readFromFd(int fd, 
681                                   DebuggerInterface::BGL_Debugger_Msg &msg)
682 {
683    int result;
684    result = read(fd, &msg.header, sizeof(msg.header));
685    if (result != -1 && msg.header.dataLength) {
686       result = read(fd, &msg.dataArea, msg.header.dataLength);
687    }
688    if (result == -1) {
689       int errnum = errno;
690       sw_printf("[%s:%u] - Error reading from process: %s\n", 
691                 __FILE__, __LINE__, strerror(errnum));
692       setLastError(err_internal, "Error reading message from process");
693       return false;
694    }
695    return true;
696 }
697
698 bool ProcSelf::readMem(void *dest, Address source, size_t size)
699 {
700    memcpy(dest, (void *) source, size);
701    return true;
702 }
703
704 int ProcDebug::getNotificationFD() {
705   return BGL_DEBUGGER_READ_PIPE;
706 }
707
708 void ProcDebugBG::clear_cache()
709 {
710   gprs_set = false;
711   read_cache_start = 0x0;
712   read_cache_size = 0x0;
713   mem_data = NULL;
714   mem_data_size = 0x0;
715 }
716