source: mainline/kernel/generic/src/udebug/udebug_ipc.c@ 336db295

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 336db295 was 336db295, checked in by Jiri Svoboda <jiri@…>, 15 years ago

Fix THREAD_READ, add AREAS_READ Udebug method. Add task dump utility.

  • Property mode set to 100644
File size: 9.2 KB
RevLine 
[9a1b20c]1/*
2 * Copyright (c) 2008 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup generic
30 * @{
31 */
32
33/**
34 * @file
35 * @brief Udebug IPC message handling.
[7dc62af]36 *
37 * This module handles udebug IPC messages and calls the appropriate
38 * functions from the udebug_ops module which implement them.
[9a1b20c]39 */
40
41#include <proc/task.h>
42#include <proc/thread.h>
[336db295]43#include <mm/as.h>
[9a1b20c]44#include <arch.h>
45#include <errno.h>
46#include <ipc/ipc.h>
47#include <syscall/copy.h>
48#include <udebug/udebug.h>
49#include <udebug/udebug_ops.h>
50#include <udebug/udebug_ipc.h>
51
52int udebug_request_preprocess(call_t *call, phone_t *phone)
53{
54 switch (IPC_GET_ARG1(call->data)) {
55 /* future UDEBUG_M_REGS_WRITE, UDEBUG_M_MEM_WRITE: */
56 default:
57 break;
58 }
59
60 return 0;
61}
62
[3926f30]63/** Process a BEGIN call.
64 *
65 * Initiates a debugging session for the current task. The reply
66 * to this call may or may not be sent before this function returns.
67 *
68 * @param call The call structure.
69 */
[9a1b20c]70static void udebug_receive_begin(call_t *call)
71{
72 int rc;
73
74 rc = udebug_begin(call);
75 if (rc < 0) {
76 IPC_SET_RETVAL(call->data, rc);
[31696b4f]77 ipc_answer(&TASK->kb.box, call);
[9a1b20c]78 return;
79 }
80
[3926f30]81 /*
82 * If the initialization of the debugging session has finished,
83 * send a reply.
84 */
[9a1b20c]85 if (rc != 0) {
86 IPC_SET_RETVAL(call->data, 0);
[31696b4f]87 ipc_answer(&TASK->kb.box, call);
[9a1b20c]88 }
89}
90
[3926f30]91/** Process an END call.
92 *
93 * Terminates the debugging session for the current task.
94 * @param call The call structure.
95 */
[9a1b20c]96static void udebug_receive_end(call_t *call)
97{
98 int rc;
99
100 rc = udebug_end();
101
102 IPC_SET_RETVAL(call->data, rc);
[31696b4f]103 ipc_answer(&TASK->kb.box, call);
[9a1b20c]104}
105
[3926f30]106/** Process a SET_EVMASK call.
107 *
108 * Sets an event mask for the current debugging session.
109 * @param call The call structure.
110 */
[9a1b20c]111static void udebug_receive_set_evmask(call_t *call)
112{
113 int rc;
114 udebug_evmask_t mask;
115
116 mask = IPC_GET_ARG2(call->data);
117 rc = udebug_set_evmask(mask);
118
119 IPC_SET_RETVAL(call->data, rc);
[31696b4f]120 ipc_answer(&TASK->kb.box, call);
[9a1b20c]121}
122
123
[3926f30]124/** Process a GO call.
125 *
126 * Resumes execution of the specified thread.
127 * @param call The call structure.
128 */
[9a1b20c]129static void udebug_receive_go(call_t *call)
130{
131 thread_t *t;
132 int rc;
133
134 t = (thread_t *)IPC_GET_ARG2(call->data);
135
136 rc = udebug_go(t, call);
137 if (rc < 0) {
138 IPC_SET_RETVAL(call->data, rc);
[31696b4f]139 ipc_answer(&TASK->kb.box, call);
[9a1b20c]140 return;
141 }
142}
143
[3926f30]144/** Process a STOP call.
145 *
146 * Suspends execution of the specified thread.
147 * @param call The call structure.
148 */
[9a1b20c]149static void udebug_receive_stop(call_t *call)
150{
151 thread_t *t;
152 int rc;
153
154 t = (thread_t *)IPC_GET_ARG2(call->data);
155
156 rc = udebug_stop(t, call);
157 IPC_SET_RETVAL(call->data, rc);
[31696b4f]158 ipc_answer(&TASK->kb.box, call);
[9a1b20c]159}
160
[3926f30]161/** Process a THREAD_READ call.
162 *
163 * Reads the list of hashes of the (userspace) threads in the current task.
164 * @param call The call structure.
165 */
[9a1b20c]166static void udebug_receive_thread_read(call_t *call)
167{
[336db295]168 uintptr_t uspace_addr;
169 size_t buf_size;
[9a1b20c]170 void *buffer;
[336db295]171 size_t copied, needed;
[9a1b20c]172 int rc;
173
174 uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */
175 buf_size = IPC_GET_ARG3(call->data); /* Dest. buffer size */
176
177 /*
178 * Read thread list. Variable n will be filled with actual number
179 * of threads times thread-id size.
180 */
[336db295]181 rc = udebug_thread_read(&buffer, buf_size, &copied, &needed);
[9a1b20c]182 if (rc < 0) {
183 IPC_SET_RETVAL(call->data, rc);
[31696b4f]184 ipc_answer(&TASK->kb.box, call);
[9a1b20c]185 return;
186 }
187
[336db295]188 /*
189 * Make use of call->buffer to transfer data to caller's userspace
190 */
191
192 IPC_SET_RETVAL(call->data, 0);
193 /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
194 same code in process_answer() can be used
195 (no way to distinguish method in answer) */
196 IPC_SET_ARG1(call->data, uspace_addr);
197 IPC_SET_ARG2(call->data, copied);
198 IPC_SET_ARG3(call->data, needed);
199 call->buffer = buffer;
200
201 ipc_answer(&TASK->kb.box, call);
202}
203
204/** Process an AREAS_READ call.
205 *
206 * Returns a list of address space areas in the current task, as an array
207 * of as_area_info_t structures.
208 *
209 * @param call The call structure.
210 */
211static void udebug_receive_areas_read(call_t *call)
212{
213 unative_t uspace_addr;
214 unative_t to_copy;
215 size_t data_size;
216 size_t buf_size;
217 void *data;
218
219 uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */
220 buf_size = IPC_GET_ARG3(call->data); /* Dest. buffer size */
221
222 /*
223 * Read area list.
224 */
225 as_get_area_info(AS, (as_area_info_t **) &data, &data_size);
[9a1b20c]226
[336db295]227 /* Copy MAX(buf_size, data_size) bytes */
[9a1b20c]228
[336db295]229 if (buf_size > data_size)
230 to_copy = data_size;
[9a1b20c]231 else
232 to_copy = buf_size;
233
234 /*
235 * Make use of call->buffer to transfer data to caller's userspace
236 */
237
238 IPC_SET_RETVAL(call->data, 0);
239 /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
240 same code in process_answer() can be used
241 (no way to distinguish method in answer) */
242 IPC_SET_ARG1(call->data, uspace_addr);
243 IPC_SET_ARG2(call->data, to_copy);
244
[336db295]245 IPC_SET_ARG3(call->data, data_size);
246 call->buffer = data;
[9a1b20c]247
[31696b4f]248 ipc_answer(&TASK->kb.box, call);
[9a1b20c]249}
250
[336db295]251
[3926f30]252/** Process an ARGS_READ call.
253 *
254 * Reads the argument of a current syscall event (SYSCALL_B or SYSCALL_E).
255 * @param call The call structure.
256 */
[9a1b20c]257static void udebug_receive_args_read(call_t *call)
258{
259 thread_t *t;
260 unative_t uspace_addr;
261 int rc;
262 void *buffer;
263
264 t = (thread_t *)IPC_GET_ARG2(call->data);
265
266 rc = udebug_args_read(t, &buffer);
267 if (rc != EOK) {
268 IPC_SET_RETVAL(call->data, rc);
[31696b4f]269 ipc_answer(&TASK->kb.box, call);
[9a1b20c]270 return;
271 }
272
273 /*
274 * Make use of call->buffer to transfer data to caller's userspace
275 */
276
277 uspace_addr = IPC_GET_ARG3(call->data);
278
279 IPC_SET_RETVAL(call->data, 0);
280 /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
281 same code in process_answer() can be used
282 (no way to distinguish method in answer) */
283 IPC_SET_ARG1(call->data, uspace_addr);
284 IPC_SET_ARG2(call->data, 6 * sizeof(unative_t));
285 call->buffer = buffer;
286
[31696b4f]287 ipc_answer(&TASK->kb.box, call);
[9a1b20c]288}
289
[3926f30]290/** Process an MEM_READ call.
291 *
292 * Reads memory of the current (debugged) task.
293 * @param call The call structure.
294 */
[9a1b20c]295static void udebug_receive_mem_read(call_t *call)
296{
297 unative_t uspace_dst;
298 unative_t uspace_src;
299 unsigned size;
300 void *buffer;
301 int rc;
302
303 uspace_dst = IPC_GET_ARG2(call->data);
304 uspace_src = IPC_GET_ARG3(call->data);
305 size = IPC_GET_ARG4(call->data);
306
307 rc = udebug_mem_read(uspace_src, size, &buffer);
308 if (rc < 0) {
309 IPC_SET_RETVAL(call->data, rc);
[31696b4f]310 ipc_answer(&TASK->kb.box, call);
[9a1b20c]311 return;
312 }
313
314 IPC_SET_RETVAL(call->data, 0);
315 /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
316 same code in process_answer() can be used
317 (no way to distinguish method in answer) */
318 IPC_SET_ARG1(call->data, uspace_dst);
319 IPC_SET_ARG2(call->data, size);
320 call->buffer = buffer;
321
[31696b4f]322 ipc_answer(&TASK->kb.box, call);
[9a1b20c]323}
324
[3926f30]325/** Handle a debug call received on the kernel answerbox.
[9a1b20c]326 *
[3926f30]327 * This is called by the kbox servicing thread. Verifies that the sender
328 * is indeed the debugger and calls the appropriate processing function.
[9a1b20c]329 */
330void udebug_call_receive(call_t *call)
331{
332 int debug_method;
333
334 debug_method = IPC_GET_ARG1(call->data);
335
336 if (debug_method != UDEBUG_M_BEGIN) {
337 /*
338 * Verify that the sender is this task's debugger.
339 * Note that this is the only thread that could change
340 * TASK->debugger. Therefore no locking is necessary
341 * and the sender can be safely considered valid until
342 * control exits this function.
343 */
344 if (TASK->udebug.debugger != call->sender) {
345 IPC_SET_RETVAL(call->data, EINVAL);
[31696b4f]346 ipc_answer(&TASK->kb.box, call);
[9a1b20c]347 return;
348 }
349 }
350
351 switch (debug_method) {
352 case UDEBUG_M_BEGIN:
353 udebug_receive_begin(call);
354 break;
355 case UDEBUG_M_END:
356 udebug_receive_end(call);
357 break;
358 case UDEBUG_M_SET_EVMASK:
359 udebug_receive_set_evmask(call);
360 break;
361 case UDEBUG_M_GO:
362 udebug_receive_go(call);
363 break;
364 case UDEBUG_M_STOP:
365 udebug_receive_stop(call);
366 break;
367 case UDEBUG_M_THREAD_READ:
368 udebug_receive_thread_read(call);
369 break;
[336db295]370 case UDEBUG_M_AREAS_READ:
371 udebug_receive_areas_read(call);
372 break;
[9a1b20c]373 case UDEBUG_M_ARGS_READ:
374 udebug_receive_args_read(call);
375 break;
376 case UDEBUG_M_MEM_READ:
377 udebug_receive_mem_read(call);
378 break;
379 }
380}
381
382/** @}
383 */
Note: See TracBrowser for help on using the repository browser.