Subversion Repositories Kolibri OS

Rev

Rev 425 | Rev 465 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
425 victor 1
$Revision: 431 $
431 serge 2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3
;;                                                              ;;
4
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
5
;; Distributed under terms of the GNU General Public License    ;;
6
;;                                                              ;;
7
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8
 
40 halyavin 9
; diamond, 2006
10
sys_debug_services:
66 diamond 11
	cmp	eax, 9
40 halyavin 12
	ja	@f
13
	jmp	dword [sys_debug_services_table+eax*4]
14
@@:	ret
15
sys_debug_services_table:
16
	dd	debug_set_event_data
17
	dd	debug_getcontext
18
	dd	debug_setcontext
19
	dd	debug_detach
20
	dd	debug_suspend
21
	dd	debug_resume
22
	dd	debug_read_process_memory
23
	dd	debug_write_process_memory
24
	dd	debug_terminate
66 diamond 25
	dd	debug_set_drx
40 halyavin 26
 
27
debug_set_event_data:
28
; in: ebx = pointer
29
; destroys eax
379 serge 30
        mov     eax, [CURRENT_TASK]
40 halyavin 31
	shl	eax, 8
380 serge 32
        mov     [eax+SLOT_BASE+APPDATA.dbg_event_mem], ebx
40 halyavin 33
	ret
34
 
35
get_debuggee_slot:
36
; in: ebx=PID
37
; out: CF=1 if error
38
;      CF=0 and eax=slot*0x20 if ok
39
; out: interrupts disabled
40
	cli
41
	mov	eax, ebx
42
	call	pid_to_slot
43
	test	eax, eax
44
	jz	.ret_bad
45
	shl	eax, 5
46
	push	ebx
379 serge 47
        mov     ebx, [CURRENT_TASK]
380 serge 48
        cmp     [SLOT_BASE+eax*8+APPDATA.debugger_slot], ebx
40 halyavin 49
	pop	ebx
50
	jnz	.ret_bad
51
;	clc	; automatically
52
	ret
53
.ret_bad:
54
	stc
55
	ret
56
 
57
debug_detach:
58
; in: ebx=pid
59
; destroys eax,ebx
60
	call	get_debuggee_slot
61
	jc	.ret
380 serge 62
        and     dword [eax*8+SLOT_BASE+APPDATA.debugger_slot], 0
40 halyavin 63
	call	do_resume
64
.ret:
65
	sti
66
	ret
67
 
68
debug_terminate:
69
; in: ebx=pid
70
	call	get_debuggee_slot
71
	jc	debug_detach.ret
72
	mov	ebx, eax
73
	shr	ebx, 5
74
	push	2
75
	pop	eax
76
	jmp	sys_system
77
 
78
debug_suspend:
79
; in: ebx=pid
80
; destroys eax,ebx
81
	call	get_debuggee_slot
82
	jc	.ret
379 serge 83
        mov     bl, [CURRENT_TASK+eax+TASKDATA.state] ; process state
40 halyavin 84
	test	bl, bl
85
	jz	.1
86
	cmp	bl, 5
87
	jnz	.ret
88
	mov	bl, 2
379 serge 89
.2:     mov     [CURRENT_TASK+eax+TASKDATA.state], bl
40 halyavin 90
.ret:
91
	sti
92
	ret
93
.1:
94
	inc	ebx
95
	jmp	.2
96
 
97
do_resume:
379 serge 98
        mov     bl, [CURRENT_TASK+eax+TASKDATA.state]
40 halyavin 99
	cmp	bl, 1
100
	jz	.1
101
	cmp	bl, 2
102
	jnz	.ret
103
	mov	bl, 5
379 serge 104
.2:     mov     [CURRENT_TASK+eax+TASKDATA.state], bl
40 halyavin 105
.ret:	ret
106
.1:	dec	ebx
107
	jmp	.2
108
 
109
debug_resume:
110
; in: ebx=pid
111
; destroys eax,ebx
112
	call	get_debuggee_slot
113
	jc	.ret
114
	call	do_resume
115
.ret:	sti
116
	ret
117
 
118
debug_getcontext:
119
; in:
120
; ebx=pid
121
; ecx=sizeof(CONTEXT)
122
; edx->CONTEXT
123
; destroys eax,ecx,edx,esi,edi
124
	cmp	ecx, 28h
125
	jnz	.ret
126
	add	edx, std_application_base_address
127
	push	ebx
128
	mov	ebx, edx
129
	call	check_region
