Subversion Repositories HelenOS

Rev

Rev 3471 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3471 Rev 3611
1
/*
1
/*
2
 * Copyright (c) 2008 Jiri Svoboda
2
 * Copyright (c) 2008 Jiri Svoboda
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
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
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.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
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
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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
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.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup generic
29
/** @addtogroup generic
30
 * @{
30
 * @{
31
 */
31
 */
32
 
32
 
33
/**
33
/**
34
 * @file
34
 * @file
35
 * @brief   Udebug IPC message handling.
35
 * @brief   Udebug IPC message handling.
36
 *
36
 *
37
 * This module handles udebug IPC messages and calls the appropriate
37
 * This module handles udebug IPC messages and calls the appropriate
38
 * functions from the udebug_ops module which implement them.
38
 * functions from the udebug_ops module which implement them.
39
 */
39
 */
40
 
40
 
41
#include <proc/task.h>
41
#include <proc/task.h>
42
#include <proc/thread.h>
42
#include <proc/thread.h>
43
#include <arch.h>
43
#include <arch.h>
44
#include <errno.h>
44
#include <errno.h>
45
#include <ipc/ipc.h>
45
#include <ipc/ipc.h>
46
#include <syscall/copy.h>
46
#include <syscall/copy.h>
47
#include <udebug/udebug.h>
47
#include <udebug/udebug.h>
48
#include <udebug/udebug_ops.h>
48
#include <udebug/udebug_ops.h>
49
#include <udebug/udebug_ipc.h>
49
#include <udebug/udebug_ipc.h>
50
 
50
 
51
static int udebug_rp_regs_write(call_t *call, phone_t *phone)
51
static int udebug_rp_regs_write(call_t *call, phone_t *phone)
52
{
52
{
53
    void *uspace_data;
53
    void *uspace_data;
54
    unative_t to_copy;
54
    unative_t to_copy;
55
    int rc;
55
    int rc;
56
    void *buffer;
56
    void *buffer;
57
 
57
 
58
    printf("debug_regs_write()\n");
58
    LOG("debug_regs_write()\n");
59
 
59
 
60
    uspace_data = (void *)IPC_GET_ARG3(call->data);
60
    uspace_data = (void *)IPC_GET_ARG3(call->data);
61
    to_copy = sizeof(istate_t);
61
    to_copy = sizeof(istate_t);
62
    buffer = malloc(to_copy, 0);
62
    buffer = malloc(to_copy, 0);
63
 
63
 
64
    rc = copy_from_uspace(buffer, uspace_data, to_copy);
64
    rc = copy_from_uspace(buffer, uspace_data, to_copy);
65
    if (rc != 0) {
65
    if (rc != 0) {
66
        printf("debug_regs_write() - copy failed\n");
66
        LOG("debug_regs_write() - copy failed\n");
67
        return rc;
67
        return rc;
68
    }
68
    }
69
 
69
 
70
    call->buffer = buffer;
70
    call->buffer = buffer;
71
 
71
 
72
    printf(" - done\n");
72
    LOG(" - done\n");
73
    return 0;
73
    return 0;
74
}
74
}
75
 
75
 
