source: mainline/kernel/generic/src/udebug/udebug_ipc.c@ 21a639b7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 21a639b7 was 31696b4f, checked in by Jiri Svoboda <jirik.svoboda@…>, 17 years ago

Move stuff related to kbox to a separate struct.

  • Property mode set to 100644
File size: 8.1 KB
Line 
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.
36 *
37 * This module handles udebug IPC messages and calls the appropriate
38 * functions from the udebug_ops module which implement them.
39 */
40
41#include <proc/task.h>
42#include <proc/thread.h>
43#include <arch.h>
44#include <errno.h>
45#include <ipc/ipc.h>
46#include <syscall/copy.h>
47#include <udebug/udebug.h>
48#include <udebug/udebug_ops.h>
49#include <udebug/udebug_ipc.h>
50
51int udebug_request_preprocess(call_t *call, phone_t *phone)
52{
53 switch (IPC_GET_ARG1(call->data)) {
54 /* future UDEBUG_M_REGS_WRITE, UDEBUG_M_MEM_WRITE: */
55 default:
56 break;
57 }
58
59 return 0;
60}
61
62/** Process a BEGIN call.
63 *
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.
66 *
67 * @param call The call structure.
68 */
69static void udebug_receive_begin(call_t *call)
70{
71 int rc;
72
73 rc = udebug_begin(call);
74 if (rc < 0) {
75 IPC_SET_RETVAL(call->data, rc);
76 ipc_answer(&TASK->kb.box, call);
77 return;
78 }
79
80 /*
81 * If the initialization of the debugging session has finished,
82 * send a reply.
83 */
84 if (rc != 0) {
85 IPC_SET_RETVAL(call->data, 0);
86 ipc_answer(&TASK->kb.box, call);
87 }
88}
89
90/** Process an END call.
91 *
92 * Terminates the debugging session for the current task.
93 * @param call The call structure.
94 */
95static void udebug_receive_end(call_t *call)
96{
97 int rc;
98
99 rc = udebug_end();
100
101 IPC_SET_RETVAL(call->data, rc);
102 ipc_answer(&TASK->kb.box, call);
103}
104
105/** Process a SET_EVMASK call.
106 *
107 * Sets an event mask for the current debugging session.
108 * @param call The call structure.
109 */
110static void udebug_receive_set_evmask(call_t *call)
111{
112 int rc;
113 udebug_evmask_t mask;
114
115 mask = IPC_GET_ARG2(call->data);
116 rc = udebug_set_evmask(mask);
117
118 IPC_SET_RETVAL(call->data, rc);
119 ipc_answer(&TASK->kb.box, call);
120}
121
122
123/** Process a GO call.
124 *
125 * Resumes execution of the specified thread.
126 * @param call The call structure.
127 */
128static void udebug_receive_go(call_t *call)
129{
130 thread_t *t;
131 int rc;
132
133 t = (thread_t *)IPC_GET_ARG2(call->data);
134
135 rc = udebug_go(t, call);
136 if (rc < 0) {
137 IPC_SET_RETVAL(call->data, rc);
138 ipc_answer(&TASK->kb.box, call);
139 return;
140 }
141}
142
143/** Process a STOP call.
144 *
145 * Suspends execution of the specified thread.
146 * @param call The call structure.
147 */
148static void udebug_receive_stop(call_t *call)
149{
150 thread_t *t;
151 int rc;
152
153 t = (thread_t *)IPC_GET_ARG2(call->data);
154
155 rc = udebug_stop(t, call);
156 IPC_SET_RETVAL(call->data, rc);
157 ipc_answer(&TASK->kb.box, call);
158}
159
160/** Process a THREAD_READ call.
161 *
162 * Reads the list of hashes of the (userspace) threads in the current task.
163 * @param call The call structure.
164 */
165static void udebug_receive_thread_read(call_t *call)
166{
167 unative_t uspace_addr;
168 unative_t to_copy;
169 unsigned total_bytes;
170 unsigned buf_size;
171 void *buffer;
172 size_t n;
173 int rc;
174
175 uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */
176 buf_size = IPC_GET_ARG3(call->data); /* Dest. buffer size */
177
178 /*
179 * Read thread list. Variable n will be filled with actual number
180 * of threads times thread-id size.
181 */
182 rc = udebug_thread_read(&buffer, buf_size, &n);
183 if (rc < 0) {
184 IPC_SET_RETVAL(call->data, rc);
185 ipc_answer(&TASK->kb.box, call);
186 return;
187 }
188
189 total_bytes = n;
190
191 /* Copy MAX(buf_size, total_bytes) bytes */
192
193 if (buf_size > total_bytes)
194 to_copy = total_bytes;
195 else
196 to_copy = buf_size;
197
198 /*
199 * Make use of call->buffer to transfer data to caller's userspace
200 */
201
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);
208
209 IPC_SET_ARG3(call->data, total_bytes);
210 call->buffer = buffer;
211
212 ipc_answer(&TASK->kb.box, call);
213}
214
215/** Process an ARGS_READ call.
216 *
217 * Reads the argument of a current syscall event (SYSCALL_B or SYSCALL_E).
218 * @param call The call structure.
219 */
220static void udebug_receive_args_read(call_t *call)
221{
222 thread_t *t;
223 unative_t uspace_addr;
224 int rc;
225 void *buffer;
226
227 t = (thread_t *)IPC_GET_ARG2(call->data);
228
229 rc = udebug_args_read(t, &buffer);
230 if (rc != EOK) {
231 IPC_SET_RETVAL(call->data, rc);
232 ipc_answer(&TASK->kb.box, call);
233 return;
234 }
235
236 /*
237 * Make use of call->buffer to transfer data to caller's userspace
238 */
239
240 uspace_addr = IPC_GET_ARG3(call->data);
241
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;
249
250 ipc_answer(&TASK->kb.box, call);
251}
252
253/** Process an MEM_READ call.
254 *
255 * Reads memory of the current (debugged) task.
256 * @param call The call structure.
257 */
258static void udebug_receive_mem_read(call_t *call)
259{
260 unative_t uspace_dst;
261 unative_t uspace_src;
262 unsigned size;
263 void *buffer;
264 int rc;
265
266 uspace_dst = IPC_GET_ARG2(call->data);
267 uspace_src = IPC_GET_ARG3(call->data);
268 size = IPC_GET_ARG4(call->data);
269
270 rc = udebug_mem_read(uspace_src, size, &buffer);
271 if (rc < 0) {
272 IPC_SET_RETVAL(call->data, rc);
273 ipc_answer(&TASK->kb.box, call);
274 return;
275 }
276
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;
284
285 ipc_answer(&TASK->kb.box, call);
286}
287
288/** Handle a debug call received on the kernel answerbox.
289 *
290 * This is called by the kbox servicing thread. Verifies that the sender
291 * is indeed the debugger and calls the appropriate processing function.
292 */
293void udebug_call_receive(call_t *call)
294{
295 int debug_method;
296
297 debug_method = IPC_GET_ARG1(call->data);
298
299 if (debug_method != UDEBUG_M_BEGIN) {
300 /*
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.
306 */
307 if (TASK->udebug.debugger != call->sender) {
308 IPC_SET_RETVAL(call->data, EINVAL);
309 ipc_answer(&TASK->kb.box, call);
310 return;
311 }
312 }
313
314 switch (debug_method) {
315 case UDEBUG_M_BEGIN:
316 udebug_receive_begin(call);
317 break;
318 case UDEBUG_M_END:
319 udebug_receive_end(call);
320 break;
321 case UDEBUG_M_SET_EVMASK:
322 udebug_receive_set_evmask(call);
323 break;
324 case UDEBUG_M_GO:
325 udebug_receive_go(call);
326 break;
327 case UDEBUG_M_STOP:
328 udebug_receive_stop(call);
329 break;
330 case UDEBUG_M_THREAD_READ:
331 udebug_receive_thread_read(call);
332 break;
333 case UDEBUG_M_ARGS_READ:
334 udebug_receive_args_read(call);
335 break;
336 case UDEBUG_M_MEM_READ:
337 udebug_receive_mem_read(call);
338 break;
339 }
340}
341
342/** @}
343 */
Note: See TracBrowser for help on using the repository browser.