130
	pop	ebx
131
	dec	eax
132
	jnz	.ret
133
	call	get_debuggee_slot
134
	jc	.ret
135
	imul	eax, tss_step/32
136
	add	eax, tss_data
137
	mov	edi, edx
237 serge 138
        cmp     [eax+TSS._cs], app_code
40 halyavin 139
	jnz	.ring0
237 serge 140
        lea     esi, [eax+TSS._eip]
40 halyavin 141
	shr	ecx, 2
142
	rep	movsd
143
	jmp	.ret
144
.ring0:
145
; note that following code assumes that all interrupt/exception handlers
146
; saves ring-3 context by push ds es, pushad in this order
237 serge 147
        mov     esi, [eax+TSS._esp0]
40 halyavin 148
; top of ring0 stack: ring3 stack ptr (ss+esp), iret data (cs+eip+eflags), ds, es, pushad
149
	sub	esi, 8+12+8+20h
150
	lodsd
151
	mov	[edi+24h], eax
152
	lodsd
153
	mov	[edi+20h], eax
154
	lodsd
155
	mov	[edi+1Ch], eax
156
	lodsd
157
	lodsd
158
	mov	[edi+14h], eax
159
	lodsd
160
	mov	[edi+10h], eax
161
	lodsd
162
	mov	[edi+0Ch], eax
163
	lodsd
164
	mov	[edi+8], eax
165
	add	esi, 8
166
	lodsd
167
	mov	[edi], eax
168
	lodsd
169
	lodsd
170
	mov	[edi+4], eax
171
	lodsd
172
	mov	[edi+18h], eax
173
.ret:
174
	sti
175
	ret
176
 
177
debug_setcontext:
178
; in:
179
; ebx=pid
180
; ecx=sizeof(CONTEXT)
181
; edx->CONTEXT
182
; destroys eax,ecx,edx,esi,edi
183
	cmp	ecx, 28h
184
	jnz	.ret
185
	add	edx, std_application_base_address
186
	push	ebx
187
	mov	ebx, edx
188
	call	check_region
189
	pop	ebx
190
	dec	eax
191
	jnz	.ret
192
	call	get_debuggee_slot
193
	jc	.stiret
194
	imul	eax, tss_step/32
195
	add	eax, tss_data
196
	mov	esi, edx
237 serge 197
        cmp     [eax+TSS._cs], app_code
40 halyavin 198
	jnz	.ring0
237 serge 199
        lea     edi, [eax+TSS._eip]
40 halyavin 200
	shr	ecx, 2
201
	rep	movsd
202
	jmp	.stiret
203
.ring0:
237 serge 204
        mov     edi, [eax+TSS._esp0]
40 halyavin 205
	sub	edi, 8+12+8+20h
206
	mov	eax, [esi+24h]
207
	stosd
208
	mov	eax, [esi+20h]
209
	stosd
210
	mov	eax, [esi+1Ch]
211
	stosd
212
	scasd
213
	mov	eax, [esi+14h]
214
	stosd
215
	mov	eax, [esi+10h]
216
	stosd
217
	mov	eax, [esi+0Ch]
218
	stosd
219
	mov	eax, [esi+8]
220
	stosd
221
	add	edi, 8
222
	mov	eax, [esi]
223
	stosd
224
	scasd
225
	mov	eax, [esi+4]
226
	stosd
227
	mov	eax, [esi+18h]
228
	stosd
229
.stiret:
230
	sti
231
.ret:
232
	ret
233
 
66 diamond 234
debug_set_drx:
235
	call	get_debuggee_slot
236
	jc	.errret
237
	mov	ebp, eax
380 serge 238
        lea     eax, [eax*8+SLOT_BASE+APPDATA.dbg_regs]
66 diamond 239
; [eax]=dr0, [eax+4]=dr1, [eax+8]=dr2, [eax+C]=dr3
240
; [eax+10]=dr7
241
	add	edx, std_application_base_address
242
	jc	.errret
243
	cmp	cl, 3
244
	ja	.errret
245
	mov	ebx, dr7
246
	shr	ebx, cl
247
	shr	ebx, cl
248
	test	ebx, 2		; bit 1+2*index = G0..G3, global break enable
249
	jnz	.errret2
250
	test	ch, ch
251
	jns	.new
252
; clear breakpoint
253
	movzx	ecx, cl
254
	add	ecx, ecx
255
	and	dword [eax+ecx*2], 0	; clear DR