76
static int udebug_rp_mem_write(call_t *call, phone_t *phone)
76
static int udebug_rp_mem_write(call_t *call, phone_t *phone)
77
{
77
{
78
    void *uspace_data;
78
    void *uspace_data;
79
    unative_t to_copy;
79
    unative_t to_copy;
80
    int rc;
80
    int rc;
81
    void *buffer;
81
    void *buffer;
82
 
82
 
83
    printf("udebug_rp_mem_write()\n");
83
    LOG("udebug_rp_mem_write()\n");
84
 
84
 
85
    uspace_data = (void *)IPC_GET_ARG2(call->data);
85
    uspace_data = (void *)IPC_GET_ARG2(call->data);
86
    to_copy = IPC_GET_ARG4(call->data);
86
    to_copy = IPC_GET_ARG4(call->data);
87
 
87
 
88
    buffer = malloc(to_copy, 0);
88
    buffer = malloc(to_copy, 0);
89
 
89
 
90
    rc = copy_from_uspace(buffer, uspace_data, to_copy);
90
    rc = copy_from_uspace(buffer, uspace_data, to_copy);
91
    if (rc != 0) {
91
    if (rc != 0) {
92
        printf(" - copy failed\n");
92
        LOG(" - copy failed\n");
93
        return rc;
93
        return rc;
94
    }
94
    }
95
 
95
 
96
    call->buffer = buffer;
96
    call->buffer = buffer;
97
 
97
 
98
    printf(" - done\n");
98
    LOG(" - done\n");
99
    return 0;
99
    return 0;
100
}
100
}
101
 
101
 
102
 
102
 
103
int udebug_request_preprocess(call_t *call, phone_t *phone)
103
int udebug_request_preprocess(call_t *call, phone_t *phone)
104
{
104
{
105
    int rc;
105
    int rc;
106
 
106
 
107
    switch (IPC_GET_ARG1(call->data)) {
107
    switch (IPC_GET_ARG1(call->data)) {
108
    case UDEBUG_M_REGS_WRITE:
108
    case UDEBUG_M_REGS_WRITE:
109
        rc = udebug_rp_regs_write(call, phone);
109
        rc = udebug_rp_regs_write(call, phone);
110
        return rc;
110
        return rc;
111
    case UDEBUG_M_MEM_WRITE:
111
    case UDEBUG_M_MEM_WRITE:
112
        rc = udebug_rp_mem_write(call, phone);
112
        rc = udebug_rp_mem_write(call, phone);
113
        return rc;
113
        return rc;
114
    default:
114
    default:
115
        break;
115
        break;
116
    }
116
    }
117
 
117
 
118
    return 0;
118
    return 0;
119
}
119
}
120
 
120
 
121
/** Process a BEGIN call.
121
/** Process a BEGIN call.
122
 *
122
 *
123
 * Initiates a debugging session for the current task. The reply
123
 * Initiates a debugging session for the current task. The reply
124
 * to this call may or may not be sent before this function returns.
124
 * to this call may or may not be sent before this function returns.
125
 *
125
 *
126
 * @param call  The call structure.
126
 * @param call  The call structure.
127
 */
127
 */
128
static void udebug_receive_begin(call_t *call)
128
static void udebug_receive_begin(call_t *call)
129
{
129
{
130
    int rc;
130
    int rc;
131
 
131
 
132
    rc = udebug_begin(call);
132
    rc = udebug_begin(call);
133
    if (rc < 0) {
133
    if (rc < 0) {
134
        IPC_SET_RETVAL(call->data, rc);
134
        IPC_SET_RETVAL(call->data, rc);
135
        ipc_answer(&TASK->kernel_box, call);
135
        ipc_answer(&TASK->kernel_box, call);
136
        return;
136
        return;
137
    }
137
    }
138
 
138
 
139
    /*
139
    /*
140
     * If the initialization of the debugging session has finished,
140
     * If the initialization of the debugging session has finished,
141
     * send a reply.
141
     * send a reply.
142
     */
142
     */
143
    if (rc != 0) {
143
    if (rc != 0) {
144
        IPC_SET_RETVAL(call->data, 0);
144
        IPC_SET_RETVAL(call->data, 0);
145
        ipc_answer(&TASK->kernel_box, call);
145
        ipc_answer(&TASK->kernel_box, call);
146
    }
146
    }
147
}
147
}
148
 
148
 
149
/** Process an END call.
149
/** Process an END call.
150
 *
150
 *
151
 * Terminates the debugging session for the current task.
151
 * Terminates the debugging session for the current task.
152
 * @param call  The call structure.
152
 * @param call  The call structure.
153
 */
