Michael writes:
>When you examine another process's stack and find that it is waiting on an
>intrinsic call, how do you determine what parameters the program has passed to
>the intrinsic? For instance, suppose you see that a process is waiting on an
>FREAD and you want to know what file number it is FREADing on.
>How do you find out?
>
>Using the above example what I would normally do is go to the ?FREAD level and
>then do a DR and see if any of the registers look like either
...
>I am hoping that someone has a better method for
>reading intrinsic parameters off of another persons stack.
...
>BTW, I have demoed the CSEQ product from Lund, and althought it gives register
>and memory addresses for intrinsic parameters, they seem to be only good if
> you are running the program yourself and set a breakpoint on the
> intrinsic you are trying to examine.
>
>Any help in this matter would be appreciated....ok Stan???? :)
Although CSEQ has other features (e.g., for AIF:PE use), the primary purpose
is to show you where parameters to intrinsics are located when you
are "sitting" at the start of the procedure (via a breakpoint). Of course,
they are only "good" at that spot ... prior to calling the intrinsic, your
code hasn't loaded the registers, and after entering it, the intrinsic's
code changes the registers.
So...let's take the FREAD example Michael asked about. Note: FREAD is
nasty, as it is optimized code that doesn't happen to store the
register-based parameters into memory at the entry of the procedure.
Assuming PIN #232 is waiting on an FREAD...
I logon as MANAGER.SYS and:
:debug
pin #232;tr,i,d
PC=a.0017170c enable_int+$2c
NM* 0) SP=41837ec8 RP=a.0108c6b0 notify_dispatcher.block_current_process+$31c
NM 1) SP=41837ec8 RP=a.0108eb10 notify_dispatcher+$264
NM 2) SP=41837e48 RP=a.001a1bd0 wait_for_active_port+$ec
NM 3) SP=41837d48 RP=a.001a2850 receive_from_port+$534
NM 4) SP=41837cc8 RP=a.003381e8 extend_receive+$494
NM 5) SP=41837ac8 RP=a.00326cc4 rendezvousio.get_specific+$158
NM 6) SP=41837948 RP=a.00327028 rendezvousio+$1d8
NM 7) SP=41837888 RP=a.00322180 waitforio+$150
NM 8) SP=41837508 RP=a.0032201c ?waitforio+$8
export stub: a.00e1a9c4 arg_regs+$28
NM 9) SP=418373c8 RP=a.00ddd4ec nm_switch_code+$94c
NM a) SP=41837298 RP=a.00dc9bec Compatability_Mode
(switch marker frame)
CM SYS % 226.404 SWITCH'TO'NM'+%4 (Mitroc CCG) SUSER1
CM * 0) SYS % 226.404 SWITCH'TO'NM'+%4 (Mitroc CCG) SUSER1
CM 1) SYS % 162.10557 WAITFORIO+%36 (Mitroc CCG) CMSWITCH
CM 2) SYS % 165.5657 IOMOVE+%1137 (Mitroc CCG) FSSEG1
CM 3) SYS % 165.2521 F'READ'+%410 (MitroC CCL) FSSEG1
CM 4) switch marker (Mitroc CCG)
NM b) SP=41836f58 RP=a.00a2017c invoke_cm_procedure+$11c
NM c) SP=41836d68 RP=a.00b1be30 tm_cms_type_mgr.tm_fread_cms+$218
NM d) SP=41836ca8 RP=a.00b1f2a4 tm_cms_type_mgr+$190
NM e) SP=41836b68 RP=a.00bebb18 tm_tape+$84
NM f) SP=41836ae8 RP=a.01110e14 fread_nm+$810
NM 10) SP=41836a28 RP=a.00e0a788 FREAD+$d4
NM 11) SP=41836628 RP=a.00e0a680 ?FREAD+$8
export stub: 691.00056124
NM 12) SP=418364e8 RP=691.0005a468
NM 13) SP=418362c8 RP=691.00000000
(end of NM stack)
Note that my instance of Debug didn't know the name for the
last couple of code addresses (691.00056124 and 691.0005a468) ...
that's because they're addresses within whatever program
PIN #232 is running ... *NOT* within the process my Debug is
running from.
If I'd said, gee..PIN #232 is the program FSYS.PUB.SIELER. Let's
do the debugging this way:
:run fsys.pub.sieler; debug
pin #232; tr,i,d
I'd get:
...(same as before)...
NM 10) SP=41836a28 RP=a.00e0a788 FREAD+$d4
NM 11) SP=41836628 RP=a.00e0a680 ?FREAD+$8
export stub: 691.00056124 test+$35a4
NM 12) SP=418364e8 RP=691.0005a468 EX_PROGRAM
NM 13) SP=418362c8 RP=691.00000000
(end of NM stack)
Ok...let's determine the file# that FREAD was passed.
According to CSEQ, FREAD looks like:
:cseq fread
Function FREAD (
filenum : int16 ; {R26}
target : anyvar record ; {(skip R25)
R23, R24}
{Address type = LongAddr}
tcount : int16 ) {SP-$0032}
:= length : int16 {R28}
{ CCE: ok }
{ CCG: denied, EOF encountered }
{ CCL: error }
{tcount is > 0 for 16-bit words, < 0 for bytes }
{length: 0 is returned for NOWAIT files. }
{ length is always non-negative, and in whatever }
{ units tcount was in. }
uncheckable_anyvar
so, the file number is in R26 *when we are at the entry of FREAD*.
Are we at the entry of FREAD? No. ... at best, we can ask the
debugger to logically position us at FREAD+$d4 ... but by that spot in
the code, the register R26 might no longer contain the file #.
Let's check:
dc FREAD, d4 / 4 + 1
SYS $a.e0a6b4
00e0a6b4 FREAD 0000400e BREAK (nmdebug bp)
00e0a6b8 FREAD+$4 6fc30280 STWM 3,320(0,30)
00e0a6bc FREAD+$8 6bc43d89 STW 4,-316(0,30)
00e0a6c0 FREAD+$c 6bc53d91 STW 5,-312(0,30)
00e0a6c4 FREAD+$10 6bd73d21 STW 23,-368(0,30)
00e0a6c8 FREAD+$14 6bd83d29 STW 24,-364(0,30)
00e0a6cc FREAD+$18 08000240 OR 0,0,0
00e0a6d0 FREAD+$1c 6bc03e29 STW 0,-236(0,30)
00e0a6d4 FREAD+$20 37c33d81 LDO -320(30),3
00e0a6d8 FREAD+$24 90786000 COMICLR,<=0,3,24
00e0a6dc FREAD+$28 34180002 LDO 1(0),24
00e0a6e0 FREAD+$2c c7f840ca BB,<,N 24,31,FREAD+$98
00e0a6e4 FREAD+$30 d4a61bde ZDEPI 3,1,2,5
00e0a6e8 FREAD+$34 40b92122 LDB 4241(0,5),25
00e0a6ec FREAD+$38 c7f9c0b2 BB,>=,N 25,31,FREAD+$98
00e0a6f0 FREAD+$3c 341f2000 LDO 4096(0),31
00e0a6f4 FREAD+$40 00009820 MTSP 0,2
00e0a6f8 FREAD+$44 4bfd8008 LDW 4(2,31),29
00e0a6fc FREAD+$48 6bdd3e51 STW 29,-216(0,30)
00e0a700 FREAD+$4c 4bdf3e51 LDW -216(0,30),31
00e0a704 FREAD+$50 4bd93e59 LDW -212(0,30),25
00e0a708 FREAD+$54 47fc07dc LDH 1006(0,31),28
00e0a70c FREAD+$58 4bf70070 LDW 56(0,31),23
00e0a710 FREAD+$5c 37810002 LDO 1(28),1
00e0a714 FREAD+$60 67e107dc STH 1,1006(0,31)
00e0a718 FREAD+$64 47f607dc LDH 1006(0,31),22
00e0a71c FREAD+$68 6be000e0 STW 0,112(0,31)
00e0a720 FREAD+$6c 8ec22048 COMIBF,= 1,22,FREAD+$98
00e0a724 FREAD+$70 6be000e8 STW 0,116(0,31)
00e0a728 FREAD+$74 42e4000c LDB 6(0,23),4
00e0a72c FREAD+$78 d49f1cdf DEPI -1,25,1,4
00e0a730 FREAD+$7c 0ee4120c STBS 4,6(0,23)
00e0a734 FREAD+$80 43f506a6 LDB 851(0,31),21
00e0a738 FREAD+$84 63e006a0 STB 0,848(0,31)
00e0a73c FREAD+$88 63e006a2 STB 0,849(0,31)
00e0a740 FREAD+$8c 63e006a4 STB 0,850(0,31)
00e0a744 FREAD+$90 d6a00cff DEP 0,24,1,21
00e0a748 FREAD+$94 63f506a6 STB 21,851(0,31)
00e0a74c FREAD+$98 d35a1ff0 EXTRS 26,31,16,26 <--a usage of r26
00e0a750 FREAD+$9c 4bd73d21 LDW -368(0,30),23
00e0a754 FREAD+$a0 4bd83d29 LDW -364(0,30),24
00e0a758 FREAD+$a4 47d43d1d LDH -370(0,30),20
00e0a75c FREAD+$a8 4bc43d59 LDW -340(0,30),4
00e0a760 FREAD+$ac d2831ff0 EXTRS 20,31,16,3
00e0a764 FREAD+$b0 d4421a1f ZDEPI 1,15,1,2
00e0a768 FREAD+$b4 d0851bfe EXTRU 4,31,2,5
00e0a76c FREAD+$b8 6bc03f89 STW 0,-60(0,30)
00e0a770 FREAD+$bc 6bc33f91 STW 3,-56(0,30)
00e0a774 FREAD+$c0 6bc23f99 STW 2,-52(0,30)
00e0a778 FREAD+$c4 6bc53f81 STW 5,-64(0,30)
00e0a77c FREAD+$c8 23f4a014 LDIL $aa9000,31
00e0a780 FREAD+$cc e7e02cb0 BLE 1624(4,31) <-- call to fread_nm
00e0a784 FREAD+$d0 081f0242 OR 31,0,2
00e0a788 FREAD+$d4 081c0243 OR 28,0,3 <-- return from fread_nm
Examining the code at the very start (first 3 to 20 instructions), we
see that the parameters in registers R23 and R24 are saved into the
stack (FREAD+$10 and FREAD+$14), *but* R26 isn't saved into the stack :(
Instead, we see that R26 is used once (sign extended from 16-bit integer
to 32-bit integer) at FREAD+$98, and then "passed" into fread_nm.
(BTW, AVATAR would have shown FREAD+$cc as a call to fread_nm).
We can't just do:
lev 11
= r26
to find out what R26 is, because the "lev" command in Debug (which
logically "unwinds" the stack), can only "restore" some of the
registers (basically R3..R18, R27, R30, SR4)....but not R23..R26.
So, to find out what R26 was at the entry, we can either look to see
what was passed to fread_nm in R26 (hoping that fread_nm saved it), *or*
look at the code that generated the value in R26 and then called FREAD.
Let's do the latter...
lev 12 /* look at code that called FREAD */
dc pc - 40, 44/4 /* display prior 14 or so instructions */
PROG $691.560e4
000560e4 test+$3564 44960110 LDH 136(0,4),22
000560e8 test+$3568 d2d61ff0 EXTRS 22,31,16,22
000560ec test+$356c 0ac00416 SUB 0,22,22
000560f0 test+$3570 64b6004c STH 22,38(0,5)
000560f4 test+$3574 d2c81ff0 EXTRS 22,31,16,8
000560f8 test+$3578 44b30060 LDH 48(0,5),19
000560fc test+$357c 449400f0 LDH 120(0,4),20
00056100 test+$3580 08940654 SH1ADD 20,4,20
00056104 test+$3584 028010b5 LDSID (0,20),21
00056108 test+$3588 44b6004c LDH 38(0,5),22
0005610c test+$358c 6bd63f99 STW 22,-52(0,30)
00056110 test+$3590 08140258 OR 20,0,24
00056114 test+$3594 08150257 OR 21,0,23
00056118 test+$3598 d27a1ff0 EXTRS 19,31,16,26
0005611c test+$359c e8590bfb BL,N ?HELP+$35c,2 <-- call to FREAD
00056120 test+$35a0 08000240 OR 0,0,0
00056124 test+$35a4 d39c1ff0 EXTRS 28,31,16,28
Well, test+$3598 built the value passed to FREAD in r26...by taking the
value in R19. Looking backwards further, we see that test+$3578
build the value in R19 (assuming some code we don't see didn't branch into
the middle of the above code). It got R19 by loading a 16-bit value (LDH)
from R5 + #48 ... alright! Let's look at that memory address, and hope
that no one changed that halfword of memory since the LDH:
dv r5+#48
VIRT $101.4163991c $ 000b0000
$000b000 looks like a BIG file number...but wait, the "dv" command always
takes the virtual address, rounds down to a multiple of 4, and displays
data in groups of 4 bytes at a time. To get just the 16-bits we want
(probably either $000b or $0000), we could look at the value of the
address r5+#48, and determine which half of the 32-bit word is being
loaded, or we could let Debug do it for us:
= [s16 r5+#48]
$b
So...file $b (probably).
We can double check this by looking in the opposite direction. FREAD
called fread_nm, passing the file number in R26. The first few
instructions in fread_nm are:
dc fread_nm, 10
SYS $a.1110604
01110604 fread_nm 6bc23fd9 STW 2,-20(0,30)
01110608 fread_nm+$4 6fc30800 STWM 3,1024(0,30)
0111060c fread_nm+$8 6bc43809 STW 4,-1020(0,30)
01110610 fread_nm+$c 6bc53811 STW 5,-1016(0,30)
01110614 fread_nm+$10 6bc63819 STW 6,-1012(0,30)
01110618 fread_nm+$14 6bc73821 STW 7,-1008(0,30)
0111061c fread_nm+$18 6bc83829 STW 8,-1004(0,30)
01110620 fread_nm+$1c 6bc93831 STW 9,-1000(0,30)
01110624 fread_nm+$20 6bca3839 STW 10,-996(0,30)
01110628 fread_nm+$24 6bcb3841 STW 11,-992(0,30)
0111062c fread_nm+$28 6bcc3849 STW 12,-988(0,30)
01110630 fread_nm+$2c 6bcd3851 STW 13,-984(0,30)
01110634 fread_nm+$30 6bce3859 STW 14,-980(0,30)
01110638 fread_nm+$34 6bcf3861 STW 15,-976(0,30)
0111063c fread_nm+$38 6bd03869 STW 16,-972(0,30)
01110640 fread_nm+$3c 67da37bd STH 26,-1058(0,30)
Notice fread_nm+$3c...it stores R26 into memory! If we assume that the
value hasn't changed since then (probably a safe assumption), we
can do:
lev 10
dc pc /* to visually verify that Debug positioned
/* us in the "fread_nm" area
SYS $a.1110e14
01110e14 fread_nm+$810 4bdf38d9 LDW -916(0,30),31
/* Yep...we got the right "lev" level
= [s16 sp-#1058]
$b
This confirms that the file# is $b (or #11).
--
Stan Sieler [log in to unmask]
http://www.allegro.com/sieler.html
|