256
	btr	dword [eax+10h], ecx	; clear L bit
257
	test	byte [eax+10h], 55h
258
	jnz	.okret
259
	imul	eax, ebp, tss_step/32
237 serge 260
        and     byte [eax + tss_data + TSS._trap], not 1
66 diamond 261
.okret:
262
	and	dword [esp+36], 0
263
	sti
264
	ret
265
.errret:
266
	sti
267
	mov	dword [esp+36], 1
268
	ret
269
.errret2:
270
	sti
271
	mov	dword [esp+36], 2
272
	ret
273
.new:
274
; add new breakpoint
275
; cl=index; ch=flags; edx=address
276
	test	ch, 0xF0
277
	jnz	.errret
278
	mov	bl, ch
279
	and	bl, 3
280
	cmp	bl, 2
281
	jz	.errret
282
	mov	bl, ch
283
	shr	bl, 2
284
	cmp	bl, 2
285
	jz	.errret
286
	test	dl, bl
287
	jnz	.errret
288
	or	byte [eax+10h+1], 3	; set GE and LE flags
289
	movzx	ebx, ch
290
	movzx	ecx, cl
291
	add	ecx, ecx
292
	bts	dword [eax+10h], ecx	; set L flag
293
	add	ecx, ecx
294
	mov	[eax+ecx], edx		; set DR
295
	shl	ebx, cl
296
	mov	edx, 0xF
297
	shl	edx, cl
298
	not	edx
299
	and	[eax+10h+2], dx
300
	or	[eax+10h+2], bx		; set R/W and LEN fields
301
	imul	eax, ebp, tss_step/32
237 serge 302
        or      byte [eax + tss_data + TSS._trap], 1
66 diamond 303
	jmp	.okret
304
 
40 halyavin 305
debug_read_process_memory:
306
; in:
307
; ebx=pid
308
; ecx=length
309
; esi->buffer in debugger
310
; edx=address in debuggee
44 halyavin 311
; out: [esp+36]=sizeof(read)
40 halyavin 312
; destroys all
313
	add	esi, std_application_base_address
314
	push	ebx
315
	mov	ebx, esi
316
	call	check_region
317
	pop	ebx
318
	dec	eax
44 halyavin 319
	jnz	.err
40 halyavin 320
	call	get_debuggee_slot
44 halyavin 321
	jc	.err
322
	shr	eax, 5
40 halyavin 323
	mov	ebx, esi
324
	call	read_process_memory
325
	sti
44 halyavin 326
	mov	dword [esp+36], eax
40 halyavin 327
	ret
44 halyavin 328
.err:
329
	or	dword [esp+36], -1
330
	ret
40 halyavin 331
 
332
debug_write_process_memory:
333
; in:
334
; ebx=pid
335
; ecx=length
336
; esi->buffer in debugger
337
; edx=address in debuggee
44 halyavin 338
; out: [esp+36]=sizeof(write)
40 halyavin 339
; destroys all
340
	add	esi, std_application_base_address
341
	push	ebx
342
	mov	ebx, esi
343
	call	check_region
344
	pop	ebx
345
	dec	eax
44 halyavin 346
	jnz	debug_read_process_memory.err
40 halyavin 347
	call	get_debuggee_slot
44 halyavin 348
	jc	debug_read_process_memory.err
349
	shr	eax, 5
40 halyavin 350
	mov	ebx, esi
351
	call	write_process_memory
352
	sti
44 halyavin 353
	mov	[esp+36], eax
40 halyavin 354
	ret
355
 
356
debugger_notify:
357
; in: eax=debugger slot
358
;     ecx=size of debug message
359
;     [esp+4]..[esp+4+ecx]=message
360
; interrupts must be disabled!
361
; destroys all general registers
362
; interrupts remain disabled
66 diamond 363
	xchg	ebp, eax
63 halyavin 364
	mov	edi, [timer_ticks]
365
	add	edi, 500	; 5 sec timeout
40 halyavin 366
.1:
66 diamond 367
	mov	eax, ebp
368
	shl	eax, 8
380 serge 369
        mov     edx, [SLOT_BASE+eax+APPDATA.dbg_event_mem]
40 halyavin 370
	test	edx, edx
371
	jz	.ret
372
; read buffer header
373
	push	ecx
374
	push	eax
375
	push	eax
376
	mov	eax, ebp
377
	mov	ebx, esp
378
	mov	ecx, 8
379
	call	read_process_memory
380
	cmp	eax, ecx
381
	jz	@f