153
 */
154
static void udebug_receive_end(call_t *call)
154
static void udebug_receive_end(call_t *call)
155
{
155
{
156
    int rc;
156
    int rc;
157
 
157
 
158
    rc = udebug_end();
158
    rc = udebug_end();
159
 
159
 
160
    IPC_SET_RETVAL(call->data, rc);
160
    IPC_SET_RETVAL(call->data, rc);
161
    ipc_answer(&TASK->kernel_box, call);
161
    ipc_answer(&TASK->kernel_box, call);
162
}
162
}
163
 
163
 
164
/** Process a SET_EVMASK call.
164
/** Process a SET_EVMASK call.
165
 *
165
 *
166
 * Sets an event mask for the current debugging session.
166
 * Sets an event mask for the current debugging session.
167
 * @param call  The call structure.
167
 * @param call  The call structure.
168
 */
168
 */
169
static void udebug_receive_set_evmask(call_t *call)
169
static void udebug_receive_set_evmask(call_t *call)
170
{
170
{
171
    int rc;
171
    int rc;
172
    udebug_evmask_t mask;
172
    udebug_evmask_t mask;
173
 
173
 
174
    mask = IPC_GET_ARG2(call->data);
174
    mask = IPC_GET_ARG2(call->data);
175
    rc = udebug_set_evmask(mask);
175
    rc = udebug_set_evmask(mask);
176
 
176
 
177
    IPC_SET_RETVAL(call->data, rc);
177
    IPC_SET_RETVAL(call->data, rc);
178
    ipc_answer(&TASK->kernel_box, call);
178
    ipc_answer(&TASK->kernel_box, call);
179
}
179
}
180
 
180
 
181
 
181
 
182
/** Process a GO call.
182
/** Process a GO call.
183
 *
183
 *
184
 * Resumes execution of the specified thread.
184
 * Resumes execution of the specified thread.
185
 * @param call  The call structure.
185
 * @param call  The call structure.
186
 */
186
 */
187
static void udebug_receive_go(call_t *call)
187
static void udebug_receive_go(call_t *call)
188
{
188
{
189
    thread_t *t;
189
    thread_t *t;
190
    int rc;
190
    int rc;
191
 
191
 
192
    t = (thread_t *)IPC_GET_ARG2(call->data);
192
    t = (thread_t *)IPC_GET_ARG2(call->data);
193
 
193
 
194
    rc = udebug_go(t, call);
194
    rc = udebug_go(t, call);
195
    if (rc < 0) {
195
    if (rc < 0) {
196
        IPC_SET_RETVAL(call->data, rc);
196
        IPC_SET_RETVAL(call->data, rc);
197
        ipc_answer(&TASK->kernel_box, call);
197
        ipc_answer(&TASK->kernel_box, call);
198
        return;
198
        return;
199
    }
199
    }
200
}
200
}
201
 
201
 
202
/** Process a STOP call.
202
/** Process a STOP call.
203
 *
203
 *
204
 * Suspends execution of the specified thread.
204
 * Suspends execution of the specified thread.
205
 * @param call  The call structure.
205
 * @param call  The call structure.
206
 */
206
 */
207
static void udebug_receive_stop(call_t *call)
207
static void udebug_receive_stop(call_t *call)
208
{
208
{
209
    thread_t *t;
209
    thread_t *t;
210
    int rc;
210
    int rc;
211
 
211
 
212
    t = (thread_t *)IPC_GET_ARG2(call->data);
212
    t = (thread_t *)IPC_GET_ARG2(call->data);
213
 
213
 
214
    rc = udebug_stop(t, call);
214
    rc = udebug_stop(t, call);
215
    IPC_SET_RETVAL(call->data, rc);
215
    IPC_SET_RETVAL(call->data, rc);
216
    ipc_answer(&TASK->kernel_box, call);
216
    ipc_answer(&TASK->kernel_box, call);
217
}
217
}
218
 
