2
* Copyright (c) 2008 Jiri Svoboda
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
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.
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.
29
/** @addtogroup generic
35
* @brief Udebug IPC message handling.
37
* This module handles udebug IPC messages and calls the appropriate
38
* functions from the udebug_ops module which implement them.
41
#include <proc/task.h>
42
#include <proc/thread.h>
46
#include <syscall/copy.h>
47
#include <udebug/udebug.h>
48
#include <udebug/udebug_ops.h>
49
#include <udebug/udebug_ipc.h>
51
int udebug_request_preprocess(call_t *call, phone_t *phone)
53
switch (IPC_GET_ARG1(call->data)) {
54
/* future UDEBUG_M_REGS_WRITE, UDEBUG_M_MEM_WRITE: */
62
/** Process a BEGIN call.
64
* Initiates a debugging session for the current task. The reply
65
* to this call may or may not be sent before this function returns.
67
* @param call The call structure.
69
static void udebug_receive_begin(call_t *call)
73
rc = udebug_begin(call);
75
IPC_SET_RETVAL(call->data, rc);
76
ipc_answer(&TASK->kb.box, call);
81
* If the initialization of the debugging session has finished,
85
IPC_SET_RETVAL(call->data, 0);
86
ipc_answer(&TASK->kb.box, call);
90
/** Process an END call.
92
* Terminates the debugging session for the current task.
93
* @param call The call structure.
95
static void udebug_receive_end(call_t *call)
101
IPC_SET_RETVAL(call->data, rc);
102
ipc_answer(&TASK->kb.box, call);
105
/** Process a SET_EVMASK call.
107
* Sets an event mask for the current debugging session.
108
* @param call The call structure.
110
static void udebug_receive_set_evmask(call_t *call)
113
udebug_evmask_t mask;
115
mask = IPC_GET_ARG2(call->data);
116
rc = udebug_set_evmask(mask);
118
IPC_SET_RETVAL(call->data, rc);
119
ipc_answer(&TASK->kb.box, call);
123
/** Process a GO call.
125
* Resumes execution of the specified thread.
126
* @param call The call structure.
128
static void udebug_receive_go(call_t *call)
133
t = (thread_t *)IPC_GET_ARG2(call->data);
135
rc = udebug_go(t, call);
137
IPC_SET_RETVAL(call->data, rc);
138
ipc_answer(&TASK->kb.box, call);
143
/** Process a STOP call.
145
* Suspends execution of the specified thread.
146
* @param call The call structure.
148
static void udebug_receive_stop(call_t *call)
153
t = (thread_t *)IPC_GET_ARG2(call->data);
155
rc = udebug_stop(t, call);
156
IPC_SET_RETVAL(call->data, rc);
157
ipc_answer(&TASK->kb.box, call);
160
/** Process a THREAD_READ call.
162
* Reads the list of hashes of the (userspace) threads in the current task.
163
* @param call The call structure.
165
static void udebug_receive_thread_read(call_t *call)
167
unative_t uspace_addr;
169
unsigned total_bytes;
175
uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */
176
buf_size = IPC_GET_ARG3(call->data); /* Dest. buffer size */
179
* Read thread list. Variable n will be filled with actual number
180
* of threads times thread-id size.
182
rc = udebug_thread_read(&buffer, buf_size, &n);
184
IPC_SET_RETVAL(call->data, rc);
185
ipc_answer(&TASK->kb.box, call);
191
/* Copy MAX(buf_size, total_bytes) bytes */
193
if (buf_size > total_bytes)
194
to_copy = total_bytes;
199
* Make use of call->buffer to transfer data to caller's userspace
202
IPC_SET_RETVAL(call->data, 0);
203
/* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
204
same code in process_answer() can be used
205
(no way to distinguish method in answer) */
206
IPC_SET_ARG1(call->data, uspace_addr);
207
IPC_SET_ARG2(call->data, to_copy);
209
IPC_SET_ARG3(call->data, total_bytes);
210
call->buffer = buffer;
212
ipc_answer(&TASK->kb.box, call);
215
/** Process an ARGS_READ call.
217
* Reads the argument of a current syscall event (SYSCALL_B or SYSCALL_E).
218
* @param call The call structure.
220
static void udebug_receive_args_read(call_t *call)
223
unative_t uspace_addr;
227
t = (thread_t *)IPC_GET_ARG2(call->data);
229
rc = udebug_args_read(t, &buffer);
231
IPC_SET_RETVAL(call->data, rc);
232
ipc_answer(&TASK->kb.box, call);
237
* Make use of call->buffer to transfer data to caller's userspace
240
uspace_addr = IPC_GET_ARG3(call->data);
242
IPC_SET_RETVAL(call->data, 0);
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
IPC_SET_ARG1(call->data, uspace_addr);
247
IPC_SET_ARG2(call->data, 6 * sizeof(unative_t));
248
call->buffer = buffer;
250
ipc_answer(&TASK->kb.box, call);
253
/** Process an MEM_READ call.
255
* Reads memory of the current (debugged) task.
256
* @param call The call structure.
258
static void udebug_receive_mem_read(call_t *call)
260
unative_t uspace_dst;
261
unative_t uspace_src;
266
uspace_dst = IPC_GET_ARG2(call->data);
267
uspace_src = IPC_GET_ARG3(call->data);
268
size = IPC_GET_ARG4(call->data);
270
rc = udebug_mem_read(uspace_src, size, &buffer);
272
IPC_SET_RETVAL(call->data, rc);
273
ipc_answer(&TASK->kb.box, call);
277
IPC_SET_RETVAL(call->data, 0);
278
/* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
279
same code in process_answer() can be used
280
(no way to distinguish method in answer) */
281
IPC_SET_ARG1(call->data, uspace_dst);
282
IPC_SET_ARG2(call->data, size);
283
call->buffer = buffer;
285
ipc_answer(&TASK->kb.box, call);
288
/** Handle a debug call received on the kernel answerbox.
290
* This is called by the kbox servicing thread. Verifies that the sender
291
* is indeed the debugger and calls the appropriate processing function.
293
void udebug_call_receive(call_t *call)
297
debug_method = IPC_GET_ARG1(call->data);
299
if (debug_method != UDEBUG_M_BEGIN) {
301
* Verify that the sender is this task's debugger.
302
* Note that this is the only thread that could change
303
* TASK->debugger. Therefore no locking is necessary
304
* and the sender can be safely considered valid until
305
* control exits this function.
307
if (TASK->udebug.debugger != call->sender) {
308
IPC_SET_RETVAL(call->data, EINVAL);
309
ipc_answer(&TASK->kb.box, call);
314
switch (debug_method) {
316
udebug_receive_begin(call);
319
udebug_receive_end(call);
321
case UDEBUG_M_SET_EVMASK:
322
udebug_receive_set_evmask(call);
325
udebug_receive_go(call);
328
udebug_receive_stop(call);
330
case UDEBUG_M_THREAD_READ:
331
udebug_receive_thread_read(call);
333
case UDEBUG_M_ARGS_READ:
334
udebug_receive_args_read(call);
336
case UDEBUG_M_MEM_READ:
337
udebug_receive_mem_read(call);