source: mainline/kernel/generic/src/udebug/udebug_ipc.c@ 6ff23ff

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

More comment fixing (ccheck).

  • Property mode set to 100644
File size: 11.3 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 */
[63e27ef]40
41#include <assert.h>
[9a1b20c]42#include <proc/task.h>
43#include <proc/thread.h>
[336db295]44#include <mm/as.h>
[9a1b20c]45#include <arch.h>
46#include <errno.h>
47#include <ipc/ipc.h>
48#include <syscall/copy.h>
49#include <udebug/udebug.h>
50#include <udebug/udebug_ops.h>
51#include <udebug/udebug_ipc.h>
52
[b7fd2a0]53errno_t udebug_request_preprocess(call_t *call, phone_t *phone)
[9a1b20c]54{
55 switch (IPC_GET_ARG1(call->data)) {
[6ff23ff]56 /* future UDEBUG_M_REGS_WRITE, UDEBUG_M_MEM_WRITE: */
[9a1b20c]57 default:
58 break;
59 }
60
61 return 0;
62}
63
[3926f30]64/** Process a BEGIN call.
65 *
66 * Initiates a debugging session for the current task. The reply
67 * to this call may or may not be sent before this function returns.
68 *
69 * @param call The call structure.
70 */
[9a1b20c]71static void udebug_receive_begin(call_t *call)
72{
[b7fd2a0]73 errno_t rc;
[b2a1fd92]74 bool active;
[9a1b20c]75
[b2a1fd92]76 rc = udebug_begin(call, &active);
77 if (rc != EOK) {
[9a1b20c]78 IPC_SET_RETVAL(call->data, rc);
[31696b4f]79 ipc_answer(&TASK->kb.box, call);
[9a1b20c]80 return;
81 }
82
[3926f30]83 /*
84 * If the initialization of the debugging session has finished,
85 * send a reply.
86 */
[b2a1fd92]87 if (active) {
88 IPC_SET_RETVAL(call->data, EOK);
[31696b4f]89 ipc_answer(&TASK->kb.box, call);
[9a1b20c]90 }
91}
92
[3926f30]93/** Process an END call.
94 *
95 * Terminates the debugging session for the current task.
96 * @param call The call structure.
97 */
[9a1b20c]98static void udebug_receive_end(call_t *call)
99{
[b7fd2a0]100 errno_t rc;
[9a1b20c]101
102 rc = udebug_end();
103
104 IPC_SET_RETVAL(call->data, rc);
[31696b4f]105 ipc_answer(&TASK->kb.box, call);
[9a1b20c]106}
107
[3926f30]108/** Process a SET_EVMASK call.
109 *
110 * Sets an event mask for the current debugging session.
111 * @param call The call structure.
112 */
[9a1b20c]113static void udebug_receive_set_evmask(call_t *call)
114{
[b7fd2a0]115 errno_t rc;
[9a1b20c]116 udebug_evmask_t mask;
117
118 mask = IPC_GET_ARG2(call->data);
119 rc = udebug_set_evmask(mask);
120
121 IPC_SET_RETVAL(call->data, rc);
[31696b4f]122 ipc_answer(&TASK->kb.box, call);
[9a1b20c]123}
124
125
[3926f30]126/** Process a GO call.
127 *
128 * Resumes execution of the specified thread.
129 * @param call The call structure.
130 */
[9a1b20c]131static void udebug_receive_go(call_t *call)
132{
133 thread_t *t;
[b7fd2a0]134 errno_t rc;
[9a1b20c]135
136 t = (thread_t *)IPC_GET_ARG2(call->data);
137
138 rc = udebug_go(t, call);
[7f11dc6]139 if (rc != EOK) {
[9a1b20c]140 IPC_SET_RETVAL(call->data, rc);
[31696b4f]141 ipc_answer(&TASK->kb.box, call);
[9a1b20c]142 return;
143 }
144}
145
[3926f30]146/** Process a STOP call.
147 *
148 * Suspends execution of the specified thread.
149 * @param call The call structure.
150 */
[9a1b20c]151static void udebug_receive_stop(call_t *call)
152{
153 thread_t *t;
[b7fd2a0]154 errno_t rc;
[9a1b20c]155
156 t = (thread_t *)IPC_GET_ARG2(call->data);
157
158 rc = udebug_stop(t, call);
159 IPC_SET_RETVAL(call->data, rc);
[31696b4f]160 ipc_answer(&TASK->kb.box, call);
[9a1b20c]161}
162
[3926f30]163/** Process a THREAD_READ call.
164 *
165 * Reads the list of hashes of the (userspace) threads in the current task.
166 * @param call The call structure.
167 */
[9a1b20c]168static void udebug_receive_thread_read(call_t *call)
169{
[336db295]170 uintptr_t uspace_addr;
171 size_t buf_size;
[9a1b20c]172 void *buffer;
[336db295]173 size_t copied, needed;
[b7fd2a0]174 errno_t rc;
[9a1b20c]175
176 uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */
177 buf_size = IPC_GET_ARG3(call->data); /* Dest. buffer size */
178
179 /*
180 * Read thread list. Variable n will be filled with actual number
181 * of threads times thread-id size.
182 */
[336db295]183 rc = udebug_thread_read(&buffer, buf_size, &copied, &needed);
[7f11dc6]184 if (rc != EOK) {
[9a1b20c]185 IPC_SET_RETVAL(call->data, rc);
[31696b4f]186 ipc_answer(&TASK->kb.box, call);
[9a1b20c]187 return;
188 }
189
[336db295]190 /*
191 * Make use of call->buffer to transfer data to caller's userspace
192 */
193
194 IPC_SET_RETVAL(call->data, 0);
[6ff23ff]195 /*
196 * ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
197 * same code in process_answer() can be used
198 * (no way to distinguish method in answer)
199 */
[336db295]200 IPC_SET_ARG1(call->data, uspace_addr);
201 IPC_SET_ARG2(call->data, copied);
202 IPC_SET_ARG3(call->data, needed);
203 call->buffer = buffer;
204
205 ipc_answer(&TASK->kb.box, call);
206}
207
[3698e44]208/** Process a NAME_READ call.
209 *
210 * Returns a string containing the name of the task.
211 *
212 * @param call The call structure.
213 */
214static void udebug_receive_name_read(call_t *call)
215{
[96b02eb9]216 sysarg_t uspace_addr;
217 sysarg_t to_copy;
[3698e44]218 size_t data_size;
219 size_t buf_size;
220 void *data;
221
222 uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */
223 buf_size = IPC_GET_ARG3(call->data); /* Dest. buffer size */
224
225 /*
226 * Read task name.
227 */
228 udebug_name_read((char **) &data, &data_size);
229
230 /* Copy MAX(buf_size, data_size) bytes */
231
232 if (buf_size > data_size)
233 to_copy = data_size;
234 else
235 to_copy = buf_size;
236
237 /*
238 * Make use of call->buffer to transfer data to caller's userspace
239 */
240
241 IPC_SET_RETVAL(call->data, 0);
[6ff23ff]242 /*
243 * ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
244 * same code in process_answer() can be used
245 * (no way to distinguish method in answer)
246 */
[3698e44]247 IPC_SET_ARG1(call->data, uspace_addr);
248 IPC_SET_ARG2(call->data, to_copy);
249
250 IPC_SET_ARG3(call->data, data_size);
251 call->buffer = data;
252
253 ipc_answer(&TASK->kb.box, call);
254}
255
[336db295]256/** Process an AREAS_READ call.
257 *
258 * Returns a list of address space areas in the current task, as an array
259 * of as_area_info_t structures.
260 *
261 * @param call The call structure.
262 */
263static void udebug_receive_areas_read(call_t *call)
264{
[96b02eb9]265 sysarg_t uspace_addr;
266 sysarg_t to_copy;
[336db295]267 size_t data_size;
268 size_t buf_size;
269 void *data;
270
271 uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */
272 buf_size = IPC_GET_ARG3(call->data); /* Dest. buffer size */
273
274 /*
275 * Read area list.
276 */
277 as_get_area_info(AS, (as_area_info_t **) &data, &data_size);
[9a1b20c]278
[336db295]279 /* Copy MAX(buf_size, data_size) bytes */
[9a1b20c]280
[336db295]281 if (buf_size > data_size)
282 to_copy = data_size;
[9a1b20c]283 else
284 to_copy = buf_size;
285
286 /*
287 * Make use of call->buffer to transfer data to caller's userspace
288 */
289
290 IPC_SET_RETVAL(call->data, 0);
[6ff23ff]291 /*
292 * ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
293 * same code in process_answer() can be used
294 * (no way to distinguish method in answer)
295 */
[9a1b20c]296 IPC_SET_ARG1(call->data, uspace_addr);
297 IPC_SET_ARG2(call->data, to_copy);
298
[336db295]299 IPC_SET_ARG3(call->data, data_size);
300 call->buffer = data;
[9a1b20c]301
[31696b4f]302 ipc_answer(&TASK->kb.box, call);
[9a1b20c]303}
304
[336db295]305
[3926f30]306/** Process an ARGS_READ call.
307 *
308 * Reads the argument of a current syscall event (SYSCALL_B or SYSCALL_E).
309 * @param call The call structure.
310 */
[9a1b20c]311static void udebug_receive_args_read(call_t *call)
312{
313 thread_t *t;
[96b02eb9]314 sysarg_t uspace_addr;
[b7fd2a0]315 errno_t rc;
[9a1b20c]316 void *buffer;
317
318 t = (thread_t *)IPC_GET_ARG2(call->data);
319
320 rc = udebug_args_read(t, &buffer);
321 if (rc != EOK) {
322 IPC_SET_RETVAL(call->data, rc);
[31696b4f]323 ipc_answer(&TASK->kb.box, call);
[9a1b20c]324 return;
325 }
326
327 /*
328 * Make use of call->buffer to transfer data to caller's userspace
329 */
330
331 uspace_addr = IPC_GET_ARG3(call->data);
332
333 IPC_SET_RETVAL(call->data, 0);
[6ff23ff]334 /*
335 * ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
336 * same code in process_answer() can be used
337 * (no way to distinguish method in answer)
338 */
[9a1b20c]339 IPC_SET_ARG1(call->data, uspace_addr);
[96b02eb9]340 IPC_SET_ARG2(call->data, 6 * sizeof(sysarg_t));
[9a1b20c]341 call->buffer = buffer;
342
[31696b4f]343 ipc_answer(&TASK->kb.box, call);
[9a1b20c]344}
345
[80487bc5]346/** Receive a REGS_READ call.
347 *
348 * Reads the thread's register state (istate structure).
349 */
350static void udebug_receive_regs_read(call_t *call)
351{
352 thread_t *t;
[96b02eb9]353 sysarg_t uspace_addr;
354 sysarg_t to_copy;
[b5f716b]355 void *buffer = NULL;
[b7fd2a0]356 errno_t rc;
[80487bc5]357
358 t = (thread_t *) IPC_GET_ARG2(call->data);
359
360 rc = udebug_regs_read(t, &buffer);
[7f11dc6]361 if (rc != EOK) {
[80487bc5]362 IPC_SET_RETVAL(call->data, rc);
363 ipc_answer(&TASK->kb.box, call);
364 return;
365 }
366
[63e27ef]367 assert(buffer != NULL);
[b5f716b]368
[80487bc5]369 /*
370 * Make use of call->buffer to transfer data to caller's userspace
371 */
372
373 uspace_addr = IPC_GET_ARG3(call->data);
374 to_copy = sizeof(istate_t);
375
376 IPC_SET_RETVAL(call->data, 0);
[6ff23ff]377 /*
378 * ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
379 * same code in process_answer() can be used
380 * (no way to distinguish method in answer)
381 */
[80487bc5]382 IPC_SET_ARG1(call->data, uspace_addr);
383 IPC_SET_ARG2(call->data, to_copy);
384
385 call->buffer = buffer;
386
387 ipc_answer(&TASK->kb.box, call);
388}
389
390
[3926f30]391/** Process an MEM_READ call.
392 *
393 * Reads memory of the current (debugged) task.
394 * @param call The call structure.
395 */
[9a1b20c]396static void udebug_receive_mem_read(call_t *call)
397{
[96b02eb9]398 sysarg_t uspace_dst;
399 sysarg_t uspace_src;
[9a1b20c]400 unsigned size;
[b5f716b]401 void *buffer = NULL;
[b7fd2a0]402 errno_t rc;
[9a1b20c]403
404 uspace_dst = IPC_GET_ARG2(call->data);
405 uspace_src = IPC_GET_ARG3(call->data);
406 size = IPC_GET_ARG4(call->data);
407
408 rc = udebug_mem_read(uspace_src, size, &buffer);
[7f11dc6]409 if (rc != EOK) {
[9a1b20c]410 IPC_SET_RETVAL(call->data, rc);
[31696b4f]411 ipc_answer(&TASK->kb.box, call);
[9a1b20c]412 return;
413 }
414
[63e27ef]415 assert(buffer != NULL);
[b5f716b]416
[9a1b20c]417 IPC_SET_RETVAL(call->data, 0);
[6ff23ff]418 /*
419 * ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
420 * same code in process_answer() can be used
421 * (no way to distinguish method in answer)
422 */
[9a1b20c]423 IPC_SET_ARG1(call->data, uspace_dst);
424 IPC_SET_ARG2(call->data, size);
425 call->buffer = buffer;
426
[31696b4f]427 ipc_answer(&TASK->kb.box, call);
[9a1b20c]428}
429
[3926f30]430/** Handle a debug call received on the kernel answerbox.
[9a1b20c]431 *
[3926f30]432 * This is called by the kbox servicing thread. Verifies that the sender
433 * is indeed the debugger and calls the appropriate processing function.
[9a1b20c]434 */
435void udebug_call_receive(call_t *call)
436{
437 int debug_method;
438
439 debug_method = IPC_GET_ARG1(call->data);
440
441 if (debug_method != UDEBUG_M_BEGIN) {
442 /*
443 * Verify that the sender is this task's debugger.
444 * Note that this is the only thread that could change
445 * TASK->debugger. Therefore no locking is necessary
446 * and the sender can be safely considered valid until
447 * control exits this function.
448 */
449 if (TASK->udebug.debugger != call->sender) {
450 IPC_SET_RETVAL(call->data, EINVAL);
[31696b4f]451 ipc_answer(&TASK->kb.box, call);
[1b20da0]452 return;
[9a1b20c]453 }
454 }
455
456 switch (debug_method) {
457 case UDEBUG_M_BEGIN:
458 udebug_receive_begin(call);
459 break;
460 case UDEBUG_M_END:
461 udebug_receive_end(call);
462 break;
463 case UDEBUG_M_SET_EVMASK:
464 udebug_receive_set_evmask(call);
465 break;
466 case UDEBUG_M_GO:
467 udebug_receive_go(call);
468 break;
469 case UDEBUG_M_STOP:
470 udebug_receive_stop(call);
471 break;
472 case UDEBUG_M_THREAD_READ:
473 udebug_receive_thread_read(call);
474 break;
[3698e44]475 case UDEBUG_M_NAME_READ:
476 udebug_receive_name_read(call);
477 break;
[336db295]478 case UDEBUG_M_AREAS_READ:
479 udebug_receive_areas_read(call);
480 break;
[9a1b20c]481 case UDEBUG_M_ARGS_READ:
482 udebug_receive_args_read(call);
483 break;
[80487bc5]484 case UDEBUG_M_REGS_READ:
485 udebug_receive_regs_read(call);
486 break;
[9a1b20c]487 case UDEBUG_M_MEM_READ:
488 udebug_receive_mem_read(call);
489 break;
490 }
491}
492
493/** @}
494 */
Note: See TracBrowser for help on using the repository browser.