218
 
219
/** Process a THREAD_READ call.
219
/** Process a THREAD_READ call.
220
 *
220
 *
221
 * Reads the list of hashes of the (userspace) threads in the current task.
221
 * Reads the list of hashes of the (userspace) threads in the current task.
222
 * @param call  The call structure.
222
 * @param call  The call structure.
223
 */
223
 */
224
static void udebug_receive_thread_read(call_t *call)
224
static void udebug_receive_thread_read(call_t *call)
225
{
225
{
226
    unative_t uspace_addr;
226
    unative_t uspace_addr;
227
    unative_t to_copy;
227
    unative_t to_copy;
228
    unsigned total_bytes;
228
    unsigned total_bytes;
229
    unsigned buf_size;
229
    unsigned buf_size;
230
    void *buffer;
230
    void *buffer;
231
    size_t n;
231
    size_t n;
232
    int rc;
232
    int rc;
233
 
233
 
234
    uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */
234
    uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */
235
    buf_size = IPC_GET_ARG3(call->data);    /* Dest. buffer size */
235
    buf_size = IPC_GET_ARG3(call->data);    /* Dest. buffer size */
236
 
236
 
237
    /*
237
    /*
238
     * Read thread list. Variable n will be filled with actual number
238
     * Read thread list. Variable n will be filled with actual number
239
     * of threads times thread-id size.
239
     * of threads times thread-id size.
240
     */
240
     */
241
    rc = udebug_thread_read(&buffer, buf_size, &n);
241
    rc = udebug_thread_read(&buffer, buf_size, &n);
242
    if (rc < 0) {
242
    if (rc < 0) {
243
        IPC_SET_RETVAL(call->data, rc);
243
        IPC_SET_RETVAL(call->data, rc);
244
        ipc_answer(&TASK->kernel_box, call);
244
        ipc_answer(&TASK->kernel_box, call);
245
        return;
245
        return;
246
    }
246
    }
247
 
247
 
248
    total_bytes = n;
248
    total_bytes = n;
249
 
249
 
250
    /* Copy MAX(buf_size, total_bytes) bytes */
250
    /* Copy MAX(buf_size, total_bytes) bytes */
251
 
251
 
252
    if (buf_size > total_bytes)
252
    if (buf_size > total_bytes)
253
        to_copy = total_bytes;
253
        to_copy = total_bytes;
254
    else
254
    else
255
        to_copy = buf_size;
255
        to_copy = buf_size;
256
 
256
 
257
    /*
257
    /*
258
     * Make use of call->buffer to transfer data to caller's userspace
258
     * Make use of call->buffer to transfer data to caller's userspace
259
     */
259
     */
260
 
260
 
261
    IPC_SET_RETVAL(call->data, 0);
261
    IPC_SET_RETVAL(call->data, 0);
262
    /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
262
    /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
263
       same code in process_answer() can be used
263
       same code in process_answer() can be used
264
       (no way to distinguish method in answer) */
264
       (no way to distinguish method in answer) */
265
    IPC_SET_ARG1(call->data, uspace_addr);
265
    IPC_SET_ARG1(call->data, uspace_addr);
266
    IPC_SET_ARG2(call->data, to_copy);
266
    IPC_SET_ARG2(call->data, to_copy);
267
 
267
 
268
    IPC_SET_ARG3(call->data, total_bytes);
268
    IPC_SET_ARG3(call->data, total_bytes);
269
    call->buffer = buffer;
269
    call->buffer = buffer;
270
 
270
 
271
    ipc_answer(&TASK->kernel_box, call);
271
    ipc_answer(&TASK->kernel_box, call);
272
}
272
}
273
 
273
 