382
	add	esp, 12
383
	jmp	.ret
384
@@:
385
	cmp	dword [ebx], 0
386
	jg	@f
387
.2:
388
	pop	ecx
389
	pop	ecx
390
	pop	ecx
379 serge 391
        cmp     dword [CURRENT_TASK], 1
66 diamond 392
	jnz	.notos
63 halyavin 393
	cmp	[timer_ticks], edi
394
	jae	.ret
66 diamond 395
.notos:
40 halyavin 396
	sti
397
	call	change_task
398
	cli
399
	jmp	.1
400
@@:
401
	mov	ecx, [ebx+8]
402
	add	ecx, [ebx+4]
403
	cmp	ecx, [ebx]
404
	ja	.2
405
; advance buffer position
406
	push	ecx
407
	mov	ecx, 4
408
	sub	ebx, ecx
409
	mov	eax, ebp
410
	add	edx, ecx
411
	call	write_process_memory
412
	pop	eax
413
; write message
414
	mov	eax, ebp
415
	add	edx, ecx
416
	add	edx, [ebx+8]
417
	add	ebx, 20
418
	pop	ecx
419
	pop	ecx
420
	pop	ecx
421
	call	write_process_memory
422
; new debug event
423
	mov	eax, ebp
424
	shl	eax, 8
380 serge 425
        or      byte [SLOT_BASE+eax+APPDATA.event_mask+1], 1      ; set flag 100h
40 halyavin 426
.ret:
427
	ret
66 diamond 428
 
429
debug_exc:
430
; int 1 = #DB
431
	save_ring3_context
113 diamond 432
	cld
66 diamond 433
	mov	ax, os_data
434
	mov	ds, ax
435
	mov	es, ax
436
	mov	eax, dr6
437
	test	ax, ax
438
	jns	@f
439
; this is exception from task switch
440
; set DRx registers for task and continue
379 serge 441
        mov     eax, [CURRENT_TASK]
66 diamond 442
	shl	eax, 8
380 serge 443
        add     eax, SLOT_BASE+APPDATA.dbg_regs
66 diamond 444
	mov	ecx, [eax+0]
445
	mov	dr0, ecx
446
	mov	ecx, [eax+4]
447
	mov	dr1, ecx
448
	mov	ecx, [eax+8]
449
	mov	dr2, ecx
450
	mov	ecx, [eax+0Ch]
451
	mov	dr3, ecx
452
	xor	ecx, ecx
453
	mov	dr6, ecx
454
	mov	ecx, [eax+10h]
455
	mov	dr7, ecx
456
	restore_ring3_context
457
	iretd
458
@@:
459
	push	eax
460
	xor	eax, eax
461
	mov	dr6, eax
462
; test if debugging
463
	cli
379 serge 464
        mov     eax, [CURRENT_TASK]
66 diamond 465
	shl	eax, 8
380 serge 466
        mov     eax, [SLOT_BASE+eax+APPDATA.debugger_slot]
66 diamond 467
	test	eax, eax
468
	jnz	.debug
469
	sti
470
; not debuggee => say error and terminate
471
	add	esp, 28h+4
472
	mov	[error_interrupt], 1
473
	call	show_error_parameters
379 serge 474
        mov     edx, [TASK_BASE]
115 poddubny 475
	mov	byte [edx+TASKDATA.state], 4
66 diamond 476
	jmp	change_task
477
.debug:
478
; we are debugged process, notify debugger and suspend ourself
479
; eax=debugger PID
480
	pop	edx
481
	mov	ebx, dr7
482
	mov	cl, not 1
483
.l1:
484
	test	bl, 1
485
	jnz	@f
486
	and	dl, cl
487
@@:
488
	shr	ebx, 2
489
	add	cl, cl
490
	inc	ecx
491
	cmp	cl, not 10h
492
	jnz	.l1
493
	push	edx	; DR6 image
379 serge 494
        mov     ecx, [TASK_BASE]
115 poddubny 495
	push	dword [ecx+TASKDATA.pid]	; PID
66 diamond 496
	push	12
497
	pop	ecx
498
	push	3	; 3 = debug exception
499
	call	debugger_notify
500
	pop	ecx
501
	pop	ecx
502
	pop	ecx
379 serge 503
        mov     edx, [TASK_BASE]
115 poddubny 504
	mov	byte [edx+TASKDATA.state], 1	; suspended
66 diamond 505
	call	change_task
506
	restore_ring3_context
507
	iretd