source: mainline/kernel/generic/src/udebug/udebug_ipc.c

Last change on this file was fa603e99, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 6 years ago

Fix unhandled error condition in udebug_name_read

Detected by GCC when LTO is enabled.
Also changed a bunch of literal zeros in the file to EOK.

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