274
/** Process an ARGS_READ call.
274
/** Process an ARGS_READ call.
275
 *
275
 *
276
 * Reads the argument of a current syscall event (SYSCALL_B or SYSCALL_E).
276
 * Reads the argument of a current syscall event (SYSCALL_B or SYSCALL_E).
277
 * @param call  The call structure.
277
 * @param call  The call structure.
278
 */
278
 */
279
static void udebug_receive_args_read(call_t *call)
279
static void udebug_receive_args_read(call_t *call)
280
{
280
{
281
    thread_t *t;
281
    thread_t *t;
282
    unative_t uspace_addr;
282
    unative_t uspace_addr;
283
    int rc;
283
    int rc;
284
    void *buffer;
284
    void *buffer;
285
 
285
 
286
    t = (thread_t *)IPC_GET_ARG2(call->data);
286
    t = (thread_t *)IPC_GET_ARG2(call->data);
287
 
287
 
288
    rc = udebug_args_read(t, &buffer);
288
    rc = udebug_args_read(t, &buffer);
289
    if (rc != EOK) {
289
    if (rc != EOK) {
290
        IPC_SET_RETVAL(call->data, rc);
290
        IPC_SET_RETVAL(call->data, rc);
291
        ipc_answer(&TASK->kernel_box, call);
291
        ipc_answer(&TASK->kernel_box, call);
292
        return;
292
        return;
293
    }
293
    }
294
 
294
 
295
    /*
295
    /*
296
     * Make use of call->buffer to transfer data to caller's userspace
296
     * Make use of call->buffer to transfer data to caller's userspace
297
     */
297
     */
298
 
298
 
299
    uspace_addr = IPC_GET_ARG3(call->data);
299
    uspace_addr = IPC_GET_ARG3(call->data);
300
 
300
 
301
    IPC_SET_RETVAL(call->data, 0);
301
    IPC_SET_RETVAL(call->data, 0);
302
    /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
302
    /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
303
       same code in process_answer() can be used
303
       same code in process_answer() can be used
304
       (no way to distinguish method in answer) */
304
       (no way to distinguish method in answer) */
305
    IPC_SET_ARG1(call->data, uspace_addr);
305
    IPC_SET_ARG1(call->data, uspace_addr);
306
    IPC_SET_ARG2(call->data, 6 * sizeof(unative_t));
306
    IPC_SET_ARG2(call->data, 6 * sizeof(unative_t));
307
    call->buffer = buffer;
307
    call->buffer = buffer;
308
 
308
 
309
    ipc_answer(&TASK->kernel_box, call);
309
    ipc_answer(&TASK->kernel_box, call);
310
}
310
}
311
 
311
 
312
static void udebug_receive_regs_read(call_t *call)
312
static void udebug_receive_regs_read(call_t *call)
313
{
313
{
314
    thread_t *t;
314
    thread_t *t;
315
    unative_t uspace_addr;
315
    unative_t uspace_addr;
316
    unative_t to_copy;
316
    unative_t to_copy;
317
    void *buffer;
317
    void *buffer;
318
    int rc;
318
    int rc;
319
 
319
 
320
    printf("debug_regs_read()\n");
320
    LOG("debug_regs_read()\n");
321
 
321
 
322
    t = (thread_t *) IPC_GET_ARG2(call->data);
322
    t = (thread_t *) IPC_GET_ARG2(call->data);
323
    buffer = malloc(sizeof(istate_t), 0);
323
    buffer = malloc(sizeof(istate_t), 0);
324
 
324
 
325
    rc = udebug_regs_read(t, buffer);
325
    rc = udebug_regs_read(t, buffer);
326
    if (rc < 0) {
326
    if (rc < 0) {
327
        IPC_SET_RETVAL(call->data, rc);
327
        IPC_SET_RETVAL(call->data, rc);
328
        ipc_answer(&TASK->kernel_box, call);
328
        ipc_answer(&TASK->kernel_box, call);
329
        return;
329
        return;
330
    }
330
    }
331
 
331
 
332
    /*
332
    /*
333
     * Make use of call->buffer to transfer data to caller's userspace
333
     * Make use of call->buffer to transfer data to caller's userspace
334
     */
334
     */
335
 
335
 
336
    uspace_addr = IPC_GET_ARG3(call->data);
336
    uspace_addr = IPC_GET_ARG3(call->data);
337
    to_copy = sizeof(istate_t);
337
    to_copy = sizeof(istate_t);
338
 
338
 
339
    IPC_SET_RETVAL(call->data, 0);
339
    IPC_SET_RETVAL(call->data, 0);
340
    /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
340
    /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
341
       same code in process_answer() can be used
341
       same code in process_answer() can be used
342
       (no way to distinguish method in answer) */
342
       (no way to distinguish method in answer) */
343
    IPC_SET_ARG1(call->data, uspace_addr);
343
    IPC_SET_ARG1(call->data, uspace_addr);
344
    IPC_SET_ARG2(call->data, to_copy);
344
    IPC_SET_ARG2(call->data, to_copy);
345
 
345
 
346
    call->buffer = buffer;
346
    call->buffer = buffer;
347
 
347
 
348
    ipc_answer(&TASK->kernel_box, call);
348
    ipc_answer(&TASK->kernel_box, call);
349
}
349
}
350
 
