Closed deverac closed 2 years ago
I studied the code around this bug some. As I expected, the bug goes back all the way to (at least) FreeDOS Debug/X 1.13, the most recent full ancestor of both today's Debug/X and my lDebug. (Version 1.13 was the last one that still uses the NASM dialect.) The bug you found in the current version presents a little differently than the one in version 1.13 as well as lDebug, but it is the same underlying bug.
This is the code in question, in the current Debug/X:
call dohack ;set debuggee's int 23/24
call writemem ;write AL at BX:(E)DX
mov di,offset run2324 ;debuggee's int 23/24
call prehak1 ;copy things back
call unhack ;set debugger's int 23/24
;--- End the loop over bytes.
ee14:
inc dx ;increment offset
mov di,offset line_out
cmp al,CR
je ee16 ;if done
The interrupt 23h/24h vector hacks are an area of the debugger that I still don't have a full grasp of, but you can confirm that both prehak1
and unhack
too do not modify ax
. Therefore, when falling through into ee14
after having written a new value, the value returned by writemem
is retained in al
. In this more recent version, the value is the same as the value written (or attempted to be written).
Here's the same spots in version 1.13 of 2008-02-27: Around ee14
, prehak1
, unhack
, and writemem
. Note that writemem
here returns the prior value read from the memory location.
Here are the ones in the current lDebug commit: Around ee14
. (NB there is another copy of ee14
around for some reason, left over from some experimentation; this one is the one in use.) Note that we accept CR (0Dh), NUL (00h), and period (2Eh) as inputs ending E interactive mode here, unlike the original Debug/X. And here's prehak1
, unhack
, and writemem
. Like in version 1.13 writemem
returns the prior value read from memory upon success. (It can also return the value trying to be written in some failure cases.)
The part around ee14
is almost exactly the same in the 2010-10-24 initial commit of lDebug (still called NDebug at the time). Like in version 1.13, here only CR (0Dh) is accepted as ending the E interactive mode.
As for a fix, I tend towards adding mov al, 32
(blank) before the ee14
label so that after falling through after writemem
we get a value in al
that indicates to continue to the next byte in E interactive mode. I still have to study the functioning of this part more in order to make sure this is right, though.
We actually should exit E interactive mode (or "enter mode" as Microsoft calls it) when a new value has been entered and then Enter is pressed. Testing the pre-release version 1.28 Debug it appears that after entering a value (other than 0Dh) and then pressing Enter, the interactive mode is not exited.
I fixed all the bugs I noticed in lDebug. Some of them are shared by current (and older) Debug/X. Here's the user-readable list of changes for the upcoming Release 4. Here's the most recent commit addressing these and here's the oldest commit of the bunch; you can follow their "parents" or "children" links to browse through the entire series.
The following bugs are still present with your patch:
e 100
Enter
2
6
Enter
, interactive enter mode is not exited:-e 100
092B:0100 90.26 90.
e 110
Enter
3
8
-
Blank
, the new value terminated by minus is not written:-e 110
092B:0110 90.38-
092B:010F 90.
092B:0110 90.
e es:FFFF
Enter
Blank
, the offset wraps around the 64 KiB boundary instead of proceeding into the second 64 KiB block. (This example uses the dpmioffs example program. As I'm using dosemu2, DebugX refuses to install its DPMI entrypoint handler, which is why I step into the DPMI entrypoint. (As opposed to DebugX, my lDebugX checks whether the entrypoint can be intercepted instead of refusing on any dosemu.))C:\>debugx.com dpmioffs.com
-g
Protected mode breakpoint at 015Dh.
32-bit code segment breakpoint at 016Fh.
32-bit data selector breakpoint at 01AAh.
Unexpected breakpoint interrupt
AX=0200 BX=00E6 CX=0205 DX=000A SP=FFFC BP=0000 SI=02E4 DI=F500
DS=0B1A ES=1B1B SS=0B1A CS=0B1A IP=013E NV UP EI PL ZR NA PE NC
0B1A:013E 89E5 MOV BP,SP
-t
AX=0200 BX=00E6 CX=0205 DX=000A SP=FFFC BP=FFFC SI=02E4 DI=F500
DS=0B1A ES=1B1B SS=0B1A CS=0B1A IP=0140 NV UP EI PL ZR NA PE NC
0B1A:0140 B80100 MOV AX,0001
-
AX=0001 BX=00E6 CX=0205 DX=000A SP=FFFC BP=FFFC SI=02E4 DI=F500
DS=0B1A ES=1B1B SS=0B1A CS=0B1A IP=0143 NV UP EI PL ZR NA PE NC
0B1A:0143 FF5E00 CALL FAR [BP+00]
-
AX=0001 BX=00E6 CX=0205 DX=000A SP=FFF8 BP=FFFC SI=02E4 DI=F500
DS=0B1A ES=1B1B SS=0B1A CS=F000 IP=F500 NV UP EI PL ZR NA PE NC
F000:F500 53 PUSH BX
-
AX=0001 BX=00E6 CX=0205 DX=000A SP=FFFC BP=FFFC SI=02E4 DI=F500
DS=00AF ES=00B7 SS=00AF CS=00FF IP=0146 NV UP EI NG NZ AC PO NC
00FF:0146 7315 JAE 015D
#g 1AA
Welcome in 32-bit protected mode.
AX=0008 BX=010F CX=0010 DX=FFFF SP=FFFC BP=FFFC SI=0308 DI=F500
DS=00AF ES=010F SS=00AF CS=00FF IP=01AA NV UP EI PL ZR NA PE NC
00FF:000001AA 26A100000100 MOV EAX,ES:[00010000]
#e es:FFFF
010F:0000FFFF C0.
010F:00000000 86.
#
Thanks for the bug report! I didn't use the patch but fixed it by a simple push/pop of register AX. Seems to work ok.
the increment/decrement 16-bit offset bug in interactive e cmd is fixed in v1.29
While in 'Edit memory' mode, entering 'd', 'D', '0d', '0D' will correctly set the memory to '0D', but then will incorrectly return the user to the DEBUG prompt instead of prompting for the next byte.
This may not be the 'correct' way to fix this bug; perhaps someone with more knowledge of the code base may provide a better solution.