Update copyright to LGPL on all files
[dyninst.git] / stackwalk / src / bluegenep-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 #include "stackwalk/src/bluegenep-swk.h"
32
33 #include "stackwalk/h/swk_errors.h"
34 #include "stackwalk/h/symlookup.h"
35 #include "stackwalk/h/walker.h"
36 #include "stackwalk/h/framestepper.h"
37 #include "stackwalk/h/procstate.h"
38 #include "stackwalk/src/symtab-swk.h"
39 #include "stackwalk/src/dbgstepper-impl.h"
40
41 #include "get_trap_instruction.h"
42
43 #include <string>
44 #include <algorithm>
45
46 #include <string.h>
47 #include <sys/syscall.h>
48 #include <unistd.h>
49 #include <errno.h>
50 #include <signal.h>
51 #include <sys/poll.h>
52 #include <assert.h>
53
54 using namespace Dyninst;
55 using namespace Dyninst::Stackwalker;
56 using namespace DebuggerInterface;
57 using namespace std;
58
59 namespace Dyninst {
60   namespace Stackwalker {
61     
62     // ============================================================ //
63     // ProcDebugBG
64     // This is the factor function that initially creates a BGP stackwalker.
65     // ============================================================ //
66     ProcDebug *ProcDebugBG::createProcDebugBG(PID pid, const string& executable) {
67       return new ProcDebugBGP(pid, executable);
68     }
69
70     
71     // ============================================================ //
72     // ProcDebugBGP
73     // ============================================================ //
74     ProcDebugBGP::ProcDebugBGP(PID pid, string exe) 
75       : ProcDebugBG(pid, exe),
76         lib_load_trap(0) { }
77     
78     ProcDebugBGP::~ProcDebugBGP() { }
79
80
81     // this is based on the linux version.  BG/P uses Linux SysV dynamic libs
82     bool ProcDebugBGP::debug_post_attach(ThreadState *) {
83       sw_printf("[%s:%u] - Entering debug_post_attach on %d\n", __FILE__, __LINE__, pid);
84
85       pollForNewThreads();
86
87       // make new thread states identical to the initial thread, since BG has no 
88       // asynchronous thread control.  They should all be doing the same thing.
89       for (thread_map_t::iterator i=threads.begin(); i != threads.end(); i++) {
90         ThreadState *ts = i->second;
91         if (ts->state() == ps_neonatal) {  // only do this to new threads.
92           copy_thread_state(initial_thread, ts);
93         }
94       }
95
96       sw_printf("[%s:%u] - Successfully polled for threads in debug_post_attach on %d\n", __FILE__, __LINE__, pid);      
97 #   if defined(cap_stackwalker_use_symtab)
98       library_tracker = new SymtabLibState(this, executable_path);
99 #   else
100       library_tracker = new DefaultLibState(this);
101 #   endif
102
103       // This should really be checking for exceptions, since the above are constructors.
104       if (!library_tracker) {
105         sw_printf("[%s:%u] - PID %d failed to create library tracker\n", __FILE__, __LINE__, pid);
106         setLastError(err_nolibtracker, "Failed to create library tracker!");
107         return false;
108       }
109
110       sw_printf("[%s:%u] - PID %d registering lib spotter...\n", __FILE__, __LINE__, pid);
111       registerLibSpotter();
112       sw_printf("[%s:%u] - PID %d registered lib spotter successfully\n", __FILE__, __LINE__, pid);
113       return true;
114     }
115
116
117     //
118     // Dynamic library methods
119     //
120     bool ProcDebugBGP::isLibraryTrap(Dyninst::THR_ID thrd) {
121       LibraryState *ls = getLibraryTracker();
122       if (!ls)
123         return false;
124       Address lib_trap_addr = ls->getLibTrapAddress();
125       if (!lib_trap_addr)
126         return false;
127       
128       Dyninst::MachRegisterVal cur_pc;
129       bool result = getRegValue(Dyninst::MachRegPC, thrd, cur_pc);
130       if (!result) {
131         sw_printf("[%s:%u] - Error getting PC value for thrd %d\n",
132                   __FILE__, __LINE__, (int) thrd);
133         return false;
134       }
135       if (cur_pc == lib_trap_addr || cur_pc-1 == lib_trap_addr)
136         return true;
137       return false;
138     }
139
140
141     void ProcDebugBGP::registerLibSpotter() 
142     {
143       if (lib_load_trap)
144         return;
145
146       if (!library_tracker) {
147         sw_printf("[%s:%u] - Not using lib tracker, don't know how "
148                   "to get library load address\n", __FILE__, __LINE__);
149         return;
150       }
151    
152       lib_load_trap = library_tracker->getLibTrapAddress();
153       if (!lib_load_trap) {
154         sw_printf("[%s:%u] - Couldn't get trap addr, couldn't set up "
155                   "library loading notification.\n", __FILE__, __LINE__);
156         return;
157       }
158
159       // construct a bg debugger msg to install a trap instruction at the loader trap address.
160       unsigned trap_len;
161       BG_Debugger_Msg write_trap_msg(SET_MEM, pid, 0, 0, 0);
162
163       getTrapInstruction((char*)write_trap_msg.dataArea.SET_MEM.data,
164                          BG_Debugger_Msg_MAX_MEM_SIZE, trap_len, true);
165       write_trap_msg.header.dataLength = sizeof(write_trap_msg.dataArea.SET_MEM);
166       write_trap_msg.dataArea.SET_MEM.addr = lib_load_trap;
167       write_trap_msg.dataArea.SET_MEM.len  = trap_len;
168
169       sw_printf("[%s:%u] - Installing BG trap at load address: %lx\n", 
170                   __FILE__, __LINE__, lib_load_trap);
171
172       if (!BG_Debugger_Msg::writeOnFd(BG_DEBUGGER_WRITE_PIPE, write_trap_msg)) {
173         sw_printf("[%s:%u] - Couldn't write BG trap at load address: %lx\n", 
174                   __FILE__, __LINE__, lib_load_trap);
175         return;
176       }
177
178       bool handled;
179       if (!debug_wait_and_handle(true, false, handled) && handled) {
180         sw_printf("[%s:%u] - Unable to get ack for setmem in registerLibSpotter()\n", __FILE__, __LINE__);
181       }
182       
183       sw_printf("[%s:%u] - Successfully wrote BG library trap at %lx\n",
184                 __FILE__, __LINE__, lib_load_trap);
185     }
186
187
188
189     //
190     // Threading methods
191     //
192     bool ProcDebugBGP::getThreadIds(std::vector<THR_ID> &output) {
193       output.clear();
194       transform(threads.begin(), threads.end(), back_inserter(output), get_first());
195       return true;
196     }
197
198
199     bool ProcDebugBGP::pollForNewThreads() {
200       sw_printf("[%s:%u] - Polling for new threads on %d\n", __FILE__, __LINE__, pid);
201
202       // send a request for thread info to the BG debugger pipe
203       BG_Debugger_Msg get_info_msg(GET_THREAD_INFO, pid, 0, 0, 0);
204       get_info_msg.header.dataLength = sizeof(get_info_msg.dataArea.GET_THREAD_INFO);
205
206       if (!BG_Debugger_Msg::writeOnFd(BG_DEBUGGER_WRITE_PIPE, get_info_msg)) {
207         sw_printf("[%s:%u] - Error writing GET_THREAD_INFO to BG debug stream.\n", 
208                   __FILE__, __LINE__);
209         setLastError(err_procread, "Failed to write GET_THREAD_INFO request.");
210         return false;
211       }
212       
213       // get a get_thread_info_ack from the read pipe, but do it through the 
214       // stackwalker debug interface.
215       if (!debug_waitfor(dbg_thread_info)) {
216         sw_printf("[%s:%u] - Unable to get ack for GET_THREAD_INFO in pollForNewThreads()\n", 
217                   __FILE__, __LINE__);
218       }
219
220       return true;
221     }
222
223
224     void ProcDebugBGP::translate_event(const BG_Debugger_Msg& msg, DebugEvent& ev) {
225       ThreadState *ts = ev.thr;
226
227       switch (msg.header.messageType) {
228       case SIGNAL_ENCOUNTERED:
229         // this is special handling for library loads, which we'll only see on BGP
230         if (ev.data.idata == SIGTRAP && state() == ps_running && isLibraryTrap(ts->getTid())) {
231           ev.dbg = dbg_libraryload;
232           sw_printf("[%s:%u] - Decoded library load event\n", __FILE__, __LINE__);
233         } else {
234           ProcDebugBG::translate_event(msg, ev);
235         }
236         break;        
237
238       case GET_THREAD_INFO_ACK:
239         {
240           ev.dbg = dbg_thread_info;
241           ev.size = msg.dataArea.GET_THREAD_INFO_ACK.numThreads;
242           ev.data.pdata = new uint32_t[ev.size];
243
244           const uint32_t *msg_ids = msg.dataArea.GET_THREAD_INFO_ACK.threadIDS;
245           uint32_t *dest = (uint32_t*)ev.data.pdata;
246           copy(&msg_ids[0], &msg_ids[ev.size], dest);
247
248           sw_printf("[%s:%u] - Received thread info: ", __FILE__, __LINE__);
249           for (size_t i=0; i < ev.size; i++) sw_printf("%d ", msg_ids[i]);
250           sw_printf("\n");
251         }
252         break;
253
254       default:
255         // delegate other events to base class
256         ProcDebugBG::translate_event(msg, ev);
257       }
258     }
259
260
261     bool ProcDebugBGP::debug_handle_event(DebugEvent ev) {
262       ThreadState *ts = ev.thr;
263       THR_ID tid = ts->getTid();
264       
265       switch (ev.dbg) {
266       case dbg_libraryload:
267         {
268           sw_printf("[%s:%u] - Handling library load event on %d/%d\n", __FILE__, __LINE__, pid, tid);
269           for_all_threads(set_stopped(true));
270           LibraryState *ls = getLibraryTracker();
271           if (!ls) {
272             sw_printf("[%s:%u] - WARNING! No library tracker registered on %d/%d\n", 
273                       __FILE__, __LINE__, pid, tid);
274             setLastError(err_nolibtracker, "No library tracker found!");
275             return false;
276           }
277           ls->notifyOfUpdate();
278           
279           if (!debug_continue(ts)) {
280             sw_printf("[%s:%u] - Debug continue failed on %d/%d with %d\n", 
281                       __FILE__, __LINE__, pid, tid, ev.data.idata);
282             setLastError(err_internal, "debug_continue() failed after library load.");
283             return false;
284           }
285           return true;
286         }    
287         break;
288
289       case dbg_thread_info:
290         {
291           // Create threads for new ids now that we're actually handling thread_info message.
292           uint32_t *ids = (uint32_t*)ev.data.pdata;
293           bool result = add_new_threads(&ids[0], &ids[ev.size]);
294           delete [] ids;
295           return result;
296         }
297         break;
298
299       default:
300         // delegate other events to base class
301         return ProcDebugBG::debug_handle_event(ev);
302       };
303     }
304
305
306     // ============================================================ //
307     // DebugStepperImpl
308     // ============================================================ //
309     bool DebugStepperImpl::isFrameRegister(MachRegister) {
310       return false;            // ppc has no frame pointer register.
311     }
312     
313     bool DebugStepperImpl::isStackRegister(MachRegister reg) {
314       return reg == BG_GPR1;   // by convention.
315     }
316
317   } // namespace Stackwalker
318 } // namespace Dyninst
319
320