350
 
351
static void udebug_receive_regs_write(call_t *call)
351
static void udebug_receive_regs_write(call_t *call)
352
{
352
{
353
    thread_t *t;
353
    thread_t *t;
354
    void *uspace_data;
354
    void *uspace_data;
355
    int rc;
355
    int rc;
356
 
356
 
357
    t = (thread_t *) IPC_GET_ARG2(call->data);
357
    t = (thread_t *) IPC_GET_ARG2(call->data);
358
    uspace_data = (void *)IPC_GET_ARG3(call->data);
358
    uspace_data = (void *)IPC_GET_ARG3(call->data);
359
 
359
 
360
    rc = udebug_regs_write(t, call->buffer);
360
    rc = udebug_regs_write(t, call->buffer);
361
    if (rc < 0) {
361
    if (rc < 0) {
362
        IPC_SET_RETVAL(call->data, rc);
362
        IPC_SET_RETVAL(call->data, rc);
363
        ipc_answer(&TASK->kernel_box, call);
363
        ipc_answer(&TASK->kernel_box, call);
364
        return;
364
        return;
365
    }
365
    }
366
 
366
 
367
    /* Set answer values */
367
    /* Set answer values */
368
 
368
 
369
    IPC_SET_RETVAL(call->data, 0);
369
    IPC_SET_RETVAL(call->data, 0);
370
    free(call->buffer);
370
    free(call->buffer);
371
    call->buffer = NULL;
371
    call->buffer = NULL;
372
 
372
 
373
    ipc_answer(&TASK->kernel_box, call);
373
    ipc_answer(&TASK->kernel_box, call);
374
}
374
}
375
 
375
 
376
/** Process an MEM_READ call.
376
/** Process an MEM_READ call.
377
 *
377
 *
378
 * Reads memory of the current (debugged) task.
378
 * Reads memory of the current (debugged) task.
379
 * @param call  The call structure.
379
 * @param call  The call structure.
380
 */
380
 */
