StackwalkerAPI ppc fixes
[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 #include "stackwalk/src/bluegene-swk.h"
32 using namespace DebuggerInterface;
33
34 #include "stackwalk/src/bluegenel-swk.h"
35 #include "stackwalk/src/bluegenep-swk.h"
36
37 #include "stackwalk/h/swk_errors.h"
38 #include "stackwalk/h/symlookup.h"
39 #include "stackwalk/h/walker.h"
40 #include "stackwalk/h/framestepper.h"
41 #include "stackwalk/h/procstate.h"
42 #include "stackwalk/src/symtab-swk.h"
43 using namespace Dyninst;
44 using namespace Dyninst::Stackwalker;
45
46 #include <string>
47 #include <memory>
48 #include <string.h>
49 #include <sys/syscall.h>
50 #include <unistd.h>
51 #include <errno.h>
52 #include <signal.h>
53 #include <sys/poll.h>
54 #include <assert.h>
55 using namespace std;
56
57
58 namespace Dyninst {
59   namespace Stackwalker {
60
61     bool bg_fdHasData(int fd) {
62       int result;
63       struct pollfd fds;
64       fds.fd = fd;
65       fds.events = POLLIN;
66       fds.revents = 0;
67       result = poll(&fds, 1, 0);
68       if (result == -1) {
69         int errnum = errno;
70         sw_printf("[%s:%u] - Unable to poll fd %d: %s\n", __FILE__, __LINE__, 
71                   fd, strerror(errnum));
72         return false;
73       }
74       return (bool) (fds.revents & POLLIN);
75     }
76
77
78     // ============================================================ //
79     // Walker
80     // ============================================================ //
81     bool Walker::createDefaultSteppers() {
82       FrameStepper *stepper = new FrameFuncStepper(this);
83       bool result = addStepper(stepper);
84       if (!result) {
85         sw_printf("[%s:%u] - Error adding stepper %p\n", __FILE__, __LINE__, stepper);
86       }
87       return result;
88     }
89
90
91     // ============================================================ //
92     // ProcSelf -- all stubs; this is 3rd-party only
93     // ============================================================ //
94     static bool proc_self_unsupported(const char *file, size_t line) {
95       const char *msg = "ProcSelf not supported for 3rd party BG stackwalkers!";
96       sw_printf("[%s:%u] - %s\n", file, line, msg);
97       setLastError(err_procread, msg);
98       return false;
99     }
100
101     bool ProcSelf::getThreadIds(std::vector<THR_ID> &) {
102       return proc_self_unsupported(__FILE__, __LINE__);
103     }
104
105
106     ProcSelf::ProcSelf() : ProcessState(getpid()) {
107       proc_self_unsupported(__FILE__, __LINE__);
108     }
109
110
111     void ProcSelf::initialize() {
112       proc_self_unsupported(__FILE__, __LINE__);
113     }
114
115
116     bool ProcSelf::getDefaultThread(THR_ID &) {
117       return proc_self_unsupported(__FILE__, __LINE__);
118     }
119
120
121     bool ProcSelf::readMem(void *, Address, size_t) {
122       return proc_self_unsupported(__FILE__, __LINE__);
123     }
124
125
126     // ============================================================ //
127     // ProcDebug
128     // ============================================================ //
129     ProcDebug *ProcDebug::newProcDebug(PID pid, string executable) {
130       auto_ptr<ProcDebug> pd(ProcDebugBG::createProcDebugBG(pid, executable));
131       if (!pd.get()) {
132         const char *msg = "Error creating new ProcDebug object";
133         sw_printf("[%s:%u] - %s\n", __FILE__, __LINE__, msg);
134         setLastError(err_internal, msg);
135         return NULL;
136       }
137   
138       bool result = pd->attach();
139       if (!result || (pd->state() != ps_running && pd->state() != ps_attached))
140       {
141         pd->setState(ps_errorstate);
142         proc_map.erase(pid);
143         const char *msg = "Error attaching to process";
144         sw_printf("[%s:%u] - %s %d\n", __FILE__, __LINE__, msg, pid);
145         setLastError(err_noproc, msg);
146         return NULL;
147       }
148   
149       return pd.release();
150     }
151
152
153     bool ProcDebug::newProcDebugSet(const vector<Dyninst::PID>&, vector<ProcDebug*>&) {
154       setLastError(err_unsupported, "ERROR: newProcDebugSet not implemented for BlueGene Stackwalker!");
155       return false;
156     }
157
158
159     ProcDebug *ProcDebug::newProcDebug(const std::string &, const std::vector<std::string> &) {
160       setLastError(err_unsupported, "Executable launch not supported on BlueGene");
161       return NULL;
162     }
163
164
165     bool ProcDebugBG::isLibraryTrap(Dyninst::THR_ID) {
166       // Base ProcDebugBG doesn't support dynamic libs.
167       return false;
168     }
169
170
171     DebugEvent ProcDebug::debug_get_event(bool block) {
172       DebugEvent ev;   
173       BG_Debugger_Msg msg;
174
175       if (!block && !bg_fdHasData(BG_DEBUGGER_READ_PIPE)) {
176         ev.dbg = dbg_noevent;
177         return ev;
178       }
179
180       // Read an event from the debug filehandle.
181       sw_printf("[%s:%u] - Waiting for debug event\n", __FILE__, __LINE__);
182       bool result = BG_Debugger_Msg::readFromFd(BG_DEBUGGER_READ_PIPE, msg);
183       if (!result) {
184         sw_printf("[%s:%u] - Unable to wait for debug event on process\n",
185                   __FILE__, __LINE__);
186         ev.dbg = dbg_err;
187         return ev;
188       }
189
190       // extract process and thread id from the BG message.
191       pid_t pid = msg.header.nodeNumber;   
192       THR_ID tid = msg.header.thread;
193       int returnCode = msg.header.returnCode;
194       sw_printf("[%s:%u] - Received debug event %s from pid %d, tid %d, rc %d\n", __FILE__, __LINE__,
195                 BG_Debugger_Msg::getMessageName(msg.header.messageType), pid, tid, returnCode);
196
197       if (returnCode > 0) {
198         // Print out a message if we get a return code we don't expect.  Consult the debugger header
199         // for the meanings of these.
200         sw_printf("[%s:%u] - WARNING: return code for %s on pid %d, tid %d was non-zero: %d\n",
201                   __FILE__, __LINE__, 
202                   BG_Debugger_Msg::getMessageName(msg.header.messageType), pid, tid,
203                   msg.header.returnCode);
204       }
205
206       // Look up the ProcDebugBG from which the event originated.      
207       std::map<PID, ProcessState *>::iterator i = proc_map.find(pid);
208       if (i == proc_map.end()) {
209         sw_printf("[%s:%u] - Error, received unknown pid %d\n", __FILE__, __LINE__, pid);
210         setLastError(err_internal, "Error waiting for debug event");
211         ev.dbg = dbg_err;
212         return ev;
213       }
214       ProcDebugBG *procbg = dynamic_cast<ProcDebugBG*>(i->second);
215       assert(procbg);
216       ev.proc = procbg;
217       
218       // below is some (somewhat nasty) magic to allow stackwalker to discover the 
219       // initial thread's id after it attaches.
220       thread_map_t::iterator t = procbg->threads.find(tid);
221       if (t == procbg->threads.end()) {
222         BGThreadState *initial_thread = dynamic_cast<BGThreadState*>(procbg->initial_thread);
223
224         if (tid != 0) {
225           // Check to see if the initial thread is valid.  If its id is zero, it's a stub
226           // from creation time and we got a signal from the real initial thread.  If it's
227           // not zero, then we're seeing a strange thread id.
228           if (initial_thread->getTid() != 0) {
229             const char *msg = "Saw unknown thread id in ProcDebug::debug_get_evet()!";
230             sw_printf("[%s:%u] - %s on pid %d\n", __FILE__, __LINE__, msg, pid);
231             setLastError(err_internal, msg);
232             ev.dbg = dbg_err;
233             return ev;
234           }
235           
236           // if we see a threadid we don't know about, it's because we got a SIGNAL_ENCOUNTERED
237           // from the main thread.  We default the initial thread id to zero, but this is only because
238           // we need to start somewhere to attach.  This sets the main thread id to the real thread id
239           // for the process.  This should happen relatively early when we stop the thread during attach.
240           procbg->threads.erase(initial_thread->getTid());
241           initial_thread->setTid(tid);
242           procbg->threads[tid] = initial_thread;
243           t = procbg->threads.find(tid);
244
245         } else {
246           // if the thread id we don't know about is zero, we got an ack for something we
247           // did before we discovered what the initial thread id was.  So just point the event
248           // at the initial thread
249           t = procbg->threads.find(initial_thread->getTid());
250         }
251       }
252
253       ThreadState *ts = t->second;
254       assert(ts);
255       ev.thr = ts;
256       
257       procbg->translate_event(msg, ev);
258       return ev;
259     }
260
261
262    int ProcDebug::getNotificationFD() {
263       return BG_DEBUGGER_READ_PIPE;
264     }
265
266
267     // ============================================================ //
268     // ProcDebugBG
269     // ============================================================ /
270     void ProcDebugBG::translate_event(const BG_Debugger_Msg& msg, DebugEvent& ev) {
271       switch (msg.header.messageType) {
272       case PROGRAM_EXITED:
273         {
274           ev.data.idata = msg.dataArea.PROGRAM_EXITED.rc;
275           int exit_type = msg.dataArea.PROGRAM_EXITED.type;
276
277           if (exit_type == 0) {
278             ev.dbg = dbg_exited;
279             sw_printf("[%s:%u] - Process %d exited with %d\n", __FILE__, __LINE__, pid, ev.data.idata);
280           } else if (exit_type == 1) {
281             ev.dbg = dbg_crashed;
282             sw_printf("[%s:%u] - Process %d crashed with %d\n", __FILE__, __LINE__, pid, ev.data.idata);
283           } else {
284             ev.dbg = dbg_err;
285             sw_printf("[%s:%u] - WARNING: Unknown exit type (%d) on process %d. "
286                       "May be using outdated BG Debugger Interface!\n", __FILE__, __LINE__, 
287                       msg.dataArea.PROGRAM_EXITED.type, pid);
288           }
289         }
290         break;
291         
292       case SIGNAL_ENCOUNTERED:
293         ev.dbg = dbg_stopped;
294         ev.data.idata = msg.dataArea.SIGNAL_ENCOUNTERED.signal;
295         sw_printf("[%s:%u] - Process %d stopped with %d\n",
296                   __FILE__, __LINE__, pid, msg.dataArea.SIGNAL_ENCOUNTERED.signal);
297         break;
298
299       case ATTACH_ACK:
300         ev.dbg = dbg_attached;
301         sw_printf("[%s:%u] - Process %d acknowledged attach\n", __FILE__, __LINE__, pid);
302         break;
303
304       case CONTINUE_ACK:
305         ev.dbg = dbg_continued;
306         sw_printf("[%s:%u] - Process %d acknowledged continue\n", __FILE__, __LINE__, pid);
307         break;
308
309       case KILL_ACK:
310         ev.dbg = dbg_other;
311         sw_printf("[%s:%u] - Process %d acknowledged kill\n", __FILE__, __LINE__, pid);
312         break;
313
314       case GET_ALL_REGS_ACK:
315         {
316           ev.dbg = dbg_allregs_ack;
317           ev.size = msg.header.dataLength;
318           BG_GPRSet_t *data = new BG_GPRSet_t();
319           *data = msg.dataArea.GET_ALL_REGS_ACK.gprs;
320           ev.data.pdata = data;
321           sw_printf("[%s:%u] - RegisterAll ACK on pid %d\n", __FILE__, __LINE__, pid);
322         }
323         break;
324
325       case GET_MEM_ACK:
326         ev.dbg = dbg_mem_ack;
327         ev.size = msg.header.dataLength;
328         ev.data.pdata = new unsigned char[msg.header.dataLength];
329         if (!ev.data.pdata) {
330           ev.dbg = dbg_err;
331           sw_printf("[%s:%u] - FATAL: Couldn't allocate enough space for memory read on pid %d\n", 
332                     __FILE__, __LINE__, pid);
333         } else {
334           memcpy(ev.data.pdata, &msg.dataArea, msg.header.dataLength);
335           sw_printf("[%s:%u] - Memory read ACK on pid %d\n", __FILE__, __LINE__, pid);
336         }
337         break;
338
339     case SET_MEM_ACK:
340         ev.dbg = dbg_setmem_ack;
341         ev.size = msg.dataArea.SET_MEM_ACK.len;
342         sw_printf("[%s:%u] - Memory write ACK on pid %d ($d bytes at %x).  \n", __FILE__, __LINE__, 
343                   msg.dataArea.SET_MEM_ACK.len, msg.dataArea.SET_MEM_ACK.addr);
344         break;
345
346       case SINGLE_STEP_ACK:
347         // single step ack is just an ack (like KILL_ACK). We ignore this event and 
348         // handle SINGLE_STEP_SIG specially in debug_handle_signal().
349         ev.dbg = dbg_other;
350         sw_printf("[%s:%u] - Process %d received SINGLE_STEP\n", __FILE__, __LINE__, pid, ev.data);
351         break;
352
353       default:
354         sw_printf("[%s:%u] - Unknown debug message: %s (%d)\n",
355                   __FILE__, __LINE__, 
356                   BG_Debugger_Msg::getMessageName(msg.header.messageType),
357                   msg.header.messageType);
358         ev.dbg = dbg_noevent;
359         break;
360      }
361   }
362
363
364     void copy_thread_state(ThreadState *source, ThreadState *dest) {
365       dest->setState(source->state());
366       dest->setStopped(source->isStopped());
367       dest->setShouldResume(source->shouldResume());
368       dest->setUserStopped(source->userIsStopped());
369     }
370
371     bool ProcDebugBG::pollForNewThreads() {
372       return true;  // by default, we don't find anything.
373     }
374
375
376     // This basic implementation assumes *only* the initial thread.
377     bool ProcDebugBG::getThreadIds(std::vector<THR_ID> &threads) {
378       threads.clear();
379       threads.push_back(initial_thread->getTid());
380       return true;
381     }
382
383
384     bool ProcDebugBG::getDefaultThread(THR_ID &default_tid) {
385       default_tid = initial_thread->getTid();
386       return true;
387     }
388
389
390     unsigned ProcDebugBG::getAddressWidth() {
391       return sizeof(DebuggerInterface::BG_Addr_t);
392     }
393
394
395     bool ProcDebugBG::debug_continue(ThreadState *ts) {
396       return debug_continue_with(ts, 0);
397     }
398
399
400     ProcDebugBG::~ProcDebugBG() {
401       if (read_cache) delete [] read_cache;
402     }
403
404
405     ProcDebugBG::ProcDebugBG(PID pid, string exe)
406       : ProcDebug(pid, exe),
407         mem_data(NULL),
408         read_cache(NULL),
409         read_cache_start(0x0),
410         read_cache_size(0x0)
411     {
412     }
413
414
415     bool ProcDebugBG::debug_create(const std::string &, const std::vector<std::string> &) 
416     {
417       setLastError(err_unsupported, "Create mode not supported on BlueGene");
418       return false;
419     }
420
421
422     struct set_gprs {
423       bool val;
424       set_gprs(bool v) : val(v) { }
425       void operator()(ThreadState *ts) {
426         dynamic_cast<BGThreadState*>(ts)->gprs_set = val;
427       }
428     };
429
430
431     void ProcDebugBG::clear_cache() {
432       for_all_threads(set_gprs(false));
433       read_cache_start = 0x0;
434       read_cache_size = 0x0;
435       mem_data = NULL;
436     }
437
438
439     bool ProcDebugBG::version_msg()
440     {
441       bool result = debug_version_msg();
442       if (!result) {
443         sw_printf("[%s:%u] - Could not version msg debugee %d\n", __FILE__, __LINE__, pid);
444         return false;
445       }
446    
447       result = debug_waitfor_version_msg();
448       if (state() == ps_exited) {
449         setLastError(err_procexit, "Process exited unexpectedly during version_msg");
450         return false;
451       }
452       if (!result) {
453         sw_printf("[%s:%u] - Error during process version_msg for %d\n",
454                   __FILE__, __LINE__, pid);
455         return false;
456       }   
457       return true;
458     }
459
460
461     bool ProcDebugBG::debug_waitfor_version_msg() {
462       sw_printf("[%s:%u] - At debug_waitfor_Version_msg.\n", __FILE__, __LINE__);
463       bool handled, result;
464    
465       result = debug_wait_and_handle(true, false, handled);
466       if (!result || state() == ps_errorstate) {
467         sw_printf("[%s:%u] - Error,  Process %d errored during version_msg\n",
468                   __FILE__, __LINE__, pid);
469         return false;
470       }
471       if (state() == ps_exited) {
472         sw_printf("[%s:%u] - Error.  Process %d exited during version_msg\n",
473                   __FILE__, __LINE__, pid);
474         return false;
475       }
476       sw_printf("[%s:%u] - Successfully version_msg %d\n",
477                 __FILE__, __LINE__, pid);
478       return true;      
479     }
480
481
482
483     bool ProcDebugBG::debug_handle_event(DebugEvent ev)
484     {
485       BGThreadState *thr = dynamic_cast<BGThreadState*>(ev.thr);
486
487       switch (ev.dbg) {
488       case dbg_stopped:
489         // we got a signal from the process.  Stop all the threads and let 
490         // debug_handle_signal() take care of things.
491         for_all_threads(set_stopped(true));
492         return debug_handle_signal(&ev);
493
494       case dbg_crashed:
495         sw_printf("[%s:%u] - Process %d crashed!\n", __FILE__, __LINE__, pid);
496         // fallthru
497
498       case dbg_exited:
499         sw_printf("[%s:%u] - Handling process exit on %d\n", __FILE__, __LINE__, pid);
500         for_all_threads(set_stopped(true));
501         for_all_threads(set_state(ps_exited));
502         break;
503
504       case dbg_continued:
505         sw_printf("[%s:%u] - Process %d continued\n", __FILE__, __LINE__, pid);
506         clear_cache();
507         assert(thr->isStopped());
508         for_all_threads(set_stopped(false));
509         break;
510
511       case dbg_attached:
512         sw_printf("[%s:%u] - Process %d attached\n", __FILE__, __LINE__, pid);
513         assert(state() == ps_neonatal);
514         for_all_threads(set_state(ps_attached_intermediate));
515         debug_pause(NULL); //immediately after debug_attach, pause the process.
516         break;
517
518       case dbg_mem_ack:
519         sw_printf("[%s:%u] - Process %d returned a memory chunk of size %u\n", 
520                   __FILE__, __LINE__, pid, ev.size);
521         assert(!mem_data);
522         mem_data = static_cast<BG_Debugger_Msg::DataArea*>(ev.data.pdata);
523         break;
524
525       case dbg_setmem_ack:
526         sw_printf("[%s:%u] - Process %d set a chunk of memory of size %u\n", 
527                   __FILE__, __LINE__, pid, ev.size);
528         break;
529
530       case dbg_allregs_ack:
531         {
532           sw_printf("[%s:%u] - Process %d returned a register chunk of size %u\n", 
533                     __FILE__, __LINE__, pid, ev.size);
534           BG_GPRSet_t *data = static_cast<BG_GPRSet_t*>(ev.data.pdata);
535           thr->gprs = *data;
536           thr->gprs_set = true;
537           ev.data.pdata = NULL;
538           delete data;
539         }
540         break;
541
542       case dbg_other:
543         sw_printf("[%s:%u] - Skipping unimportant event\n", __FILE__, __LINE__);
544         break;
545
546       case dbg_err:
547       case dbg_noevent:       
548       default:
549         sw_printf("[%s:%u] - Unexpectedly handling an error event %d on %d\n", 
550                   __FILE__, __LINE__, ev.dbg, pid);
551         setLastError(err_internal, "Told to handle an unexpected event.");
552         return false;
553       }
554
555       return true;
556     }
557
558
559     bool ProcDebugBG::debug_handle_signal(DebugEvent *ev) {
560       assert(ev->dbg == dbg_stopped); 
561       // PRE: we got a signal event, and things are stopped.
562
563       sw_printf("[%s:%u] - Handling signal for pid %d\n", __FILE__, __LINE__, pid);
564       BGThreadState *thr = dynamic_cast<BGThreadState*>(ev->thr);
565
566       switch (ev->data.idata) {
567       case SIGSTOP:
568         // if we're attaching, SIGSTOP tells us we've completed.
569         if (state() == ps_attached_intermediate) {
570           setState(ps_attached);
571           sw_printf("[%s:%u] - Moving %d to state ps_attached\n", __FILE__, __LINE__, pid);
572         }
573         // if we're not attaching, do nothing.  leave the thread stopped.
574         break;
575         
576       case SINGLE_STEP_SIG:
577         // BG uses this special signal to indicate completion of a single step.
578         // Ignore the event and continue if the user didn't stop. TODO: why?
579         // Otherwise, if *we* stopped, just stay stopped.
580         clear_cache();  // took a step, need to clear cache.
581         return thr->userIsStopped() ? true : debug_continue_with(thr, 0);
582         break;
583         
584       default:
585         // by default, pass the signal back to the process being debugged.
586         return debug_continue_with(thr, ev->data.idata);
587       }
588       
589       return true;
590     }
591
592
593     bool ProcDebugBG::debug_attach(ThreadState *ts)
594     {
595       THR_ID tid = ts->getTid();
596       BG_Debugger_Msg msg(ATTACH, pid, tid, 0, 0);
597       msg.header.dataLength = sizeof(msg.dataArea.ATTACH);
598       
599       // send attach message
600       sw_printf("[%s:%u] - Attaching to pid %d, thread %d\n", __FILE__, __LINE__, pid, tid);
601       bool result = BG_Debugger_Msg::writeOnFd(BG_DEBUGGER_WRITE_PIPE, msg);
602       if (!result) {
603         sw_printf("[%s:%u] - Error sending attach to process %d, thread %d\n",
604                   __FILE__, __LINE__, pid, tid);
605       }
606        
607       return result;
608     }
609
610
611     bool ProcDebugBG::detach(bool /* leave_stopped */) {
612       // TODO: send detach message
613       return true;
614     }
615
616
617     bool ProcDebugBG::debug_pause(ThreadState *ts)
618     {
619       THR_ID tid = initial_thread->getTid();  // default to initial thread.
620       if (ts) tid = ts->getTid();
621
622       BG_Debugger_Msg msg(KILL, pid, tid, 0, 0);
623       msg.dataArea.KILL.signal = SIGSTOP;
624       msg.header.dataLength = sizeof(msg.dataArea.KILL);
625       
626       sw_printf("[%s:%u] - Sending SIGSTOP to pid %d, thread %d\n", __FILE__, __LINE__, pid, tid);
627       bool result = BG_Debugger_Msg::writeOnFd(BG_DEBUGGER_WRITE_PIPE, msg);
628       if (!result) {
629         sw_printf("[%s:%u] - Unable to send SIGSTOP to process %d, thread\n", __FILE__, __LINE__, pid, tid);
630       }
631       return result;
632     }
633
634
635     bool ProcDebugBG::debug_continue_with(ThreadState *ts, long sig)
636     {
637       THR_ID tid = ts->getTid();
638       if (!ts->isStopped()) {
639         sw_printf("[%s:%u] - Error in debug_continue_with(): pid %d, thread %d not stopped.\n",
640                   __FILE__, __LINE__, pid, tid);
641         return false;
642       }
643
644       BG_Debugger_Msg msg(CONTINUE, pid, tid, 0, 0);
645       msg.dataArea.CONTINUE.signal = sig;
646       msg.header.dataLength = sizeof(msg.dataArea.CONTINUE);
647
648       sw_printf("[%s:%u] - Sending signal %d to pid %d, thread %d\n", __FILE__, __LINE__, sig, pid, tid);
649       bool result = BG_Debugger_Msg::writeOnFd(BG_DEBUGGER_WRITE_PIPE, msg);
650       if (!result) {
651         sw_printf("[%s:%u] - Unable to send %d to process %d, thread %d\n", __FILE__, __LINE__, sig, pid, tid);
652       }
653       return result;
654     }
655
656
657     bool ProcDebugBG::getRegValue(MachRegister reg, THR_ID tid, MachRegisterVal &val) {
658       assert(threads.count(tid));
659       BGThreadState *thr = dynamic_cast<BGThreadState*>(threads[tid]);
660
661       if (!thr->gprs_set) {
662         BG_Debugger_Msg msg(GET_ALL_REGS, pid, tid, 0, 0);
663         msg.header.dataLength = sizeof(msg.dataArea.GET_ALL_REGS);
664
665         bool result = BG_Debugger_Msg::writeOnFd(BG_DEBUGGER_WRITE_PIPE, msg);
666         if (!result) {
667           sw_printf("[%s:%u] - Unable to write to process %d, thread %d\n",
668                     __FILE__, __LINE__, pid, tid);
669           return true;
670         }
671       
672         //Wait for the read to return
673         sw_printf("[%s:%u] - Waiting for read to return on pid %d, tid %d\n",
674                   __FILE__, __LINE__, pid, tid);
675         
676         do {
677           bool handled, result;
678           result = debug_wait_and_handle(true, false, handled);
679           if (!result)
680           {
681             sw_printf("[%s:%u] - Error while waiting for read to return\n",
682                       __FILE__, __LINE__);
683             return false;
684           }
685         } while (!thr->gprs_set);
686       }
687    
688       switch(reg)
689       {
690       case Dyninst::MachRegStackBase:
691         val = 0x0;
692         break;
693       case Dyninst::MachRegFrameBase:
694         val = thr->gprs.gpr[BG_GPR1];
695         break;
696       case Dyninst::MachRegPC:
697         val = thr->gprs.iar;
698         break;
699       default:
700         sw_printf("[%s:%u] - Request for unsupported register %d\n", __FILE__, __LINE__, reg);
701         setLastError(err_badparam, "Unknown register passed in reg field");
702         return false;
703       }   
704       return true;
705     }
706
707
708     bool ProcDebugBG::readMem(void *dest, Address source, size_t size)
709     {
710       unsigned char *ucdest = (unsigned char *) dest;
711       bool result;
712
713       for (;;)
714       {
715         if (size == 0)
716           return true;
717
718         sw_printf("[%s:%u] - Reading memory from 0x%lx to 0x%lx (into %p)\n",
719                   __FILE__, __LINE__, source, source+size, ucdest);
720         if (source >= read_cache_start && 
721             source+size < read_cache_start + read_cache_size)
722         {
723           //Lucky us, we have everything cached.
724           memcpy(ucdest, read_cache + (source - read_cache_start), size);
725           return true;
726         }
727         if (source >= read_cache_start &&
728             source < read_cache_start + read_cache_size)
729         {
730           //The beginning is in the cache, read those bytes
731           long cached_bytes = read_cache_start + read_cache_size - source;
732           memcpy(ucdest, read_cache + (source - read_cache_start), cached_bytes);
733           //Change the parameters and continue the read (this is a kind of
734           // optimized tail call).
735           ucdest += cached_bytes;
736           source = read_cache_start + read_cache_size;
737           size -= cached_bytes;
738           continue;
739         }
740         if (source+size > read_cache_start &&
741             source+size <= read_cache_start + read_cache_size)
742         {
743           //The end is in the cache, read those bytes
744           long cached_bytes = (source+size) - read_cache_start;
745           memcpy(ucdest + read_cache_start - source, read_cache, cached_bytes);
746           //Change the parameters and continue the read (this is a kind of
747           // optimized tail call).
748           size -= cached_bytes;
749           continue;
750         }
751         if (source < read_cache_start &&
752             source+size >= read_cache_start+read_cache_size)
753         {
754           //The middle is in the cache
755           unsigned char *dest_start = ucdest + read_cache_start - source;
756           Address old_read_cache_start = read_cache_start;
757           memcpy(dest_start, read_cache, read_cache_size);
758           //Use actual recursion here, as we need to queue up two reads
759           // First read out of the high memory with recursion
760           result = readMem(dest_start + read_cache_size, 
761                            read_cache_start+read_cache_size,
762                            source+size - read_cache_start+read_cache_size);
763           if (!result) {
764             return false;
765           }
766           // Now read out of the low memory
767           size = old_read_cache_start - source;
768           continue;
769         }
770         //The memory isn't cached, read a new cache'd page.
771         assert(source < read_cache_start || 
772                source >= read_cache_start+read_cache_size);
773       
774         if (!read_cache) {
775           read_cache = new unsigned char[BG_READCACHE_SIZE];
776           assert(read_cache);
777         }
778
779         read_cache_size = BG_READCACHE_SIZE;
780         read_cache_start = source - (source % read_cache_size);
781         sw_printf("[%s:%u] - Caching memory from 0x%lx to 0x%lx\n",
782                   __FILE__, __LINE__, read_cache_start, 
783                   read_cache_start+read_cache_size);
784                     
785         //Read read_cache_start to read_cache_start+read_cache_size into our
786         // cache.
787         assert(!mem_data);
788         assert(read_cache_size < BG_Debugger_Msg_MAX_MEM_SIZE);
789
790         BG_Debugger_Msg msg(GET_MEM, pid, 0, 0, 0);
791         msg.header.dataLength = sizeof(msg.dataArea.GET_MEM);
792         msg.dataArea.GET_MEM.addr = read_cache_start;
793         msg.dataArea.GET_MEM.len = read_cache_size;
794         bool result = BG_Debugger_Msg::writeOnFd(BG_DEBUGGER_WRITE_PIPE, msg);
795         if (!result) {
796           sw_printf("[%s:%u] - Unable to write to process %d\n", __FILE__, __LINE__, pid);
797           return true;
798         }
799       
800         //Wait for the read to return
801         sw_printf("[%s:%u] - Waiting for read to return on pid %d\n", __FILE__, __LINE__);
802
803         if (!debug_waitfor(dbg_mem_ack)) {
804           sw_printf("[%s:%u] - Error while waiting for read to return\n", __FILE__, __LINE__);
805           return false;
806         }
807
808         sw_printf("[%s:%u] - Asserting mem_data post-read.\n", __FILE__, __LINE__);
809         assert(mem_data->GET_MEM_ACK.addr == read_cache_start);
810         assert(mem_data->GET_MEM_ACK.len == read_cache_size);
811         memcpy(read_cache, mem_data->GET_MEM_ACK.data, read_cache_size);
812       
813         //Free up the memory data
814         delete mem_data;
815         mem_data = NULL;
816       }
817     }   
818
819
820     bool ProcDebugBG::debug_version_msg()
821     {
822       BG_Debugger_Msg msg(VERSION_MSG, pid, 0, 0, 0);
823       msg.header.dataLength = sizeof(msg.dataArea.VERSION_MSG);
824
825       sw_printf("[%s:%u] - Sending VERSION_MSG to pid %d\n", __FILE__, __LINE__, pid);
826       bool result = BG_Debugger_Msg::writeOnFd(BG_DEBUGGER_WRITE_PIPE, msg);
827
828       if (!result) {
829         sw_printf("[%s:%u] - Unable to send VERSION_MSG to process %d\n",
830                   __FILE__, __LINE__, pid);
831         return false;
832       }
833       return true;
834     }
835
836
837     // ============================================================ //
838     // SigHandlerStepper -- unsupported.  All stubs.
839     // ============================================================ //
840 #   define sig_handler_stepper_unsupported(file, line) \
841       sw_printf("[%s:%u] - Error, signal handler walker used on unsupported platform\n", file, line); \
842       setLastError(err_unsupported, "Signal handling walking not supported on this platform");
843
844     SigHandlerStepper::SigHandlerStepper(Walker *w) :
845       FrameStepper(w) {
846       sig_handler_stepper_unsupported(__FILE__, __LINE__);
847       assert(0);
848     }
849
850     gcframe_ret_t SigHandlerStepper::getCallerFrame(const Frame &, Frame &) {
851       sig_handler_stepper_unsupported(__FILE__, __LINE__);
852       return gcf_error;
853     }
854     
855     unsigned SigHandlerStepper::getPriority() const {
856       sig_handler_stepper_unsupported(__FILE__, __LINE__);
857       return 0;
858     }
859     
860     void SigHandlerStepper::registerStepperGroup(StepperGroup *) {
861       sig_handler_stepper_unsupported(__FILE__, __LINE__);
862     }
863     
864     SigHandlerStepper::~SigHandlerStepper() { 
865       sig_handler_stepper_unsupported(__FILE__, __LINE__);
866     }
867     
868
869     // ============================================================ //
870     // SymtabLibState -- need to differentiate for P
871     // ============================================================ //
872     bool SymtabLibState::updateLibsArch() {
873       return true;
874     }
875
876
877     // ============================================================ //
878     // ThreadState
879     // ============================================================ //
880     ThreadState* ThreadState::createThreadState(ProcDebug *parent, Dyninst::THR_ID tid, bool) {
881       THR_ID thread_id = tid;
882       if (thread_id == NULL_THR_ID) {
883         thread_id = 0;
884       }
885       BGThreadState *ts = new BGThreadState(parent, thread_id);
886       return ts;
887     }
888
889   } // namespace Stackwalker
890 } // namespace Dyninst
891