Subversion Repositories Kolibri OS

Rev

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

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