Suppress debug message when no vsyscall page was found on arm64
[dyninst.git] / stackwalk / src / bluegenep-swk.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30 #include "stackwalk/src/bluegenep-swk.h"
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 #include "stackwalk/h/procstate.h"
37 #include "stackwalk/src/symtab-swk.h"
38 #include "stackwalk/src/dbgstepper-impl.h"
39
40 #include "get_trap_instruction.h"
41
42 #include <string>
43 #include <algorithm>
44
45 #include <string.h>
46 #include <sys/syscall.h>
47 #include <unistd.h>
48 #include <errno.h>
49 #include <signal.h>
50 #include <sys/poll.h>
51 #include <assert.h>
52
53 using namespace Dyninst;
54 using namespace Dyninst::Stackwalker;
55 using namespace DebuggerInterface;
56 using namespace std;
57
58 namespace Dyninst {
59   namespace Stackwalker {
60     
61     // ============================================================ //
62     // ProcDebugBG
63     // This is the factor function that initially creates a BGP stackwalker.
64     // ============================================================ //
65     ProcDebug *ProcDebugBG::createProcDebugBG(PID pid, string executable) {
66       return new ProcDebugBGP(pid, executable);
67     }
68
69     
70     // ============================================================ //
71     // ProcDebugBGP
72     // ============================================================ //
73     ProcDebugBGP::ProcDebugBGP(PID pid, string exe) 
74       : ProcDebugBG(pid, exe),
75         lib_load_trap(0) { }
76     
77     ProcDebugBGP::~ProcDebugBGP() { }
78
79
80     // this is based on the linux version.  BG/P uses Linux SysV dynamic libs
81     bool ProcDebugBGP::debug_post_attach(ThreadState *) {
82       sw_printf("[%s:%u] - Entering debug_post_attach on %d\n", FILE__, __LINE__, pid);
83
84       pollForNewThreads();
85
86       // make new thread states identical to the initial thread, since BG has no 
87       // asynchronous thread control.  They should all be doing the same thing.
88       for (thread_map_t::iterator i=threads.begin(); i != threads.end(); i++) {
89         ThreadState *ts = i->second;
90         if (ts->state() == ps_neonatal) {  // only do this to new threads.
91           copy_thread_state(initial_thread, ts);
92         }
93       }
94
95       if (!library_tracker)
96          setDefaultLibraryTracker();
97       // This should really be checking for exceptions, since the above are constructors.
98       if (!library_tracker) {
99         sw_printf("[%s:%u] - PID %d failed to create library tracker\n", FILE__, __LINE__, pid);
100         setLastError(err_nolibtracker, "Failed to create library tracker!");
101         return false;
102       }
103
104       sw_printf("[%s:%u] - PID %d registering lib spotter...\n", FILE__, __LINE__, pid);
105       registerLibSpotter();
106       sw_printf("[%s:%u] - PID %d registered lib spotter successfully\n", FILE__, __LINE__, pid);
107       return true;
108     }
109
110
111     //
112     // Dynamic library methods
113     //
114     bool ProcDebugBGP::isLibraryTrap(Dyninst::THR_ID thrd) {
115       LibraryState *ls = getLibraryTracker();
116       if (!ls)
117         return false;
118       Address lib_trap_addr = ls->getLibTrapAddress();
119       if (!lib_trap_addr)
120         return false;
121       
122       Dyninst::MachRegisterVal cur_pc;
123       bool result = getRegValue(Dyninst::ReturnAddr, thrd, cur_pc);
124       if (!result) {
125         sw_printf("[%s:%u] - Error getting PC value for thrd %d\n",
126                   FILE__, __LINE__, (int) thrd);
127         return false;
128       }
129       if (cur_pc == lib_trap_addr || cur_pc-1 == lib_trap_addr)
130         return true;
131       return false;
132     }
133
134     bool ProcDebugBGP::cleanOnDetach() {
135       bool result = pause();
136       if (!result) {
137         sw_printf("[%s:%u] - Failed to pause process for detach clean\n");
138       }
139
140       if (!wrote_trap)
141       {
142          sw_printf("[%s:%u] - Skipping trap clean\n", FILE__, __LINE__);
143          return true;
144       }
145
146       lib_load_trap = library_tracker->getLibTrapAddress();
147       if (!lib_load_trap) {
148         sw_printf("[%s:%u] - Couldn't get trap addr, couldn't set up "
149                   "library loading notification.\n", FILE__, __LINE__);
150         return false;
151       }
152
153       // construct a bg debugger msg to clean out the trap 
154       BG_Debugger_Msg write_trap_msg(SET_MEM, pid, 0, 0, 0);
155       write_trap_msg.header.dataLength = sizeof(write_trap_msg.dataArea.SET_MEM);
156       memcpy(write_trap_msg.dataArea.SET_MEM.data, lib_trap_orig_mem, trap_len);
157       write_trap_msg.dataArea.SET_MEM.addr = lib_load_trap;
158       write_trap_msg.dataArea.SET_MEM.len  = trap_len;
159
160       sw_printf("[%s:%u] - Restoring memory over library trap at %lx\n", 
161                   FILE__, __LINE__, lib_load_trap);
162       write_ack = false;
163       if (!BG_Debugger_Msg::writeOnFd(BG_DEBUGGER_WRITE_PIPE, write_trap_msg))
164       {
165         sw_printf("[%s:%u] - Couldn't write BG trap at load address: %lx\n", 
166                   FILE__, __LINE__, lib_load_trap);
167         return false;
168       }
169
170       bool handled;
171       while (!write_ack) {
172         result = debug_wait_and_handle(true, false, handled);
173         if (result) {
174           sw_printf("[%s:%u] - Unable to get ack for setmem in " 
175                     "registerLibSpotter()\n", FILE__, __LINE__);
176           break;
177         }
178       }
179       
180       return true;
181     }
182
183     void ProcDebugBGP::registerLibSpotter() 
184     {
185       if (lib_load_trap)
186         return;
187
188       if (!library_tracker) {
189         sw_printf("[%s:%u] - Not using lib tracker, don't know how "
190                   "to get library load address\n", FILE__, __LINE__);
191         return;
192       }
193    
194       lib_load_trap = library_tracker->getLibTrapAddress();
195       if (!lib_load_trap) {
196         sw_printf("[%s:%u] - Couldn't get trap addr, couldn't set up "
197                   "library loading notification.\n", FILE__, __LINE__);
198         return;
199       }
200
201       // construct a bg debugger msg to install a trap instruction at the loader trap address.
202       BG_Debugger_Msg write_trap_msg(SET_MEM, pid, 0, 0, 0);
203
204       getTrapInstruction((char*)write_trap_msg.dataArea.SET_MEM.data,
205                          BG_Debugger_Msg_MAX_MEM_SIZE, trap_len, true);
206       write_trap_msg.header.dataLength = sizeof(write_trap_msg.dataArea.SET_MEM);
207       write_trap_msg.dataArea.SET_MEM.addr = lib_load_trap;
208       write_trap_msg.dataArea.SET_MEM.len  = trap_len;
209
210       sw_printf("[%s:%u] - Reading original memory at library trap\n",
211                 FILE__, __LINE__);
212       assert(trap_len <= sizeof(lib_trap_orig_mem));
213       memset(lib_trap_orig_mem, 0, sizeof(lib_trap_orig_mem));
214       bool result = readMem(lib_trap_orig_mem, lib_load_trap, trap_len);
215       if (!result) {
216         sw_printf("Failed to read memory for library trap\n");
217         return;
218       }
219
220       sw_printf("[%s:%u] - Installing BG trap at load address: %lx\n", 
221                   FILE__, __LINE__, lib_load_trap);
222       write_ack = false;
223       if (!BG_Debugger_Msg::writeOnFd(BG_DEBUGGER_WRITE_PIPE, write_trap_msg))
224       {
225         sw_printf("[%s:%u] - Couldn't write BG trap at load address: %lx\n", 
226                   FILE__, __LINE__, lib_load_trap);
227         return;
228       }
229
230       bool handled;
231       while (!write_ack) {
232         result = debug_wait_and_handle(true, false, handled);
233         if (result) {
234         sw_printf("[%s:%u] - Unable to get ack for setmem in registerLibSpotter()\n", FILE__, __LINE__);
235           break;
236         }
237       }
238  
239       wrote_trap = true;
240       sw_printf("[%s:%u] - Successfully wrote BG library trap at %lx\n",
241                 FILE__, __LINE__, lib_load_trap);
242     }
243
244
245
246     //
247     // Threading methods
248     //
249     bool ProcDebugBGP::getThreadIds(std::vector<THR_ID> &output) {
250       output.clear();
251       transform(threads.begin(), threads.end(), back_inserter(output), get_first());
252       return true;
253     }
254
255
256     bool ProcDebugBGP::pollForNewThreads() {
257       sw_printf("[%s:%u] - Polling for new threads on %d\n", FILE__, __LINE__, pid);
258
259       // send a request for thread info to the BG debugger pipe
260       BG_Debugger_Msg get_info_msg(GET_THREAD_INFO, pid, 0, 0, 0);
261       get_info_msg.header.dataLength = sizeof(get_info_msg.dataArea.GET_THREAD_INFO);
262
263       if (!BG_Debugger_Msg::writeOnFd(BG_DEBUGGER_WRITE_PIPE, get_info_msg)) {
264         sw_printf("[%s:%u] - Error writing GET_THREAD_INFO to BG debug stream.\n", 
265                   FILE__, __LINE__);
266         setLastError(err_procread, "Failed to write GET_THREAD_INFO request.");
267         return false;
268       }
269       
270       // get a get_thread_info_ack from the read pipe, but do it through the 
271       // stackwalker debug interface.
272       if (!debug_waitfor(dbg_thread_info)) {
273         sw_printf("[%s:%u] - Unable to get ack for GET_THREAD_INFO in pollForNewThreads()\n", 
274                   FILE__, __LINE__);
275       }
276
277       return true;
278     }
279
280
281     void ProcDebugBGP::translate_event(const BG_Debugger_Msg& msg, DebugEvent& ev) {
282       ThreadState *ts = ev.thr;
283       switch (msg.header.messageType) {
284       case SIGNAL_ENCOUNTERED:
285         // this is special handling for library loads, which we'll only see on BGP
286         ev.data.idata = msg.dataArea.SIGNAL_ENCOUNTERED.signal;
287         if (ev.data.idata == SIGTRAP && isLibraryTrap(ts->getTid())) {
288           ev.dbg = dbg_libraryload;
289           sw_printf("[%s:%u] - Decoded library load event\n", FILE__, __LINE__);
290         } else {
291           ProcDebugBG::translate_event(msg, ev);
292         }
293         break;        
294
295       case GET_THREAD_INFO_ACK:
296         {
297           ev.dbg = dbg_thread_info;
298           ev.size = msg.dataArea.GET_THREAD_INFO_ACK.numThreads;
299           ev.data.pdata = new uint32_t[ev.size];
300
301           const uint32_t *msg_ids = msg.dataArea.GET_THREAD_INFO_ACK.threadIDS;
302           uint32_t *dest = (uint32_t*)ev.data.pdata;
303           copy(&msg_ids[0], &msg_ids[ev.size], dest);
304
305           sw_printf("[%s:%u] - Received thread info: ", FILE__, __LINE__);
306           for (size_t i=0; i < ev.size; i++) sw_printf("%d ", msg_ids[i]);
307           sw_printf("\n");
308         }
309         break;
310
311       default:
312         // delegate other events to base class
313         ProcDebugBG::translate_event(msg, ev);
314       }
315     }
316
317
318     bool ProcDebugBGP::debug_handle_event(DebugEvent ev) {
319       ThreadState *ts = ev.thr;
320       THR_ID tid = ts->getTid();
321       
322       switch (ev.dbg) {
323       case dbg_libraryload:
324         {
325           sw_printf("[%s:%u] - Handling library load event on %d/%d\n", FILE__, __LINE__, pid, tid);
326           for_all_threads(set_stopped(true));
327           LibraryState *ls = getLibraryTracker();
328           if (!ls) {
329             sw_printf("[%s:%u] - WARNING! No library tracker registered on %d/%d\n", 
330                       FILE__, __LINE__, pid, tid);
331             setLastError(err_nolibtracker, "No library tracker found!");
332             return false;
333           }
334           ls->notifyOfUpdate();
335           
336           /**
337            * Forward over the trap instructoin
338            **/
339           Dyninst::MachRegisterVal newpc = ls->getLibTrapAddress() + 4;
340           bool result = setRegValue(Dyninst::ReturnAddr, tid, newpc);
341           if (!result) {
342             sw_printf("[%s:%u] - Error! Could not set PC past trap!\n",
343                       FILE__, __LINE__);
344             setLastError(err_internal, "Could not set PC after trap\n");
345             return false;
346           }
347           
348           if (!debug_continue(ts)) {
349             sw_printf("[%s:%u] - Debug continue failed on %d/%d with %d\n", 
350                       FILE__, __LINE__, pid, tid, ev.data.idata);
351             setLastError(err_internal, "debug_continue() failed after library load.");
352             return false;
353           }
354           return true;
355         }    
356         break;
357
358       case dbg_thread_info:
359         {
360           // Create threads for new ids now that we're actually handling thread_info message.
361           uint32_t *ids = (uint32_t*)ev.data.pdata;
362           bool result = add_new_threads(&ids[0], &ids[ev.size]);
363           delete [] ids;
364           return result;
365         }
366         break;
367
368       default:
369         // delegate other events to base class
370         return ProcDebugBG::debug_handle_event(ev);
371       };
372     }
373
374
375     // ============================================================ //
376     // DebugStepperImpl
377     // ============================================================ //
378     bool DebugStepperImpl::isFrameRegister(MachRegister) {
379       return false;            // ppc has no frame pointer register.
380     }
381     
382     bool DebugStepperImpl::isStackRegister(MachRegister reg) {
383       return reg == BG_GPR1;   // by convention.
384     }
385
386   } // namespace Stackwalker
387 } // namespace Dyninst
388
389