381
static void udebug_receive_mem_read(call_t *call)
381
static void udebug_receive_mem_read(call_t *call)
382
{
382
{
383
    unative_t uspace_dst;
383
    unative_t uspace_dst;
384
    unative_t uspace_src;
384
    unative_t uspace_src;
385
    unsigned size;
385
    unsigned size;
386
    void *buffer;
386
    void *buffer;
387
    int rc;
387
    int rc;
388
 
388
 
389
    uspace_dst = IPC_GET_ARG2(call->data);
389
    uspace_dst = IPC_GET_ARG2(call->data);
390
    uspace_src = IPC_GET_ARG3(call->data);
390
    uspace_src = IPC_GET_ARG3(call->data);
391
    size = IPC_GET_ARG4(call->data);
391
    size = IPC_GET_ARG4(call->data);
392
 
392
 
393
    rc = udebug_mem_read(uspace_src, size, &buffer);
393
    rc = udebug_mem_read(uspace_src, size, &buffer);
394
    if (rc < 0) {
394
    if (rc < 0) {
395
        IPC_SET_RETVAL(call->data, rc);
395
        IPC_SET_RETVAL(call->data, rc);
396
        ipc_answer(&TASK->kernel_box, call);
396
        ipc_answer(&TASK->kernel_box, call);
397
        return;
397
        return;
398
    }
398
    }
399
 
399
 
400
    IPC_SET_RETVAL(call->data, 0);
400
    IPC_SET_RETVAL(call->data, 0);
401
    /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
401
    /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
402
       same code in process_answer() can be used
402
       same code in process_answer() can be used
403
       (no way to distinguish method in answer) */
403
       (no way to distinguish method in answer) */
404
    IPC_SET_ARG1(call->data, uspace_dst);
404
    IPC_SET_ARG1(call->data, uspace_dst);
405
    IPC_SET_ARG2(call->data, size);
405
    IPC_SET_ARG2(call->data, size);
406
    call->buffer = buffer;
406
    call->buffer = buffer;
407
 
407
 
408
    ipc_answer(&TASK->kernel_box, call);
408
    ipc_answer(&TASK->kernel_box, call);
409
}
409
}
410
 
410
 
411
static void udebug_receive_mem_write(call_t *call)
411
static void udebug_receive_mem_write(call_t *call)
412
{
412
{
413
    unative_t uspace_dst;
413
    unative_t uspace_dst;
414
    unsigned size;
414
    unsigned size;
415
    int rc;
415
    int rc;
416
 
416
 
417
    printf("udebug_receive_mem_write()\n");
417
    LOG("udebug_receive_mem_write()\n");
418
 
418
 
419
    uspace_dst = IPC_GET_ARG3(call->data);
419
    uspace_dst = IPC_GET_ARG3(call->data);
420
    size = IPC_GET_ARG4(call->data);
420
    size = IPC_GET_ARG4(call->data);
421
 
421
 
422
    rc = udebug_mem_write(uspace_dst, call->buffer, size);
422
    rc = udebug_mem_write(uspace_dst, call->buffer, size);
423
    if (rc < 0) {
423
    if (rc < 0) {
424
        IPC_SET_RETVAL(call->data, rc);
424
        IPC_SET_RETVAL(call->data, rc);
425
        ipc_answer(&TASK->kernel_box, call);
425
        ipc_answer(&TASK->kernel_box, call);
426
        return;
426
        return;
427
    }
427
    }
428
 
428
 
429
    IPC_SET_RETVAL(call->data, 0);
429
    IPC_SET_RETVAL(call->data, 0);
430
    free(call->buffer);
430
    free(call->buffer);
431
    call->buffer = NULL;
431
    call->buffer = NULL;
432
 
432
 
433
    ipc_answer(&TASK->kernel_box, call);
433
    ipc_answer(&TASK->kernel_box, call);
434
}
434
}
435
 
435
 
436
 
436
 
437
/** Handle a debug call received on the kernel answerbox.
437
/** Handle a debug call received on the kernel answerbox.
438
 *
438
 *
439
 * This is called by the kbox servicing thread. Verifies that the sender
439
 * This is called by the kbox servicing thread. Verifies that the sender
440
 * is indeed the debugger and calls the appropriate processing function.
440
 * is indeed the debugger and calls the appropriate processing function.
441
 */
441
 */
