source: vendor/emx/current/src/dos/ptrace.asm

Last change on this file was 18, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 15.7 KB
Line 
1;
2; PTRACE.ASM -- Implement ptrace()
3;
4; Copyright (c) 1995 by Eberhard Mattes
5;
6; This file is part of emx.
7;
8; emx is free software; you can redistribute it and/or modify it
9; under the terms of the GNU General Public License as published by
10; the Free Software Foundation; either version 2, or (at your option)
11; any later version.
12;
13; emx is distributed in the hope that it will be useful,
14; but WITHOUT ANY WARRANTY; without even the implied warranty of
15; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16; GNU General Public License for more details.
17;
18; You should have received a copy of the GNU General Public License
19; along with emx; see the file COPYING. If not, write to
20; the Free Software Foundation, 59 Temple Place - Suite 330,
21; Boston, MA 02111-1307, USA.
22;
23; See emx.asm for a special exception.
24;
25
26 INCLUDE EMX.INC
27 INCLUDE SIGNAL.INC
28 INCLUDE PROCESS.INC
29 INCLUDE PMINT.INC
30 INCLUDE DEBUG.INC
31 INCLUDE HEADERS.INC
32 INCLUDE ERRORS.INC
33
34SV_DATA SEGMENT
35
36 TALIGN 2
37POKE_VALUE DD ?
38
39REG_TABLE STRUCT
40RT_ADDR DD ?
41RT_PROC DW ?
42RT_LEN DB ?
43REG_TABLE ENDS
44
45PTRACE_REGS REG_TABLE <USER_AREA.U_GS, PROCESS.P_GS, 2>
46 REG_TABLE <USER_AREA.U_FS, PROCESS.P_FS, 2>
47 REG_TABLE <USER_AREA.U_ES, PROCESS.P_ES, 2>
48 REG_TABLE <USER_AREA.U_DS, PROCESS.P_DS, 2>
49 REG_TABLE <USER_AREA.U_EDI, PROCESS.P_EDI, 4>
50 REG_TABLE <USER_AREA.U_ESI, PROCESS.P_ESI, 4>
51 REG_TABLE <USER_AREA.U_EBP, PROCESS.P_EBP, 4>
52 REG_TABLE <USER_AREA.U_ESP, PROCESS.P_ESP, 4>
53 REG_TABLE <USER_AREA.U_EBX, PROCESS.P_EBX, 4>
54 REG_TABLE <USER_AREA.U_EDX, PROCESS.P_EDX, 4>
55 REG_TABLE <USER_AREA.U_ECX, PROCESS.P_ECX, 4>
56 REG_TABLE <USER_AREA.U_EAX, PROCESS.P_EAX, 4>
57 REG_TABLE <USER_AREA.U_EIP, PROCESS.P_EIP, 4>
58 REG_TABLE <USER_AREA.U_CS, PROCESS.P_CS, 2>
59 REG_TABLE <USER_AREA.U_EFL, PROCESS.P_EFLAGS, 4>
60 REG_TABLE <USER_AREA.U_UESP, PROCESS.P_ESP, 4>
61 REG_TABLE <USER_AREA.U_SS, PROCESS.P_SS, 2>
62 REG_TABLE <-1, 0, 0>
63
64SV_DATA ENDS
65
66
67SV_CODE SEGMENT
68
69 ASSUME CS:SV_CODE, DS:NOTHING
70
71 PUBLIC PTRACE
72
73 TALIGN 2
74PTRACE_JMP DW PTRACE00 ; PTRACE_TRACEME
75 DW PTRACE01 ; PTRACE_PEEKTEXT
76 DW PTRACE02 ; PTRACE_PEEKDATA
77 DW PTRACE03 ; PTRACE_PEEKUSER
78 DW PTRACE04 ; PTRACE_POKETEXT
79 DW PTRACE05 ; PTRACE_POKEDATA
80 DW PTRACE06 ; PTRACE_POKEUSER
81 DW PTRACE07 ; PTRACE_RESUME
82 DW PTRACE08 ; PTRACE_EXIT
83 DW PTRACE09 ; PTRACE_STEP
84 DW PTRACE0A ; PTRACE_SESSION
85PTRACE_LAST = ($-PTRACE_JMP)/2-1
86
87;
88; Bits in EFLAGS that may be changed by ptrace()
89;
90EFLAGS_USER = 0000110011010101B ; OF, DF, SF, ZF, AF, PF, CF
91
92; ----------------------------------------------------------------------------
93; AX=7F08H: ptrace()
94;
95; Debugging support
96;
97; In: EBX request code (see /emx/include/sys/ptrace.h)
98; EDI pid
99; EDX address
100; ECX data
101;
102; Out: EAX result
103; ECX errno, if non-zero
104;
105; ----------------------------------------------------------------------------
106 ASSUME DS:SV_DATA
107 ASSUME BP:PTR ISTACKFRAME
108
109 TALIGN 4
110PTRACE: MOV ECX, I_ECX ; ECX := data
111 MOV I_ECX, 0 ; No error
112 MOV EDI, I_EBX
113 CMP EDI, 0 ; PTRACE_TRACEME?
114 JE SHORT SYS08_JMP ; Yes -> ignore pid
115 CMP EDI, PTRACE_LAST ; Valid request code?
116 JA SHORT SYS08_IO_ERR ; No -> I/O error
117 MOV EAX, I_EDI ; Get process ID
118 CALL FIND_PROCESS ; Lookup process table entry
119 CMP BX, NO_PROCESS ; Found?
120 JE SHORT SYS08_ESRCH ; No -> no such process
121 ASSUME BX:PTR PROCESS
122 TEST [BX].P_FLAGS, PF_DEBUG ; Process in debugging mode?
123 JZ SHORT SYS08_IO_ERR ; No -> I/O error
124SYS08_JMP: MOV ESI, I_EDX ; ESI := Address
125 JMP PTRACE_JMP[EDI*2] ; Dispatch
126
127SYS08_ESRCH: MOV I_ECX, ESRCH ; No such process
128 JMP SHORT SYS08_ERROR ; Failure
129
130SYS08_EINVAL: MOV I_ECX, EINVAL ; Invalid argument
131 JMP SHORT SYS08_ERROR ; Failure
132
133SYS08_IO_ERR: MOV I_ECX, EIO ; I/O error
134SYS08_ERROR: MOV I_EAX, -1 ; Failure
135 RET
136
137
138;
139; Request code 0 is used (by Unix) to switch the current process to debugging
140; mode. This is not used by emx. Ignored.
141;
142PTRACE00: MOV I_EAX, 0
143 RET
144
145;
146; Request code 10 is used to switch to and from the child session. Only
147; for OS/2.
148;
149PTRACE0A: MOV I_EAX, 0
150 RET
151
152
153;
154; Request codes 1 and 2 are used for reading a word from code/data space.
155;
156PTRACE01: ; Same as PTRACE02
157PTRACE02: CALL PTRACE_ADDR ; Check address
158 .386P
159 SLDT DI ; Save LDT
160 LLDT [BX].P_LDT ; Get LDT of child process
161 MOV ES, [BX].P_DS
162 MOV EAX, ES:[ESI] ; Read the word
163 LLDT DI ; Note 2
164 MOV I_EAX, EAX ; and return it in EAX
165 RET
166 .386
167;
168; Note 2: It is essential, that the LDT of the client process is active
169; until after accessing the memory of the client process.
170; Why is this necessary, the 386 uses the LDT only when loading
171; a segment register; the LDT isn't referenced after loading
172; the segment register? Correct. But accessing the memory of
173; the child could cause a page fault (or an interrupt may occur
174; between restoring the LDTR and accessing memory). The exception
175; (or interrupt) handler saves all the segment registers (and the
176; LDTR). When returning to the interrupted code, the segment registers
177; are restored using the LDTR saved on entry to the interrupt routine.
178; Therefore, one must be very cautious when switching LDTs!
179;
180
181;
182; Request code 3 is used for reading from the process table (registers).
183;
184 TALIGN 2
185PTRACE03: MOV EAX, ESI
186 CMP EAX, USER_AREA.U_AR0 ; Pointer to registers?
187 JE SHORT PEEKU_AR0 ; Yes -> special handling
188 CMP EAX, USER_AREA.U_FPVALID ; Floating point flag?
189 JE SHORT PEEKU_FPVALID ; Yes -> special handling
190 CMP EAX, USER_AREA.U_FPSTATUS ; Floating point status?
191 JE SHORT PEEKU_FPSTATUS ; Yes -> special handling
192 CMP EAX, USER_AREA.U_FPSTATE ; Floating point?
193 JB SHORT PEEKU_10
194 CMP EAX, USER_AREA.U_FPSTATE + 108 - 4
195 JBE SHORT PEEKU_FLOAT ; Yes -> special handling
196PEEKU_10: CALL USER_ADDR ; Convert address
197 JNZ SYS08_IO_ERR
198 ASSUME SI:PTR REG_TABLE
199 MOVZX CX, [SI].RT_LEN ; Get size of register (bytes)
200 MOV SI, [SI].RT_PROC ; Pointer in process structure
201PEEKU_11: ADD SI, BX
202 MOV I_EAX, 0 ; Clear return value
203 LEA DI, I_EAX
204PEEKU_12: LODS BYTE PTR DS:[SI]
205 MOV SS:[DI], AL
206 INC DI
207 LOOP PEEKU_12
208 ASSUME SI:NOTHING
209 RET
210
211;
212; A MASM bug strikes here if DWORD PTR isn't used: MASM omits the operand
213; size prefix and inserts 4 bytes of immediate data.
214;
215PEEKU_AR0: MOV I_EAX, DWORD PTR (USER_AREA.U_REGS + KERNEL_U_ADDR)
216 RET
217
218PEEKU_FPSTATUS: MOV I_EAX, 0
219 RET
220
221PEEKU_FPVALID:
222 IF FLOATING_POINT
223 MOV I_EAX, 0FFH
224 ELSE
225 MOV I_EAX, 0
226 ENDIF
227 RET
228
229PEEKU_FLOAT:
230 IF FLOATING_POINT
231 FNOP ; Save 387 registers
232 ADD ESI, PROCESS.P_CW - USER_AREA.U_FPSTATE
233 MOV CX, 4
234 JMP SHORT PEEKU_11
235 ELSE
236 JMP SYS08_IO_ERR
237 ENDIF
238
239;
240; Request code 6 is used for writing to the process table (registers).
241;
242; Note: Only some bits of EFLAG can be written. Segment registers and
243; 387 registers cannot be written.
244;
245 TALIGN 2
246PTRACE06: MOV POKE_VALUE, ECX
247 MOV EAX, ESI
248 CALL USER_ADDR ; Convert address
249 JNZ SYS08_IO_ERR
250 ASSUME SI:PTR REG_TABLE
251 MOVZX CX, [SI].RT_LEN
252 MOV DI, [SI].RT_PROC
253 CMP DI, PROCESS.P_EFLAGS
254 JNE SHORT POKEU_10
255 ADD DI, BX
256 MOV EAX, [DI]
257 MOV ECX, POKE_VALUE
258 AND ECX, EFLAGS_USER ; Keep only changable bits
259 AND EAX, NOT EFLAGS_USER ; Keep only unchangabe bits
260 OR EAX, ECX ; Insert new bits
261 MOV [DI], EAX
262 JMP SHORT POKEU_ZERO
263
264 ASSUME SI:NOTHING
265
266POKEU_10: ADD DI, BX
267 LEA SI, POKE_VALUE
268 MOV_ES_DS
269 REP MOVSB
270POKEU_ZERO: MOV I_EAX, 0 ; Return 0
271 RET
272
273;
274; Request codes 4 and 5 are used for writing a word to code/data space.
275;
276PTRACE04: ; Same as PTRACE05
277PTRACE05:
278 CALL PTRACE_ADDR ; Check address
279 .386P
280 SLDT DI ; Save LDT
281 LLDT [BX].P_LDT ; Get LDT of child process
282 MOV ES, [BX].P_DS
283 MOV ES:[ESI], ECX ; Write the word
284 LLDT DI ; Note 2
285 MOV I_EAX, ECX ; and return it
286 RET
287 .386
288
289;
290; Request code 8 is used for terminating a process.
291;
292PTRACE08: CALL REMOVE_PROCESS ; Kill child process
293 RET
294
295;
296; Request code 9 is used for single stepping a process.
297;
298; Note: ECX (data) is passed to PTRACE_SWITCH
299;
300PTRACE09: CALL PTRACE_SWITCH ; Switch to child process
301 JC SYS08_EINVAL ; Error ->
302 CALL DEBUG_STEP ; Set EFLAGS for stepping
303 RET
304
305
306;
307; Request code 7 is used for resuming a process.
308;
309; Note: ECX (data) is passed to PTRACE_SWITCH
310;
311PTRACE07: CALL PTRACE_SWITCH ; Switch to child process
312 JC SYS08_EINVAL ; Error ->
313 CALL DEBUG_RESUME ; Set EFLAGS for resuming
314 CALL BREAK_AFTER_IRET ; For debugging debuggers
315 RET
316
317 ASSUME BX:NOTHING
318
319;
320; Switch to the program being debugged.
321;
322; In: BX Pointer to process table entry of child process
323; ECX 4th argument (DATA) of ptrace(): signal number
324; SS:BP Interrupt stack frame
325;
326; Out: CY Error (invalid signal number)
327;
328 ASSUME BX:PTR PROCESS
329PTRACE_SWITCH PROC NEAR
330 MOV [BX].P_SIG_PENDING, 0 ; Cancel pending signals
331 JECXZ NOSIG ; No signal -> skip
332 CMP ECX, SIGNALS ; Valid signal number?
333 JAE SHORT FAIL ; No -> failure
334 CMP SIG_VALID[EAX], FALSE
335 JE SHORT FAIL ; No -> failure
336 BTS [BX].P_SIG_PENDING, ECX ; Generate signal
337NOSIG: PUSH BX ; Child process table entry
338 MOV BX, PROCESS_PTR
339 MOV (PROCESS PTR [BX]).P_STATUS, PS_WAIT_PTRACE
340 CALL SAVE_PROCESS ; Save current process
341 POP BX
342 MOV PROCESS_PTR, BX ; Switch to child process
343 MOV PROCESS_SIG, BX
344 CALL REST_PROCESS
345 CLC ; No error
346 RET
347
348FAIL: STC ; Error
349 RET
350PTRACE_SWITCH ENDP
351 ASSUME BX:NOTHING
352
353;
354; Check address
355;
356; In: DS:BX Pointer to process table entry
357; ESI Address
358;
359 ASSUME BX:PTR PROCESS
360PTRACE_ADDR PROC NEAR
361 PUSH EAX
362 PUSH EDX
363 MOV EAX, ESI
364 ADD EAX, 3 ; Last byte of word
365 JC SHORT PTRACE_ADDR_ERR ; Beyond end -> error
366;
367; Try code area: [BX].P_CODE_OFF ... [BX].P_CODE_OFF + [BX].P_CODE_SIZE - 1
368;
369 MOV EDX, [BX].P_TEXT_OFF
370 CMP ESI, EDX
371 JB SHORT PTRACE_ADDR_1 ; Not in code area ->
372 ADD EDX, [BX].P_TEXT_SIZE
373 CMP EAX, EDX
374 JBE SHORT PTRACE_ADDR_OK ; In code area ->
375;
376; Try data area: [BX].P_DATA_OFF ... [BX].P_BRK - 1
377;
378PTRACE_ADDR_1: CMP ESI, [BX].P_DATA_OFF
379 JB SHORT PTRACE_ADDR_2 ; Not in data area ->
380 CMP EAX, [BX].P_BRK
381 JB SHORT PTRACE_ADDR_OK ; In data area ->
382;
383; Try stack: [BX].P_STACK_ADDR - [BX].P_STACK_SIZE ... [BX].P_STACK_ADDR - 1
384;
385PTRACE_ADDR_2: MOV EDX, [BX].P_STACK_ADDR
386 CMP EAX, EDX
387 JAE SHORT PTRACE_ADDR_3 ; Not in stack ->
388 SUB EDX, [BX].P_STACK_SIZE
389 CMP ESI, EDX
390 JAE SHORT PTRACE_ADDR_OK
391PTRACE_ADDR_3:
392PTRACE_ADDR_ERR:POP EDX ; Restore registers
393 POP EAX
394 ADD SP, 2 ; Remove return address
395 JMP SYS08_IO_ERR
396
397PTRACE_ADDR_OK: POP EDX
398 POP EAX
399 RET
400 ASSUME BX:NOTHING
401PTRACE_ADDR ENDP
402
403;
404;
405;
406 TALIGN 2
407USER_ADDR PROC NEAR
408 LEA SI, PTRACE_REGS
409 ASSUME SI:PTR REG_TABLE
410USER_ADDR_1: CMP [SI].RT_ADDR, -1 ; End of table?
411 JE USER_ADDR_ERR
412 CMP EAX, [SI].RT_ADDR
413 JE SHORT USER_ADDR_OK
414 ADD SI, SIZE REG_TABLE
415 JMP SHORT USER_ADDR_1
416USER_ADDR_ERR: CMP [SI].RT_ADDR, 0 ; Set NZ
417USER_ADDR_OK: RET
418 ASSUME SI:NOTHING
419USER_ADDR ENDP
420
421
422SV_CODE ENDS
423
424 END
Note: See TracBrowser for help on using the repository browser.