442
void udebug_call_receive(call_t *call)
442
void udebug_call_receive(call_t *call)
443
{
443
{
444
    int debug_method;
444
    int debug_method;
445
 
445
 
446
    debug_method = IPC_GET_ARG1(call->data);
446
    debug_method = IPC_GET_ARG1(call->data);
447
 
447
 
448
    if (debug_method != UDEBUG_M_BEGIN) {
448
    if (debug_method != UDEBUG_M_BEGIN) {
449
        /*
449
        /*
450
         * Verify that the sender is this task's debugger.
450
         * Verify that the sender is this task's debugger.
451
         * Note that this is the only thread that could change
451
         * Note that this is the only thread that could change
452
         * TASK->debugger. Therefore no locking is necessary
452
         * TASK->debugger. Therefore no locking is necessary
453
         * and the sender can be safely considered valid until
453
         * and the sender can be safely considered valid until
454
         * control exits this function.
454
         * control exits this function.
455
         */
455
         */
456
        if (TASK->udebug.debugger != call->sender) {
456
        if (TASK->udebug.debugger != call->sender) {
457
            IPC_SET_RETVAL(call->data, EINVAL);
457
            IPC_SET_RETVAL(call->data, EINVAL);
458
            ipc_answer(&TASK->kernel_box, call);
458
            ipc_answer(&TASK->kernel_box, call);
459
            return;
459
            return;
460
        }
460
        }
461
    }
461
    }
462
 
462
 
463
    switch (debug_method) {
463
    switch (debug_method) {
464
    case UDEBUG_M_BEGIN:
464
    case UDEBUG_M_BEGIN:
465
        udebug_receive_begin(call);
465
        udebug_receive_begin(call);
466
        break;
466
        break;
467
    case UDEBUG_M_END:
467
    case UDEBUG_M_END:
468
        udebug_receive_end(call);
468
        udebug_receive_end(call);
469
        break;
469
        break;
470
    case UDEBUG_M_SET_EVMASK:
470
    case UDEBUG_M_SET_EVMASK:
471
        udebug_receive_set_evmask(call);
471
        udebug_receive_set_evmask(call);
472
        break;
472
        break;
473
    case UDEBUG_M_GO:
473
    case UDEBUG_M_GO:
474
        udebug_receive_go(call);
474
        udebug_receive_go(call);
475
        break;
475
        break;
476
    case UDEBUG_M_STOP:
476
    case UDEBUG_M_STOP:
477
        udebug_receive_stop(call);
477
        udebug_receive_stop(call);
478
        break;
478
        break;
479
    case UDEBUG_M_THREAD_READ:
479
    case UDEBUG_M_THREAD_READ:
480
        udebug_receive_thread_read(call);
480
        udebug_receive_thread_read(call);
481
        break;
481
        break;
482
    case UDEBUG_M_ARGS_READ:
482
    case UDEBUG_M_ARGS_READ:
483
        udebug_receive_args_read(call);
483
        udebug_receive_args_read(call);
484
        break;
484
        break;
485
    case UDEBUG_M_REGS_READ:
485
    case UDEBUG_M_REGS_READ:
486
        udebug_receive_regs_read(call);
486
        udebug_receive_regs_read(call);
487
        break;
487
        break;
488
    case UDEBUG_M_REGS_WRITE:
488
    case UDEBUG_M_REGS_WRITE:
489
        udebug_receive_regs_write(call);
489
        udebug_receive_regs_write(call);
490
        break;
490
        break;
491
    case UDEBUG_M_MEM_READ:
491
    case UDEBUG_M_MEM_READ:
492
        udebug_receive_mem_read(call);
492
        udebug_receive_mem_read(call);
493
        break;
493
        break;
494
    case UDEBUG_M_MEM_WRITE:
494
    case UDEBUG_M_MEM_WRITE:
495
        udebug_receive_mem_write(call);
495
        udebug_receive_mem_write(call);
496
        break;
496
        break;
497
    }
497
    }
498
}
498
}
499
 
499
 
500
/** @}
500
/** @}
501
 */
501
 */
502
 
502