├── .gitignore ├── History.txt ├── Readme.txt ├── Samples ├── Dos1.asm ├── Dos132.asm ├── Dos2.asm ├── Dos2.lbc ├── Dos3.c ├── Dos3.def ├── Dos4.c ├── mDos1.bat ├── mDos132.bat ├── mDos2.bat ├── mDos3.bat └── mDos4.bat ├── dip_src ├── cvinfo.h ├── cvld.c ├── cvmisc.c ├── cvsym.c ├── cvtype.c └── readme.txt ├── mad_src └── x86 │ ├── readme.txt │ └── x86trace.c ├── trap_src ├── dosr │ ├── dosacc.c │ ├── readme.txt │ └── trap.asm └── dosx │ ├── dosxlink.c │ └── hx │ └── dos.trp │ └── makefile ├── ui_src └── dos │ └── uibios.c └── wv_src ├── dbgbrk.c ├── dbgexec.c ├── dbgmain.c ├── dbgprog.c ├── dbgtrace.c └── dsx ├── dsxscrn.c └── pcscrnio.h /.gitignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | Test 3 | ver 4 | -------------------------------------------------------------------------------- /History.txt: -------------------------------------------------------------------------------- 1 | 2 | Changes for HX OpenWatcom WD 3 | 4 | v1.2 07/2022 5 | - module stdosfil.obj now included in HXDEV16. 6 | - no longer any need to change HDPMI environment variable, HDPMI v3.20 7 | provides an API to change things dynamically. 8 | 9 | v1.1 07/2022 10 | 11 | - wv source added. 12 | - WD uses VESA functions to save/restore video state. 13 | - WD page flip directly programs CRT ( BIOS works rather bad in many emulations ). 14 | - check if current video mode is text has been simplified, since 15 | the old code has/had problems in DosEmu; works for VGA+VESA only! 16 | 17 | v1.0 12/2012 18 | 19 | - display/edit XMM registers ( std.trp ) 20 | - screen flip on INT instruction ( madx86.mad ) 21 | - interrupt flag set on program entry ( std.trp ) 22 | - register window on upper right corner ( default.dbg ) 23 | - crash in wd/wdw if cv S_BLOCKxx symbols in mod ( codeview.dll,codeview.dip ) 24 | 25 | -------------------------------------------------------------------------------- /Readme.txt: -------------------------------------------------------------------------------- 1 | 2 | 1. About 3 | 4 | This version of OpenWatcom's WD can debug programs written in C, C++ or 5 | assembly language. It has improved support for the MS CodeView debug format 6 | and hence is not restricted to Open Watcom, but should also work with 7 | MS C(++) compilers, both 16-bit and 32-bit, as long as the CodeView format 8 | is CV4 or CV5. 9 | 10 | The HX trap helper files supplied with the debugger should be able to 11 | handle DPMI mode switches. So they aren't restricted for debugging binaries 12 | in the usual HX formats ( that is, NE for 16-bit and PE/PX for 32-bit ), 13 | but may be able to handle any DOS binary. 14 | 15 | Although the focus of this package is to debug HX binaries, the default 16 | Open Watcom trap file, STD.TRP, is also supplied. So the debugger can also 17 | be used to debug DOS real-mode applications without the HX trap files; in 18 | this case, the /TR cmdline option isn't needed. Additionally, all files 19 | needed to debug CauseWay DOS extender binaries are also included. 20 | 21 | Supported debug formats are codeview and dwarf. The watcom debug format may 22 | also work, but hasn't been tested and file WATCOM.DIP, which contains the 23 | support for this format, isn't included. 24 | 25 | 26 | 2. Usage 27 | 28 | 2.1 Prepare for Debugging 29 | 30 | If symbolic debugging is wanted, both the compiler/assembler and linker 31 | have to be told that. If the debug information is in codeview format 32 | and OW wlink ( or jwlink ) is to be used as linker, the cvp option has 33 | to be set. 34 | 35 | If the program to debug is a protected-mode application, but in a format 36 | that cannot be handled by the HX program loaders ( NE, PE/PX ), DPMI host 37 | HDPMI should be at least v3.20; if this isn't the case, environment variable 38 | HDPMI=32 must not be set. 39 | 40 | 41 | 2.2 Debugging 42 | 43 | Start WD with the /tr=HX (32-bit) or /tr=HX16 (16-bit) option, depending 44 | what type of protected-mode application the program to debug is - if it is 45 | a real-mode program, both variants are ok and should behave identically. 46 | If no symbolic debug info has been created, the debugger will just stop at 47 | the program entry point of the executable. 48 | If the binary has been linked with symbolic debug info, the debugger will 49 | stop at main(). Be aware that this symbol (main) is also needed for assembly 50 | programs in this case. 51 | To debug graphic applications locally, WD has to be launched with the /swap 52 | cmdline option. 53 | 54 | 55 | 3. Modifications 56 | 57 | The files modified compared to Open Watcom v1.9 are: 58 | 59 | a) MADX86.MAD: 60 | - page swap in "trace" mode whenever an INT instruction is detected. 61 | 62 | b) STD.TRP: 63 | - allows to view and edit the XMM registers. 64 | - interrupt flag is enabled on debuggee's entry. 65 | 66 | c) DEFAULT.DBG: 67 | - initially shows the register window at the upper right corner - 68 | quite appropriate for assembly programs. 69 | 70 | d) CODEVIEW.DIP: improved support for the CodeView debug format. 71 | 72 | e) WD.EXE: VESA save/restore, text mode detection, ... 73 | 74 | 75 | 4. Creating the binaries 76 | 77 | You'll need: 78 | 79 | - the OpenWatcom v1.9 source 80 | - the HX runtime 81 | - the HX development package. 82 | 83 | a) Install HXDEV's Open Watcom support. See OWSUPP\Readme.txt 84 | for details. The Open Watcom linker wlink must know "system hxdos" 85 | and the HX startup modules must be in Watcom's lib386\dos directory. 86 | please verify that "system hxdos" (defined in file HX.LNK) has 87 | CSTRTDHR.OBJ as startup module ( that's for the Watcom calling 88 | convention ). 89 | 90 | 91 | b) Files to copy to the Open Watcom source tree: 92 | 93 | - dip_src/*.c to bld/dip/codeview/c 94 | - dip_src/*.h to bld/dip/codeview/h 95 | - mad_src/x86/*.c to bld/mad/x86/c 96 | - trap_src/dosr/*.asm to bld/trap/lcl/dos/dosr/asm 97 | - trap_src/dosr/*.c to bld/trap/lcl/dos/dosr/c 98 | - trap_src/dosx/*.c to bld/trap/lcl/dos/dosx/c 99 | - trap_src/dosx/hx to bld/trap/lcl/dos/dosx/hx 100 | - ui_src/dos/*.c to bld/ui/dos/c 101 | - wv_src/*.c to bld/wv/c 102 | - wv_src/dsx/*.c to bld/wv/dsx/c 103 | - wv_src/dsx/*.h to bld/wv/dsx/h 104 | 105 | c) Change file bld\build\mif\cproj.mif: 106 | 107 | line "lflags_dos_386 = sys dos4g" to "lflags_dos_386 = sys hxdos" 108 | 109 | d) (Re)build the Open Watcom project. Or, more specific: 110 | 111 | - run wmake in bld\dip\codeview\dos386 112 | - run wmake in bld\mad\dos386 113 | - run wmake in bld\trap\lcl\dos\dosr\dos.std 114 | - run wmake in bld\trap\lcl\dos\dosx\hx\dos.trp 115 | - run wmake in bld\ui\dos\dos386 116 | - run wmake in bld\wv\dsx\dos386 117 | 118 | e) Revert the change in file bld\build\mif\cproj.mif. 119 | 120 | 121 | japheth 122 | -------------------------------------------------------------------------------- /Samples/Dos1.asm: -------------------------------------------------------------------------------- 1 | 2 | ;--- 16bit DPMI application, linked as MZ. 3 | 4 | .286 5 | .model small 6 | .stack 2048 7 | .dosseg 8 | 9 | LF equ 10 10 | CR equ 13 11 | 12 | .data 13 | 14 | szHello db "welcome in protected-mode",CR,LF,0 15 | 16 | .code 17 | 18 | nop ; for WD, main must not start at offset 0 19 | 20 | main proc c 21 | mov si, offset szHello 22 | nextchar: 23 | lodsb 24 | and al,al 25 | jz done 26 | mov dl,al 27 | mov ah,2 28 | int 21h 29 | jmp nextchar 30 | done: 31 | ret 32 | main endp 33 | 34 | start: 35 | mov ax, @data 36 | mov ds, ax 37 | mov bx, ss 38 | sub bx, ax 39 | shl bx, 4 40 | mov ss, ax 41 | add sp, bx 42 | mov ax, 1687h ;DPMI host installed? 43 | int 2Fh 44 | and ax, ax 45 | jnz nohost 46 | push es ;save DPMI entry address 47 | push di 48 | and si, si ;requires host client-specific DOS memory? 49 | jz nomemneeded 50 | mov bx, si 51 | mov ah, 48h ;alloc DOS memory 52 | int 21h 53 | jc nomem 54 | mov es, ax 55 | nomemneeded: 56 | mov bp, sp 57 | mov ax, 0000 ;start a 16-bit client 58 | call far ptr [bp] 59 | jc initfailed 60 | add sp, 4 61 | call main 62 | mov ax, 4C00h ;normal client exit 63 | int 21h 64 | 65 | nohost: 66 | call error 67 | db "no DPMI host installed",CR,LF,'$' 68 | nomem: 69 | call error 70 | db "not enough DOS memory for initialisation",CR,LF,'$' 71 | initfailed: 72 | call error 73 | db "DPMI initialisation failed",CR,LF,'$' 74 | error: 75 | push cs 76 | pop ds 77 | pop dx 78 | mov ah, 9 79 | int 21h 80 | mov ax, 4C00h 81 | int 21h 82 | 83 | end start 84 | -------------------------------------------------------------------------------- /Samples/Dos132.asm: -------------------------------------------------------------------------------- 1 | 2 | ;--- 32bit DPMI application, linked as MZ. 3 | 4 | .386 5 | .model small 6 | .stack 2048 7 | .dosseg 8 | 9 | LF equ 10 10 | CR equ 13 11 | 12 | 13 | .data 14 | 15 | szWelcome db "welcome in protected-mode",CR,LF,0 16 | 17 | .code 18 | 19 | nop ; to make WD find it, main must not start at offset 0 20 | 21 | main proc 22 | mov esi, offset szWelcome 23 | nextchar: 24 | lodsb 25 | and al, al 26 | jz done 27 | mov dl, al 28 | mov ah, 2 29 | int 21h 30 | jmp nextchar 31 | done: 32 | ret 33 | main endp 34 | 35 | start: 36 | call main 37 | mov ax, 4C00h ;normal client exit 38 | int 21h 39 | 40 | ;--- the 16bit startup 41 | 42 | _TEXT16 segment use16 word public 'CODE' 43 | 44 | start16: 45 | mov ax, ss 46 | mov cx, es 47 | sub ax, cx 48 | mov bx, sp 49 | shr bx, 4 50 | inc bx 51 | add bx, ax 52 | mov ah, 4Ah ;free unused memory 53 | int 21h 54 | 55 | mov ax, 1687h ;DPMI host installed? 56 | int 2Fh 57 | and ax, ax 58 | jnz nohost 59 | push es ;save DPMI entry address 60 | push di 61 | and si, si ;requires host client-specific DOS memory? 62 | jz nomemneeded 63 | mov bx, si 64 | mov ah, 48h ;alloc DOS memory 65 | int 21h 66 | jc nomem 67 | mov es, ax 68 | nomemneeded: 69 | mov ax, DGROUP 70 | mov ds, ax 71 | mov bp, sp 72 | mov ax, 0001 ;start a 32-bit client 73 | call far ptr [bp] ;initial switch to protected-mode 74 | jc initfailed 75 | 76 | ;--- now in protected-mode 77 | 78 | ;--- create a 32bit code selector and jump to 32bit code 79 | 80 | mov cx, 1 81 | mov ax, 0 ;alloc descriptor 82 | int 31h 83 | mov bx, ax 84 | mov cx, _TEXT 85 | mov dx, cx 86 | shl dx, 4 87 | shr cx, 12 88 | mov ax, 7 ;set base address 89 | int 31h 90 | mov dx, -1 91 | mov cx, 0 92 | mov ax, 8 93 | int 31h ;set descriptor limit to 64 kB 94 | mov cx, cs 95 | lar cx, cx 96 | shr cx, 8 97 | or ch, 40h 98 | mov ax, 9 99 | int 31h ;set code descriptors attributes to 32bit 100 | push ebx 101 | push offset start 102 | retd ;jump to 32-bit code 103 | 104 | nohost: 105 | mov dx, offset dErr1 106 | jmp error 107 | nomem: 108 | mov dx, offset dErr2 109 | jmp error 110 | initfailed: 111 | mov dx, offset dErr3 112 | error: 113 | push cs 114 | pop ds 115 | mov ah, 9 116 | int 21h 117 | mov ax, 4C00h 118 | int 21h 119 | 120 | dErr1 db "no DPMI host installed",CR,LF,'$' 121 | dErr2 db "not enough DOS memory for initialisation",CR,LF,'$' 122 | dErr3 db "DPMI initialisation failed",CR,LF,'$' 123 | 124 | _TEXT16 ends 125 | 126 | end start16 127 | -------------------------------------------------------------------------------- /Samples/Dos2.asm: -------------------------------------------------------------------------------- 1 | 2 | ;--- this program is supposed to be linked as 16-bit NE binary. 3 | 4 | .model small 5 | .stack 1024 6 | 7 | .data 8 | 9 | text db 13,10,"Hello, world!",13,10,'$' 10 | 11 | .code 12 | 13 | nop ; for WD, "main" must not start at offset 0. 14 | 15 | ;--- OW WD needs a "main" if symbolic debugging is wanted! 16 | 17 | main proc 18 | mov ah, 09h 19 | mov dx, offset text 20 | int 21h 21 | ret 22 | main endp 23 | 24 | start: 25 | call main 26 | mov ax, 4c00h 27 | int 21h 28 | 29 | end start 30 | -------------------------------------------------------------------------------- /Samples/Dos2.lbc: -------------------------------------------------------------------------------- 1 | 2 | OP MODNAME=Dos2 3 | OP PROTMODE 4 | OP ALIGN=16 5 | OP STACK=5120 6 | OP HEAP=1024 7 | OP STUB=dpmist16.bin 8 | 9 | SEGMENT type code MOVEABLE 10 | SEGMENT type data MOVEABLE 11 | -------------------------------------------------------------------------------- /Samples/Dos3.c: -------------------------------------------------------------------------------- 1 | 2 | /* 16-bit C sample */ 3 | 4 | #include 5 | 6 | char *pTest = "Hello, world!\n"; 7 | 8 | int main( int argc, char *argv[] ) 9 | { 10 | printf( pTest ); 11 | return( 0 ); 12 | } 13 | -------------------------------------------------------------------------------- /Samples/Dos3.def: -------------------------------------------------------------------------------- 1 | 2 | NAME WINDOWCOMPAT 3 | 4 | STUB 'dpmist16.bin' 5 | 6 | PROTMODE 7 | 8 | DATA LOADONCALL MOVEABLE 9 | CODE LOADONCALL DISCARDABLE 10 | 11 | STACKSIZE 4096 12 | HEAPSIZE 2048 13 | 14 | -------------------------------------------------------------------------------- /Samples/Dos4.c: -------------------------------------------------------------------------------- 1 | 2 | /* 32-bit C sample */ 3 | 4 | #include 5 | 6 | char *pTest = "Hello, world!\n"; 7 | 8 | int main( int argc, char *argv[] ) 9 | { 10 | printf( pTest ); 11 | return( 0 ); 12 | } 13 | -------------------------------------------------------------------------------- /Samples/mDos1.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | jwasm -nologo -Zi Dos1.asm 3 | jwlink debug c format dos f Dos1.obj op q,cvp 4 | -------------------------------------------------------------------------------- /Samples/mDos132.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | jwasm -Zi dos132.asm 3 | jwlink debug c format dos f dos132.obj op q,m,cvp 4 | -------------------------------------------------------------------------------- /Samples/mDos2.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | jwasm -nologo -Zi Dos2.asm 3 | jwlink debug c format win dpmi f Dos2.obj op q,cvp @Dos2.lbc 4 | -------------------------------------------------------------------------------- /Samples/mDos3.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem 16-bit MS C/C++ 4 | rem there are a few peculiarities 5 | rem - module initapp is included ( defines dummy InitApp, called 6 | rem by the MS C startup code in slibcew ). 7 | rem - module stdosfil is needed to ensure that files 0, 1 and 2 are 8 | rem in text mode ( translation of LF to CR/LF ) 9 | rem - program patchne will mark the application as DPMI. 10 | rem these things are needed because the MS 16-bit VC provides 11 | rem a protected-mode library for Windows only ( slibcew.lib ). 12 | 13 | \msvc\bin\cl -nologo -c -Zi -I\msvc\include dos3.c 14 | \msvc\bin\link /A:16/NOLOGO/CO/NOD/MAP:F dos3 \hx\lib16\initapp \hx\lib16\stdosfil,,dos3.map,\msvc\lib\slibcew \hx\lib16\slx \hx\lib16\kernel16, dos3.def 15 | patchne Dos3.exe 16 | 17 | -------------------------------------------------------------------------------- /Samples/mDos4.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem using MS C(++) 4 | rem old style debug info (-Z7 instead of -Zi) is needed! 5 | rem jwlink's cvpack has problems with "new" MS debug info - to be fixed... 6 | rem \msvc71\bin\cl -nologo -c -Z7 -I\msvc71\include dos4.c 7 | 8 | rem using OW C 9 | 10 | \watcom\binnt\wcc386 -bc -bt=nt -d2 -i=\watcom\h\nt -i=\watcom\h dos4.c 11 | jwlink debug c format win pe hx f dos4.obj libpath \watcom\lib386\nt libpath \watcom\lib386 lib { \hx\lib\dkrnl32.lib \hx\lib\duser32.lib } op q,m,cvp,stub=dpmist32.bin 12 | 13 | -------------------------------------------------------------------------------- /dip_src/cvinfo.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Open Watcom Project 4 | * 5 | * Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved. 6 | * 7 | * ======================================================================== 8 | * 9 | * This file contains Original Code and/or Modifications of Original 10 | * Code as defined in and that are subject to the Sybase Open Watcom 11 | * Public License version 1.0 (the 'License'). You may not use this file 12 | * except in compliance with the License. BY USING THIS FILE YOU AGREE TO 13 | * ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is 14 | * provided with the Original Code and Modifications, and is also 15 | * available at www.sybase.com/developer/opensource. 16 | * 17 | * The Original Code and all software distributed under the License are 18 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 19 | * EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM 20 | * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR 22 | * NON-INFRINGEMENT. Please see the License for the specific language 23 | * governing rights and limitations under the License. 24 | * 25 | * ======================================================================== 26 | * 27 | * Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE 28 | * DESCRIBE IT HERE! 29 | * 30 | ****************************************************************************/ 31 | 32 | 33 | #ifndef DIP_CV 34 | 35 | #include "dip.h" 36 | #include "dipimp.h" 37 | #include "cv4w.h" 38 | 39 | enum { 40 | #define _CVREG( name, num ) CV_X86_##name = num, 41 | #include "cv4intl.h" 42 | #undef _CVREG 43 | #define _CVREG( name, num ) CV_AXP_##name = num, 44 | #include "cv4axp.h" 45 | CV_LAST_REG 46 | }; 47 | 48 | typedef unsigned long virt_mem; 49 | 50 | #define BLOCK_FACTOR( i, n ) (((i)+((n)-1))/(n)) 51 | 52 | #define MH_BASE 1 53 | #define MH_GBL ((imp_mod_handle)-1) 54 | 55 | struct imp_sym_handle { 56 | virt_mem handle; 57 | unsigned short len; 58 | imp_mod_handle im; 59 | virt_mem containing_type; 60 | virt_mem adjustor_type; 61 | unsigned long adjustor_offset; 62 | unsigned short mfunc_idx; 63 | }; 64 | 65 | struct imp_type_handle { 66 | virt_mem handle; 67 | unsigned short idx; 68 | unsigned short array_dim; 69 | }; 70 | 71 | struct imp_cue_handle { 72 | virt_mem file; 73 | virt_mem line; 74 | unsigned_16 pair; 75 | imp_mod_handle im; 76 | }; 77 | 78 | #define DIRECTORY_BLOCK_ENTRIES 256 79 | 80 | struct imp_image_handle { 81 | imp_image_handle *next_image; 82 | struct virt_page ***virt; 83 | unsigned vm_dir_num; 84 | dig_fhandle sym_file; 85 | unsigned long bias; 86 | cv_directory_entry **directory; 87 | unsigned dir_count; 88 | unsigned map_count; 89 | seg_desc *mapping; 90 | virt_mem types_base; 91 | mad_handle mad; 92 | }; 93 | 94 | typedef struct { 95 | type_kind k; 96 | unsigned size; 97 | void *valp; 98 | unsigned long int_val; /* only if k == TK_INTEGER */ 99 | } numeric_leaf; 100 | 101 | extern address NilAddr; 102 | 103 | extern imp_image_handle *ImageList; 104 | 105 | extern dip_status VMInit( imp_image_handle *, unsigned long ); 106 | extern void VMFini( imp_image_handle * ); 107 | extern void *VMBlock( imp_image_handle *, virt_mem, unsigned ); 108 | extern void *VMRecord( imp_image_handle *, virt_mem ); 109 | extern unsigned VMShrink(void); 110 | 111 | typedef walk_result (DIR_WALKER)( imp_image_handle *, cv_directory_entry *, void * ); 112 | extern walk_result WalkDirList( imp_image_handle *, DIR_WALKER *, void * ); 113 | extern cv_directory_entry *FindDirEntry( imp_image_handle *, imp_mod_handle, unsigned ); 114 | 115 | extern void LocationCreate( location_list *, location_type, void * ); 116 | extern void LocationAdd( location_list *, long ); 117 | extern void LocationTrunc( location_list *, unsigned ); 118 | extern dip_status LocationOneReg( imp_image_handle *, unsigned, location_context *, location_list * ); 119 | extern dip_status LocationManyReg( imp_image_handle *, unsigned, const unsigned_8 *, location_context *, location_list * ); 120 | 121 | extern unsigned NameCopy( char *, const char *, unsigned, unsigned ); 122 | extern void MapLogical( imp_image_handle *, address * ); 123 | extern void * GetNumLeaf( void *, numeric_leaf * ); 124 | extern dip_status SegIsExecutable( imp_image_handle *, unsigned ); 125 | 126 | extern search_result ImpAddrMod( imp_image_handle *, address, imp_mod_handle * ); 127 | 128 | extern dip_status TypeSymGetName( imp_image_handle *, imp_sym_handle *, char **, unsigned * ); 129 | extern dip_status TypeSymGetType( imp_image_handle *, imp_sym_handle *, imp_type_handle * ); 130 | extern dip_status TypeSymGetAddr( imp_image_handle *, imp_sym_handle *, location_context *, location_list * ); 131 | extern dip_status TypeSymGetValue( imp_image_handle *, imp_sym_handle *, location_context *, void * ); 132 | extern dip_status TypeSymGetInfo( imp_image_handle *, imp_sym_handle *, location_context *, sym_info * ); 133 | extern dip_status TypeCallInfo( imp_image_handle *, unsigned, cv_calls *, unsigned * ); 134 | extern walk_result TypeSymWalkList( imp_image_handle *ii, imp_type_handle *it, IMP_SYM_WKR* wk, imp_sym_handle *is, void *d ); 135 | extern dip_status TypeIndexFillIn( imp_image_handle *, unsigned, imp_type_handle * ); 136 | extern search_result TypeSearchTagName( imp_image_handle *, lookup_item *, void * ); 137 | extern search_result TypeSearchNestedSym( imp_image_handle *, imp_type_handle *, lookup_item *, void * ); 138 | extern dip_status ImpTypeInfo( imp_image_handle *, imp_type_handle *, location_context *, type_info * ); 139 | extern dip_status ImpTypeBase( imp_image_handle *, imp_type_handle *, imp_type_handle * ); 140 | extern dip_status TypeMemberFuncInfo( imp_image_handle *, imp_type_handle *, imp_type_handle *, imp_type_handle *, unsigned long * ); 141 | 142 | extern dip_status SymFillIn( imp_image_handle *, imp_sym_handle *, virt_mem ); 143 | extern dip_status SymFindMatchingSym( imp_image_handle *, char *, unsigned, unsigned, imp_sym_handle * ); 144 | extern dip_status ImpSymLocation( imp_image_handle *, imp_sym_handle *, location_context *, location_list * ); 145 | extern dip_status ImpSymValue( imp_image_handle *, imp_sym_handle *, location_context *, void * ); 146 | extern dip_status ImpSymType( imp_image_handle *, imp_sym_handle *, imp_type_handle * ); 147 | 148 | extern void Confused( int, char *, uint ); 149 | extern dip_status DoIndirection( imp_image_handle *, type_info *, location_context *, location_list * ); 150 | extern cs_compile *GetCompInfo( imp_image_handle *, imp_mod_handle ); 151 | 152 | #define T_CODE_LBL16 0x00f01 153 | #define T_CODE_LBL32 0x00f02 154 | #define T_DATA_LBL16 0x00f09 155 | #define T_DATA_LBL32 0x00f0a 156 | 157 | #define SCOPE_TOKEN "::" 158 | #define SCOPE_TOKEN_LEN (sizeof(SCOPE_TOKEN)-1) 159 | 160 | #define DIP_CV 161 | #endif 162 | 163 | //temp 164 | extern void NYI(void); 165 | -------------------------------------------------------------------------------- /dip_src/cvld.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Open Watcom Project 4 | * 5 | * Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved. 6 | * 7 | * ======================================================================== 8 | * 9 | * This file contains Original Code and/or Modifications of Original 10 | * Code as defined in and that are subject to the Sybase Open Watcom 11 | * Public License version 1.0 (the 'License'). You may not use this file 12 | * except in compliance with the License. BY USING THIS FILE YOU AGREE TO 13 | * ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is 14 | * provided with the Original Code and Modifications, and is also 15 | * available at www.sybase.com/developer/opensource. 16 | * 17 | * The Original Code and all software distributed under the License are 18 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 19 | * EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM 20 | * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR 22 | * NON-INFRINGEMENT. Please see the License for the specific language 23 | * governing rights and limitations under the License. 24 | * 25 | * ======================================================================== 26 | * 27 | * Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE 28 | * DESCRIBE IT HERE! 29 | * 30 | ****************************************************************************/ 31 | 32 | 33 | #include 34 | #include 35 | #include "cvinfo.h" // 36 | #include "exepe.h" 37 | #include "exedos.h" 38 | 39 | /* 40 | Loading/unloading symbolic information. 41 | */ 42 | 43 | imp_image_handle *ImageList; 44 | 45 | static void Cleanup( imp_image_handle *ii ) 46 | { 47 | imp_image_handle **owner; 48 | imp_image_handle *curr; 49 | unsigned blocks; 50 | unsigned i; 51 | 52 | owner = &ImageList; 53 | for( ;; ) { 54 | curr = *owner; 55 | if( curr == ii ) break; 56 | owner = &curr->next_image; 57 | } 58 | *owner = ii->next_image; 59 | if( ii->directory != NULL ) { 60 | blocks = BLOCK_FACTOR( ii->dir_count, DIRECTORY_BLOCK_ENTRIES ); 61 | for( i = 0; i < blocks; ++i ) { 62 | if( ii->directory[i] != NULL ) { 63 | DCFree( ii->directory[i] ); 64 | } 65 | } 66 | DCFree( ii->directory ); 67 | } 68 | DCFree( ii->mapping ); 69 | VMFini( ii ); 70 | } 71 | 72 | static dip_status TryFindPE( dig_fhandle h, unsigned long *offp, 73 | unsigned long *sizep ) 74 | { 75 | union { 76 | dos_exe_header dos; 77 | pe_header pe; 78 | } hdr; 79 | pe_object obj; 80 | unsigned_32 nh_off; 81 | unsigned_32 section_off; 82 | unsigned i; 83 | unsigned_32 debug_rva; 84 | debug_directory dir; 85 | 86 | if( DCSeek( h, 0, DIG_ORG ) != 0 ) { 87 | return( DS_ERR|DS_FSEEK_FAILED ); 88 | } 89 | if( DCRead( h, &hdr.dos, sizeof( hdr.dos ) ) != sizeof( hdr.dos ) ) { 90 | return( DS_ERR|DS_FREAD_FAILED ); 91 | } 92 | if( hdr.dos.signature != DOS_SIGNATURE ) { 93 | return( DS_FAIL ); 94 | } 95 | if( DCSeek( h, NH_OFFSET, DIG_ORG ) != NH_OFFSET ) { 96 | return( DS_ERR|DS_FSEEK_FAILED ); 97 | } 98 | if( DCRead( h, &nh_off, sizeof( nh_off ) ) != sizeof( nh_off ) ) { 99 | return( DS_ERR|DS_FREAD_FAILED ); 100 | } 101 | if( DCSeek( h, nh_off, DIG_ORG ) != nh_off ) { 102 | return( DS_ERR|DS_FSEEK_FAILED ); 103 | } 104 | if( DCRead( h, &hdr.pe, sizeof( hdr.pe ) ) != sizeof( hdr.pe ) ) { 105 | return( DS_FAIL ); 106 | } 107 | //if( hdr.pe.signature != PE_SIGNATURE ) { 108 | if( hdr.pe.signature != PE_SIGNATURE && hdr.pe.signature != 0x5850 ) { /* japheth */ 109 | return( DS_FAIL ); 110 | } 111 | if( hdr.pe.table[ PE_TBL_DEBUG ].rva == 0 ) { 112 | return( DS_FAIL ); 113 | } 114 | debug_rva = (hdr.pe.table[ PE_TBL_DEBUG ].rva / hdr.pe.object_align)* 115 | hdr.pe.object_align; 116 | 117 | section_off = nh_off + offsetof( pe_header, flags ) + 118 | sizeof( hdr.pe.flags ) + hdr.pe.nt_hdr_size; 119 | 120 | if( DCSeek( h, section_off, DIG_ORG ) != section_off ) { 121 | return( DS_ERR|DS_FSEEK_FAILED ); 122 | } 123 | for( i=0; i < hdr.pe.num_objects; i++ ) { 124 | if( DCRead( h, &obj, sizeof( obj ) ) != sizeof( obj ) ) { 125 | return( DS_ERR|DS_FREAD_FAILED ); 126 | } 127 | if( obj.rva == debug_rva ) { 128 | debug_rva = obj.physical_offset + 129 | hdr.pe.table[ PE_TBL_DEBUG ].rva - debug_rva; 130 | if( DCSeek( h, debug_rva, DIG_ORG ) != debug_rva ) { 131 | return( DS_ERR|DS_FSEEK_FAILED ); 132 | } 133 | if( DCRead( h, &dir, sizeof( dir ) ) != sizeof( dir ) ) { 134 | return( DS_ERR|DS_FREAD_FAILED ); 135 | } 136 | if( dir.debug_type != DEBUG_TYPE_CODEVIEW ) { 137 | return( DS_FAIL ); 138 | } 139 | *offp = dir.data_seek; 140 | *sizep = dir.debug_size; 141 | } 142 | } 143 | return( DS_FAIL ); 144 | } 145 | 146 | static dip_status TryFindTrailer( dig_fhandle h, unsigned long *offp, 147 | unsigned long *sizep ) 148 | { 149 | cv_trailer sig; 150 | unsigned long pos; 151 | 152 | pos = DCSeek( h, -(long)sizeof( sig ), DIG_END ); 153 | if( pos == -1UL ) { 154 | return( DS_ERR|DS_FSEEK_FAILED ); 155 | } 156 | if( DCRead( h, &sig, sizeof( sig ) ) != sizeof( sig ) ) { 157 | return( DS_ERR|DS_FREAD_FAILED ); 158 | } 159 | if( memcmp( sig.sig, CV4_NB09, sizeof( sig.sig ) ) != 0 ) { 160 | return( DS_FAIL ); 161 | } 162 | *sizep = sig.offset - sizeof( sig ); 163 | *offp = pos - *sizep; 164 | return( DS_OK ); 165 | } 166 | 167 | static dip_status FindCV( dig_fhandle h, unsigned long *offp, 168 | unsigned long *sizep ) 169 | { 170 | char sig[CV_SIG_SIZE]; 171 | dip_status ds; 172 | 173 | ds = TryFindPE( h, offp, sizep ); 174 | if( ds & DS_ERR ) return( ds ); 175 | if( ds != DS_OK ) { 176 | ds = TryFindTrailer( h, offp, sizep ); 177 | if( ds != DS_OK ) return( ds ); 178 | } 179 | if( DCSeek( h, *offp, DIG_ORG ) != *offp ) { 180 | return( DS_ERR|DS_FSEEK_FAILED ); 181 | } 182 | if( DCRead( h, sig, sizeof( sig ) ) != sizeof( sig ) ) { 183 | return( DS_ERR|DS_FREAD_FAILED ); 184 | } 185 | if( memcmp( sig, CV4_NB09, sizeof( sig ) ) != 0 ) { 186 | return( DS_FAIL ); 187 | } 188 | return( DS_OK ); 189 | } 190 | 191 | static dip_status LoadDirectory( imp_image_handle *ii, unsigned long off ) 192 | { 193 | unsigned_32 directory; 194 | cv_subsection_directory dir_header; 195 | unsigned block_count; 196 | unsigned i; 197 | unsigned left; 198 | unsigned block_size; 199 | unsigned num; 200 | 201 | if( DCSeek( ii->sym_file, off, DIG_ORG ) != off ) { 202 | return( DS_ERR|DS_FSEEK_FAILED ); 203 | } 204 | if( DCRead( ii->sym_file, &directory, sizeof( directory ) ) != sizeof( directory ) ) { 205 | return( DS_ERR|DS_FREAD_FAILED ); 206 | } 207 | if( DCSeek( ii->sym_file, ii->bias + directory, DIG_ORG ) != (ii->bias + directory) ) { 208 | return( DS_ERR|DS_FSEEK_FAILED ); 209 | } 210 | if( DCRead( ii->sym_file, &dir_header, sizeof( dir_header ) ) != sizeof( dir_header ) ) { 211 | return( DS_ERR|DS_FREAD_FAILED ); 212 | } 213 | if( dir_header.cbDirHeader != sizeof( dir_header ) 214 | || dir_header.cbDirEntry != sizeof( cv_directory_entry ) ) { 215 | return( DS_ERR|DS_INFO_INVALID ); 216 | } 217 | ii->dir_count = dir_header.cDir; 218 | block_count = BLOCK_FACTOR( ii->dir_count, DIRECTORY_BLOCK_ENTRIES ); 219 | ii->directory = DCAlloc( block_count * sizeof( cv_directory_entry * ) ); 220 | if( ii->directory == NULL ) { 221 | return( DS_ERR|DS_NO_MEM ); 222 | } 223 | memset( ii->directory, 0, block_count * sizeof( cv_directory_entry * ) ); 224 | i = 0; 225 | left = ii->dir_count; 226 | for( ;; ) { 227 | num = left; 228 | if( num > DIRECTORY_BLOCK_ENTRIES ) num = DIRECTORY_BLOCK_ENTRIES; 229 | block_size = num * sizeof( cv_directory_entry ); 230 | ii->directory[i] = DCAlloc( block_size ); 231 | if( ii->directory[i] == NULL ) { 232 | return( DS_ERR|DS_NO_MEM ); 233 | } 234 | if( DCRead( ii->sym_file, ii->directory[i], block_size ) != block_size ) { 235 | return( DS_ERR|DS_FREAD_FAILED ); 236 | } 237 | ++i; 238 | left -= num; 239 | if( left == 0 ) break; 240 | } 241 | return( DS_OK ); 242 | } 243 | 244 | static dip_status LoadMapping( imp_image_handle *ii ) 245 | { 246 | cv_directory_entry *cde; 247 | cv_sst_seg_map *map; 248 | unsigned size; 249 | 250 | cde = FindDirEntry( ii, MH_GBL, sstSegMap ); 251 | if( cde == NULL ) return( DS_ERR|DS_INFO_INVALID ); 252 | map = VMBlock( ii, cde->lfo, cde->cb ); 253 | if( map == NULL ) return( DS_ERR|DS_FAIL ); 254 | size = map->cSegLog * sizeof( map->segdesc[0] ); 255 | ii->mapping = DCAlloc( size ); 256 | if( ii->mapping == NULL ) return( DS_ERR|DS_NO_MEM ); 257 | map = VMBlock( ii, cde->lfo, cde->cb ); /* malloc might have unloaded */ 258 | memcpy( ii->mapping, &map->segdesc[0], size ); 259 | ii->map_count = map->cSegLog; 260 | return( DS_OK ); 261 | } 262 | 263 | static walk_result FindCompUnit( imp_image_handle *ii, 264 | cv_directory_entry *cde, void *d ) 265 | { 266 | cs_compile **rec = d; 267 | 268 | if( cde->subsection != sstModule ) return( WR_CONTINUE ); 269 | *rec = GetCompInfo( ii, cde->iMod ); 270 | if( *rec == NULL ) return( WR_CONTINUE ); 271 | return( WR_STOP ); 272 | } 273 | 274 | static dip_status SetMADType( imp_image_handle *ii ) 275 | { 276 | cs_compile *rec; 277 | walk_result wr; 278 | 279 | wr = WalkDirList( ii, &FindCompUnit, &rec ); 280 | if( wr != WR_STOP ) return( DS_OK ); 281 | switch( rec->machine & 0xf0 ) { 282 | case MACH_INTEL_8080: 283 | ii->mad = MAD_X86; 284 | break; 285 | case MACH_DECALPHA: 286 | ii->mad = MAD_AXP; 287 | break; 288 | default: 289 | return( DS_ERR|DS_INFO_INVALID ); 290 | } 291 | return( DS_OK ); 292 | } 293 | 294 | dip_status DIPENTRY DIPImpLoadInfo( dig_fhandle h, imp_image_handle *ii ) 295 | { 296 | dip_status ds; 297 | unsigned long off; 298 | unsigned long size; 299 | cv_directory_entry *cde; 300 | cv_sst_global_types_header *hdr; 301 | 302 | memset( ii, 0, sizeof( *ii ) ); 303 | ds = FindCV( h, &off, &size ); 304 | if( ds != DS_OK ) return( ds ); 305 | ii->sym_file = h; 306 | ii->bias = off; 307 | ds = VMInit( ii, size ); 308 | if( ds != DS_OK ) return( ds ); 309 | ii->next_image = ImageList; 310 | ImageList = ii; 311 | ds = LoadDirectory( ii, off + CV_SIG_SIZE ); 312 | if( ds != DS_OK ) { 313 | DCStatus( ds ); 314 | Cleanup( ii ); 315 | return( ds ); 316 | } 317 | ds = LoadMapping( ii ); 318 | if( ds != DS_OK ) { 319 | DCStatus( ds ); 320 | Cleanup( ii ); 321 | return( ds ); 322 | } 323 | cde = FindDirEntry( ii, MH_GBL, sstGlobalTypes ); 324 | if( cde != NULL ) { 325 | hdr = VMBlock( ii, cde->lfo, sizeof( *hdr ) ); 326 | if( hdr == NULL ) { 327 | Cleanup( ii ); 328 | return( DS_ERR|DS_FAIL ); 329 | } 330 | ii->types_base = cde->lfo 331 | + offsetof(cv_sst_global_types_header, offType ) 332 | + hdr->cType * sizeof( hdr->offType[0] ); 333 | } 334 | ds = SetMADType( ii ); 335 | if( ds != DS_OK ) { 336 | DCStatus( ds ); 337 | Cleanup( ii ); 338 | return( ds ); 339 | } 340 | return( DS_OK ); 341 | } 342 | 343 | void DIPENTRY DIPImpMapInfo( imp_image_handle *ii, void *d ) 344 | { 345 | unsigned i; 346 | addr_ptr addr; 347 | 348 | for( i = 0; i < ii->map_count; ++i ) { 349 | addr.segment = ii->mapping[i].frame; 350 | addr.offset = ii->mapping[i].offset; 351 | DCMapAddr( &addr, d ); 352 | ii->mapping[i].frame = addr.segment; 353 | ii->mapping[i].offset = addr.offset; 354 | } 355 | } 356 | 357 | dip_status SegIsExecutable( imp_image_handle *ii, unsigned log ) 358 | { 359 | seg_desc *map; 360 | 361 | map = &ii->mapping[log-1]; 362 | return( map->u.b.fExecute ? DS_OK : DS_FAIL ); 363 | } 364 | 365 | void MapLogical( imp_image_handle *ii, address *a ) 366 | { 367 | seg_desc *map; 368 | 369 | map = &ii->mapping[a->mach.segment-1]; 370 | a->mach.segment = map->frame; 371 | a->mach.offset += map->offset; 372 | a->sect_id = map->ovl; 373 | a->indirect = 1; 374 | } 375 | 376 | void DIPENTRY DIPImpUnloadInfo( imp_image_handle *ii ) 377 | { 378 | Cleanup( ii ); 379 | DCClose( ii->sym_file ); 380 | } 381 | -------------------------------------------------------------------------------- /dip_src/cvmisc.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Open Watcom Project 4 | * 5 | * Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved. 6 | * 7 | * ======================================================================== 8 | * 9 | * This file contains Original Code and/or Modifications of Original 10 | * Code as defined in and that are subject to the Sybase Open Watcom 11 | * Public License version 1.0 (the 'License'). You may not use this file 12 | * except in compliance with the License. BY USING THIS FILE YOU AGREE TO 13 | * ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is 14 | * provided with the Original Code and Modifications, and is also 15 | * available at www.sybase.com/developer/opensource. 16 | * 17 | * The Original Code and all software distributed under the License are 18 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 19 | * EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM 20 | * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR 22 | * NON-INFRINGEMENT. Please see the License for the specific language 23 | * governing rights and limitations under the License. 24 | * 25 | * ======================================================================== 26 | * 27 | * Description: Miscellaneous CodeView support routines. 28 | * 29 | ****************************************************************************/ 30 | 31 | 32 | #include 33 | #include 34 | #include "cvinfo.h" 35 | 36 | /* 37 | Misc. stuff. 38 | */ 39 | 40 | const char DIPImpName[] = "CodeView"; 41 | 42 | unsigned DIPENTRY DIPImpQueryHandleSize( handle_kind hk ) 43 | { 44 | static unsigned_8 Sizes[] = { 45 | sizeof( imp_image_handle ), 46 | sizeof( imp_type_handle ), 47 | sizeof( imp_cue_handle ), 48 | sizeof( imp_sym_handle ) 49 | }; 50 | 51 | return( Sizes[ hk ] ); 52 | } 53 | 54 | dip_status DIPENTRY DIPImpMoreMem( unsigned size ) 55 | { 56 | size = size; 57 | return( (VMShrink() != 0) ? DS_OK : DS_FAIL ); 58 | } 59 | 60 | dip_status DIPENTRY DIPImpStartup(void) 61 | { 62 | return( DS_OK ); 63 | } 64 | 65 | void DIPENTRY DIPImpShutdown( void ) 66 | { 67 | } 68 | 69 | void DIPENTRY DIPImpCancel( void ) 70 | { 71 | } 72 | 73 | unsigned NameCopy( char *dst, const char *src, unsigned max, unsigned len ) 74 | { 75 | if( max > 0 ) { 76 | --max; 77 | if( max > len ) max = len; 78 | memcpy( dst, src, max ); 79 | dst[ max ] = '\0'; 80 | } 81 | return( len ); 82 | } 83 | 84 | cv_directory_entry *FindDirEntry( imp_image_handle *ii, imp_mod_handle im, 85 | unsigned subsection_type ) 86 | { 87 | unsigned i; 88 | unsigned block; 89 | unsigned full_blocks; 90 | unsigned remainder; 91 | cv_directory_entry *p; 92 | 93 | full_blocks = BLOCK_FACTOR( ii->dir_count, DIRECTORY_BLOCK_ENTRIES ) - 1; 94 | for( block = 0; block < full_blocks; ++block ) { 95 | for( i = 0; i < DIRECTORY_BLOCK_ENTRIES; ++i ) { 96 | p = &ii->directory[block][i]; 97 | if( p->subsection == subsection_type && p->iMod == im ) { 98 | return( p ); 99 | } 100 | } 101 | } 102 | remainder = ii->dir_count - (full_blocks * DIRECTORY_BLOCK_ENTRIES); 103 | for( i = 0; i < remainder; ++i ) { 104 | p = &ii->directory[block][i]; 105 | if( p->subsection == subsection_type && p->iMod == im ) { 106 | return( p ); 107 | } 108 | } 109 | return( NULL ); 110 | } 111 | 112 | walk_result WalkDirList( imp_image_handle *ii, DIR_WALKER *wk, void *d ) 113 | { 114 | unsigned i; 115 | unsigned block; 116 | unsigned full_blocks; 117 | unsigned remainder; 118 | walk_result wr; 119 | cv_directory_entry *p; 120 | 121 | full_blocks = BLOCK_FACTOR( ii->dir_count, DIRECTORY_BLOCK_ENTRIES ) - 1; 122 | for( block = 0; block < full_blocks; ++block ) { 123 | for( i = 0; i < DIRECTORY_BLOCK_ENTRIES; ++i ) { 124 | p = &ii->directory[block][i]; 125 | wr = wk( ii, p, d ); 126 | if( wr != WR_CONTINUE ) return( wr ); 127 | } 128 | } 129 | remainder = ii->dir_count - (full_blocks * DIRECTORY_BLOCK_ENTRIES); 130 | for( i = 0; i < remainder; ++i ) { 131 | p = &ii->directory[block][i]; 132 | wr = wk( ii, p, d ); 133 | if( wr != WR_CONTINUE ) return( wr ); 134 | } 135 | return( WR_CONTINUE ); 136 | } 137 | 138 | static const struct { 139 | unsigned_8 k; 140 | unsigned_8 size; 141 | } LeafInfo[] = { 142 | { TK_INTEGER, 1 }, 143 | { TK_INTEGER, 2 }, 144 | { TK_INTEGER, 2 }, 145 | { TK_INTEGER, 4 }, 146 | { TK_INTEGER, 4 }, 147 | { TK_REAL, 4 }, 148 | { TK_REAL, 8 }, 149 | { TK_REAL, 10 }, 150 | { TK_REAL, 16 }, 151 | { TK_INTEGER, 8 }, 152 | { TK_INTEGER, 8 }, 153 | { TK_REAL, 6 }, 154 | { TK_COMPLEX, 8 }, 155 | { TK_COMPLEX, 16 }, 156 | { TK_COMPLEX, 20 }, 157 | { TK_COMPLEX, 32 }, 158 | { TK_STRING, 0 }, 159 | }; 160 | 161 | void *GetNumLeaf( void *p, numeric_leaf *v ) 162 | { 163 | unsigned key; 164 | 165 | key = *(unsigned_16 *)p; 166 | if( key < LF_NUMERIC ) { 167 | v->k = TK_INTEGER; 168 | v->size = sizeof( unsigned_16 ); 169 | v->valp = p; 170 | v->int_val = key; 171 | } else { 172 | v->valp = (unsigned_8 *)p + sizeof( unsigned_16 ); 173 | v->size = LeafInfo[ key - LF_NUMERIC ].size; 174 | v->k = LeafInfo[ key - LF_NUMERIC ].k; 175 | switch( key ) { 176 | case LF_CHAR: 177 | v->int_val = *(signed_8 *)v->valp; 178 | break; 179 | case LF_SHORT: 180 | v->int_val = *(signed_16 *)v->valp; 181 | break; 182 | case LF_USHORT: 183 | v->int_val = *(unsigned_16 *)v->valp; 184 | break; 185 | case LF_LONG: 186 | case LF_ULONG: 187 | v->int_val = *(unsigned_32 *)v->valp; 188 | break; 189 | case LF_VARSTRING: 190 | v->size = *(unsigned_16 *)v->valp; 191 | v->valp = (unsigned_8 *)v->valp + sizeof( unsigned_16 ); 192 | break; 193 | } 194 | } 195 | return( (unsigned_8 *)v->valp + v->size ); 196 | } 197 | 198 | 199 | dip_status DoIndirection( imp_image_handle *ii, type_info *ti, 200 | location_context *lc, location_list *ll ) 201 | { 202 | union { 203 | unsigned_8 u8; 204 | unsigned_16 u16; 205 | unsigned_32 u32; 206 | addr32_off ao32; 207 | addr48_off ao48; 208 | addr32_ptr ap32; 209 | addr48_ptr ap48; 210 | } tmp; 211 | location_list dst; 212 | dip_status ds; 213 | 214 | ii = ii; 215 | LocationCreate( &dst, LT_INTERNAL, &tmp ); 216 | ds = DCAssignLocation( &dst, ll, ti->size ); 217 | if( ds != DS_OK ) return( ds ); 218 | ds = DCItemLocation( lc, CI_DEF_ADDR_SPACE, ll ); 219 | if( ds != DS_OK ) return( ds ); 220 | if( ti->modifier == TM_NEAR ) { 221 | if( ti->size == sizeof( addr32_off ) ) { 222 | ll->e[0].u.addr.mach.offset = tmp.ao32; 223 | } else { 224 | ll->e[0].u.addr.mach.offset = tmp.ao48; 225 | } 226 | } else { 227 | if( ti->size == sizeof( addr32_ptr ) ) { 228 | ll->e[0].u.addr.mach.offset = tmp.ap32.offset; 229 | ll->e[0].u.addr.mach.segment = tmp.ap32.segment; 230 | } else { 231 | ll->e[0].u.addr.mach.offset = tmp.ap48.offset; 232 | ll->e[0].u.addr.mach.segment = tmp.ap48.segment; 233 | } 234 | } 235 | return( DS_OK ); 236 | } 237 | 238 | void NYI( void ) 239 | { 240 | volatile int a = 0; 241 | volatile int b = 0; 242 | DCWrite( 2, "\a\a\a\a\a\a\a", 8 ); 243 | a /= b; /* cause a fault */ 244 | } 245 | 246 | void OutputDebugStringA( char * ); 247 | #pragma aux OutputDebugStringA = \ 248 | "cld" \ 249 | "lbl1:" \ 250 | "lodsb" \ 251 | "cmp al,0" \ 252 | "jz lbl2" \ 253 | "mov dl,al" \ 254 | "mov ax,0" \ 255 | "int 41h" \ 256 | "jmp lbl1" \ 257 | "lbl2:" \ 258 | parm [esi] \ 259 | modify exact [esi ax dx] 260 | 261 | extern char *itoa( int, char *, int ); 262 | 263 | void Confused( int type, char *function, uint code ) 264 | { 265 | char tmp[16]; 266 | OutputDebugStringA( "codeview.dip - " ); 267 | OutputDebugStringA( function ); 268 | OutputDebugStringA( " type=" ); 269 | OutputDebugStringA( itoa(type, tmp, 10 ) ); 270 | OutputDebugStringA( " code=" ); 271 | OutputDebugStringA( itoa(code, tmp, 10 ) ); 272 | OutputDebugStringA( "\r\n" ); 273 | _asm int 3; 274 | /* don't know what's happening */ 275 | NYI(); 276 | } 277 | -------------------------------------------------------------------------------- /dip_src/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | Files modified for binary codeview.dll/codeview.dip, branch \watcom\bld\dip: 3 | 4 | - crash in wd/wdw if C module compiled with -hc is included and debug format is codeview 5 | dip\codeview\c\cvmisc.c (just the "Confused()" proc - additional params ) 6 | dip\codeview\c\cvsym.c ( added case for S_BLOCK32 ) 7 | dip\codeview\c\cvtype.c (just the "Confused()" calls ) 8 | dip\codeview\h\cvinfo.h (just prototype for "Confused()") 9 | 10 | 11 | -------------------------------------------------------------------------------- /mad_src/x86/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | Files modified for binary madx86.mad, branch \watcom\bld\mad 3 | 4 | - screen flip on INT instruction: 5 | mad\x86\c\x86trace.c 6 | 7 | -------------------------------------------------------------------------------- /mad_src/x86/x86trace.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Open Watcom Project 4 | * 5 | * Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved. 6 | * 7 | * ======================================================================== 8 | * 9 | * This file contains Original Code and/or Modifications of Original 10 | * Code as defined in and that are subject to the Sybase Open Watcom 11 | * Public License version 1.0 (the 'License'). You may not use this file 12 | * except in compliance with the License. BY USING THIS FILE YOU AGREE TO 13 | * ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is 14 | * provided with the Original Code and Modifications, and is also 15 | * available at www.sybase.com/developer/opensource. 16 | * 17 | * The Original Code and all software distributed under the License are 18 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 19 | * EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM 20 | * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR 22 | * NON-INFRINGEMENT. Please see the License for the specific language 23 | * governing rights and limitations under the License. 24 | * 25 | * ======================================================================== 26 | * 27 | * Description: Execution tracing support for x86. 28 | * 29 | ****************************************************************************/ 30 | 31 | 32 | #include 33 | #include 34 | #include "x86.h" 35 | #include "madregs.h" 36 | 37 | unsigned DIGENTRY MITraceSize( void ) 38 | { 39 | return( sizeof( mad_trace_data ) ); 40 | } 41 | 42 | void DIGENTRY MITraceInit( mad_trace_data *td, const mad_registers *mr ) 43 | { 44 | td->prev_ins_type = -1; 45 | td->prev_ins_flags = 0; 46 | } 47 | 48 | 49 | mad_status DIGENTRY MITraceHaveRecursed( address watch_stack, const mad_registers *mr ) 50 | { 51 | if( mr->x86.cpu.ss == watch_stack.mach.segment 52 | && mr->x86.cpu.esp < watch_stack.mach.offset ) { 53 | /* 54 | we're down some levels in a recursive call -- want to unwind. 55 | */ 56 | return( MS_OK ); 57 | } 58 | return( MS_FAIL ); 59 | } 60 | 61 | /* 62 | * BreakRet -- put a break point at the return address of a routine 63 | */ 64 | 65 | static void BreakRet( mad_trace_data *td, mad_disasm_data *dd, const mad_registers *mr ) 66 | { 67 | address sp; 68 | union { 69 | addr32_off off32; 70 | addr48_off off48; 71 | } off; 72 | 73 | sp = GetRegSP( mr ); 74 | if( dd->characteristics & X86AC_BIG ) { 75 | MCReadMem( sp, sizeof( off.off48 ), &off.off48 ); 76 | sp.mach.offset += sizeof( off.off48 ); 77 | td->brk.mach.offset = off.off48; 78 | } else { 79 | MCReadMem( sp, sizeof( off.off32 ), &off.off32 ); 80 | sp.mach.offset += sizeof( off.off32 ); 81 | td->brk.mach.offset = off.off32; 82 | } 83 | switch( td->prev_ins_type ) { 84 | case DI_X86_call: 85 | case DI_X86_call2: 86 | case DI_X86_ret: 87 | case DI_X86_ret2: 88 | td->brk.mach.segment = mr->x86.cpu.cs; 89 | break; 90 | case DI_X86_call3: 91 | case DI_X86_call4: 92 | case DI_X86_int: 93 | case DI_X86_into: 94 | case DI_X86_iret: 95 | case DI_X86_iretd: 96 | case DI_X86_retf: 97 | case DI_X86_retf2: 98 | MCReadMem( sp, sizeof( td->brk.mach.segment ), &td->brk.mach.segment ); 99 | sp.mach.offset += sizeof( td->brk.mach.segment ); 100 | break; 101 | default: 102 | break; 103 | } 104 | MCAddrSection( &td->brk ); 105 | } 106 | 107 | 108 | /* 109 | * BreakNext -- put a break point at the next instruction 110 | */ 111 | 112 | static void BreakNext( mad_trace_data *td, mad_disasm_data *dd ) 113 | { 114 | td->brk = dd->addr; 115 | td->brk.mach.offset += dd->ins.size; 116 | } 117 | 118 | static mad_trace_how DoTraceOne( mad_trace_data *td, mad_disasm_data *dd, mad_trace_kind tk, const mad_registers *mr ) 119 | { 120 | switch( tk ) { 121 | case MTRK_OUT: 122 | BreakRet( td, dd, mr ); 123 | return( MTRH_BREAK ); 124 | case MTRK_INTO: 125 | return( MTRH_STEP ); 126 | case MTRK_OVER: 127 | switch( dd->ins.type ) { 128 | case DI_X86_call: 129 | /* Handle special case of a call to the next instruction, which is 130 | * used under Linux to get the GOT pointer when compiled for 131 | * 386 processors. 132 | */ 133 | if( dd->ins.op[0].value == dd->ins.size ) 134 | return( MTRH_STEP ); 135 | /* Fall through for normal handling */ 136 | case DI_X86_call2: 137 | case DI_X86_call3: 138 | case DI_X86_call4: 139 | case DI_X86_int: 140 | case DI_X86_into: 141 | BreakNext( td, dd ); 142 | return( MTRH_BREAK ); 143 | case DI_X86_movs: 144 | case DI_X86_cmps: 145 | case DI_X86_scas: 146 | case DI_X86_lods: 147 | case DI_X86_stos: 148 | case DI_X86_outs: 149 | case DI_X86_ins: 150 | if( dd->ins.flags & (DIF_X86_REPE|DIF_X86_REPNE|DIF_X86_FWAIT) ) { 151 | BreakNext( td, dd ); 152 | return( MTRH_BREAK ); 153 | } 154 | return( MTRH_STEP ); 155 | default: 156 | break; 157 | } 158 | return( MTRH_STEP ); 159 | case MTRK_NEXT: 160 | BreakNext( td, dd ); 161 | return( MTRH_BREAK ); 162 | } 163 | return( MTRH_STOP ); 164 | } 165 | 166 | 167 | /* 168 | * CheckSpecial - check for instructions we have to handle specially or 169 | * we'll have problems 170 | */ 171 | 172 | static mad_trace_how CheckSpecial( mad_trace_data *td, mad_disasm_data *dd, const mad_registers *mr, mad_trace_how th ) 173 | { 174 | if( th != MTRH_STEP ) return( th ); 175 | switch( dd->ins.type ) { 176 | case DI_X86_int: 177 | MCNotify( MNT_EXECUTE_TOUCH_SCREEN_BUFF, NULL ); /* japheth, added to cause a screen flip when the INT runs */ 178 | if( dd->ins.flags & DIF_X86_EMU_INT ) 179 | break; 180 | /* fall through */ 181 | case DI_X86_into: 182 | if( !( dd->characteristics & X86AC_REAL ) ) 183 | break; 184 | return( MTRH_SIMULATE ); 185 | case DI_X86_iret: 186 | case DI_X86_iretd: 187 | BreakRet( td, dd, mr ); 188 | return( MTRH_STEPBREAK ); 189 | case DI_X86_pop: 190 | case DI_X86_pop2: 191 | case DI_X86_pop3d: 192 | case DI_X86_pop3e: 193 | case DI_X86_pop3s: 194 | case DI_X86_pop4f: 195 | case DI_X86_pop4g: 196 | case DI_X86_mov: 197 | case DI_X86_mov2: 198 | case DI_X86_mov3: 199 | case DI_X86_mov4: 200 | case DI_X86_mov5: 201 | case DI_X86_mov6: 202 | case DI_X86_mov7: 203 | if( dd->ins.op[0].type != DO_REG ) 204 | return( MTRH_STEP ); 205 | switch( dd->ins.op[0].base ) { 206 | case DR_X86_es: 207 | case DR_X86_ds: 208 | if( ( MCSystemConfig()->cpu & X86_CPU_MASK ) < X86_386 ) 209 | break; 210 | /* fall through */ 211 | default: 212 | return( MTRH_STEP ); 213 | } 214 | break; 215 | case DI_X86_pushf: 216 | case DI_X86_pushfd: 217 | case DI_X86_popf: 218 | case DI_X86_popfd: 219 | break; 220 | case DI_X86_fwait: 221 | if( MCSystemConfig()->fpu != X86_EMU ) 222 | return( MTRH_STEP ); 223 | break; 224 | default: 225 | if( dd->ins.flags & DIF_X86_EMU_INT ) break; 226 | if( ( dd->ins.flags & DIF_X86_FP_INS ) 227 | && ( ( dd->ins.flags & DIF_X86_FWAIT ) || ( MCSystemConfig()->fpu == X86_EMU ) ) ) 228 | break; 229 | return( MTRH_STEP ); 230 | } 231 | BreakNext( td, dd ); 232 | return( MTRH_STEPBREAK ); 233 | } 234 | 235 | static walk_result TouchesScreenBuff( address a, mad_type_handle th, mad_memref_kind mk, void *d ) 236 | { 237 | const mad_registers *mr = d; 238 | 239 | th = th; 240 | if( mk & MMK_IMPLICIT ) 241 | return( WR_CONTINUE ); 242 | switch( MCSystemConfig()->os ) { 243 | case OS_DOS: 244 | if( a.mach.segment < 0xa000 || a.mach.segment >= 0xc000 ) 245 | return( WR_CONTINUE ); 246 | break; 247 | case OS_RATIONAL: 248 | if( a.mach.segment != mr->x86.cpu.cs && a.mach.segment != mr->x86.cpu.ds ) 249 | return( WR_CONTINUE ); 250 | if( a.mach.offset < 0xa0000UL || a.mach.offset >= 0xc0000UL ) 251 | return( WR_CONTINUE ); 252 | break; 253 | case OS_AUTOCAD: 254 | case OS_PHARLAP: 255 | case OS_ECLIPSE: 256 | if( a.mach.segment == mr->x86.cpu.cs 257 | || a.mach.segment == mr->x86.cpu.ds ) 258 | return( WR_CONTINUE ); 259 | break; 260 | } 261 | MCNotify( MNT_EXECUTE_TOUCH_SCREEN_BUFF, NULL ); 262 | return( WR_STOP ); 263 | } 264 | 265 | mad_trace_how DIGENTRY MITraceOne( mad_trace_data *td, mad_disasm_data *dd, mad_trace_kind tk, const mad_registers *mr, address *brk ) 266 | { 267 | mad_trace_how th; 268 | 269 | th = DoTraceOne( td, dd, tk, mr ); 270 | th = CheckSpecial( td, dd, mr, th ); 271 | switch( MCSystemConfig()->os ) { 272 | case OS_OS2: 273 | case OS_NW386: 274 | case OS_QNX: 275 | case OS_WINDOWS: 276 | case OS_NT: 277 | break; 278 | default: 279 | DoDisasmMemRefWalk( dd, TouchesScreenBuff, mr, (void *)mr ); 280 | break; 281 | } 282 | td->prev_ins_type = dd->ins.type; 283 | td->prev_ins_flags = dd->ins.flags; 284 | switch( th ) { 285 | case MTRH_BREAK: 286 | switch( td->prev_ins_type ) { 287 | case DI_X86_call: 288 | case DI_X86_call2: 289 | case DI_X86_call3: 290 | case DI_X86_call4: 291 | case DI_X86_int: 292 | case DI_X86_into: 293 | MCNotify( MNT_EXECUTE_LONG, NULL ); 294 | break; 295 | default: 296 | break; 297 | } 298 | /* fall through */ 299 | case MTRH_STEPBREAK: 300 | *brk = td->brk; 301 | break; 302 | } 303 | return( th ); 304 | } 305 | 306 | mad_status DIGENTRY MITraceSimulate( mad_trace_data *td, mad_disasm_data *dd, const mad_registers *in, mad_registers *out ) 307 | { 308 | address sp; 309 | word value; 310 | 311 | td = td; 312 | switch( dd->ins.type ) { 313 | case DI_X86_into: 314 | if( !( in->x86.cpu.efl & FLG_O ) ) { 315 | out->x86 = in->x86; 316 | out->x86.cpu.eip += dd->ins.size; 317 | return( MS_OK ); 318 | } 319 | /* fall through */ 320 | case DI_X86_int: 321 | /* only in real mode */ 322 | if( !( dd->characteristics & X86AC_REAL ) ) 323 | break; 324 | out->x86 = in->x86; 325 | sp = GetRegSP( out ); 326 | sp.mach.offset -= sizeof( word ); 327 | value = out->x86.cpu.efl; 328 | MCWriteMem( sp, sizeof( value ), &value ); 329 | out->x86.cpu.efl &= ~FLG_I; 330 | value = out->x86.cpu.cs; 331 | MCWriteMem( sp, sizeof( value ), &value ); 332 | value = out->x86.cpu.eip; 333 | MCWriteMem( sp, sizeof( value ), &value ); 334 | out->x86.cpu.esp = sp.mach.offset; 335 | return( MS_OK ); 336 | default: 337 | break; 338 | } 339 | return( MS_UNSUPPORTED ); 340 | } 341 | 342 | void DIGENTRY MITraceFini( mad_trace_data *td ) 343 | { 344 | td = td; 345 | } 346 | 347 | #define JMP_SHORT ((unsigned char)0XEB) 348 | #define BRK_POINT ((unsigned char)0XCC) 349 | 350 | mad_status DIGENTRY MIUnexpectedBreak( mad_registers *mr, unsigned *maxp, char *buff ) 351 | { 352 | address a; 353 | union { 354 | byte b[9]; 355 | addr32_ptr a32; 356 | addr48_ptr a48; 357 | } data; 358 | unsigned max; 359 | unsigned len; 360 | 361 | max = *maxp; 362 | *maxp = 0; 363 | if( max > 0 ) 364 | buff[0] = '\0'; 365 | a = GetRegIP( mr ); 366 | memset( &data, 0, sizeof( data ) ); 367 | MCReadMem( a, sizeof( data.b ), &data ); 368 | if( data.b[0] != BRK_POINT ) 369 | return( MS_FAIL ); 370 | mr->x86.cpu.eip += 1; 371 | if( data.b[1] != JMP_SHORT ) 372 | return( MS_OK ); 373 | if( memcmp( &data.b[3], "WVIDEO", 6 ) != 0 ) 374 | return( MS_OK ); 375 | a = GetRegSP( mr ); 376 | MCReadMem( a, sizeof( addr_ptr ), &data ); 377 | if( BIG_SEG( a ) ) { 378 | a.mach = data.a48; 379 | } else { 380 | ConvAddr32ToAddr48( data.a32, a.mach ); 381 | } 382 | len = 0; 383 | for( ;; ) { 384 | if( MCReadMem( a, sizeof( data.b[0] ), &data.b[0] ) == 0 ) 385 | break; 386 | a.mach.offset++; 387 | if( len < max ) 388 | buff[len] = data.b[0]; 389 | if( data.b[0] == '\0' ) 390 | break; 391 | ++len; 392 | } 393 | if( max > 0 ) 394 | buff[max] = '\0'; 395 | *maxp = len; 396 | return( MS_OK ); 397 | } 398 | -------------------------------------------------------------------------------- /trap_src/dosr/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | Files modified for binary std.trp, located in \watcom\bld\trap\lcl\dos\dosr 3 | 4 | - display & edit XMM registers: 5 | dosr\asm\trap.asm 6 | dosr\c\dosacc.c 7 | 8 | - interrupt flag set on program entry: 9 | dosr\c\dosacc.c 10 | 11 | -------------------------------------------------------------------------------- /trap_src/dosr/trap.asm: -------------------------------------------------------------------------------- 1 | ;***************************************************************************** 2 | ;* 3 | ;* Open Watcom Project 4 | ;* 5 | ;* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved. 6 | ;* 7 | ;* ======================================================================== 8 | ;* 9 | ;* This file contains Original Code and/or Modifications of Original 10 | ;* Code as defined in and that are subject to the Sybase Open Watcom 11 | ;* Public License version 1.0 (the 'License'). You may not use this file 12 | ;* except in compliance with the License. BY USING THIS FILE YOU AGREE TO 13 | ;* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is 14 | ;* provided with the Original Code and Modifications, and is also 15 | ;* available at www.sybase.com/developer/opensource. 16 | ;* 17 | ;* The Original Code and all software distributed under the License are 18 | ;* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 19 | ;* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM 20 | ;* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF 21 | ;* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR 22 | ;* NON-INFRINGEMENT. Please see the License for the specific language 23 | ;* governing rights and limitations under the License. 24 | ;* 25 | ;* ======================================================================== 26 | ;* 27 | ;* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE 28 | ;* DESCRIBE IT HERE! 29 | ;* 30 | ;***************************************************************************** 31 | 32 | 33 | include struct.inc 34 | include traps.inc 35 | 36 | extrn _DOS_major:byte 37 | extrn _DOS_minor:byte 38 | extrn _BoundAppLoading:byte 39 | 40 | CONST segment byte public 'DATA' 41 | CONST ends 42 | 43 | DGROUP group CONST 44 | 45 | _TEXT segment byte public 'CODE' 46 | 47 | 48 | 49 | extrn DebugTask :near 50 | extrn BptTrap :near 51 | extrn ExitDebugger :near 52 | 53 | extrn TraceRtn :word 54 | extrn TrapType :byte 55 | 56 | extrn "C", FPUExpand :near 57 | extrn "C", FPUContract :near 58 | 59 | ; these macros assume ES is pointing at the interrupt vector 60 | ; segment and that AX and BX are available for use 61 | 62 | SaveIntr macro intr,loc 63 | ife dummy 64 | if intr+1 65 | mov BX,4*intr ; get vector offset 66 | else 67 | xor BH,BH 68 | add BX,BX 69 | add BX,BX 70 | endif 71 | mov AX,ES:0[BX] ; get interrupt offset 72 | mov loc+0,AX ; save it 73 | mov AX,ES:2[BX] ; get interrupt segment 74 | mov loc+2,AX ; save it 75 | endif 76 | endm 77 | 78 | SetIntr macro intr,loc 79 | ife dummy 80 | if intr+1 81 | mov BX,4*intr ; get vector offset 82 | else 83 | xor BH,BH 84 | add BX,BX 85 | add BX,BX 86 | endif 87 | mov word ptr ES:0[BX],offset loc; set interrupt offset 88 | mov ES:2[BX],CS ; set interrupt segment 89 | endif 90 | endm 91 | 92 | SwapIntr macro intr,loc 93 | ife dummy 94 | if intr+1 95 | mov BX,4*intr ; get vector offset 96 | else 97 | xor BH,BH 98 | add BX,BX 99 | add BX,BX 100 | endif 101 | mov AX,word ptr loc+0 ; get new interrupt offset 102 | xchg ES:0[BX],AX ; swap offsets 103 | mov word ptr loc+0, AX ; . . . 104 | mov AX,word ptr loc+2 ; get new interrupt segment 105 | xchg ES:2[BX],AX ; swap segments 106 | mov word ptr loc+2,AX ; . . . 107 | endif 108 | endm 109 | 110 | RestIntr macro intr,loc 111 | ife dummy 112 | if intr+1 113 | mov BX,4*intr ; get vector offset 114 | else 115 | xor BH,BH 116 | add BX,BX 117 | add BX,BX 118 | endif 119 | mov AX,loc+0 ; get old interrupt offset 120 | mov ES:0[BX],AX ; restore it 121 | mov AX,loc+2 ; get old interrupt segment 122 | mov ES:2[BX],AX ; restore it 123 | endif 124 | endm 125 | 126 | 127 | assume CS:_TEXT 128 | 129 | 130 | WATCH_DEPTH equ 6+2+2 ; additional stack in watch point rtn 131 | 132 | ; Code Segment variables 133 | 134 | public _SegmentChain 135 | _SegmentChain dw ? 136 | OurSP dw ? 137 | OurSS dw ? 138 | DbgPSP dw ? 139 | CurrPSP dw ? 140 | TaskPSP dw 0 141 | 142 | 143 | SaveIntSP dw ? 144 | SaveIntSS dw ? 145 | InDos dd ? 146 | 147 | 148 | SaveBrkHndlr dw ?,? 149 | SaveCrtErrHndlr dw ?,? 150 | SaveBusyWait dw ?,? 151 | 152 | 153 | SaveVects db 1024 dup(?) 154 | 155 | TraceVec equ word ptr cs:(SaveVects+01H*4) 156 | BptVec equ word ptr cs:(SaveVects+03H*4) 157 | PrgIntVec equ word ptr cs:(SaveVects+05H*4) 158 | TimerIntVec equ word ptr cs:(SaveVects+08H*4) 159 | KbdIntVec equ word ptr cs:(SaveVects+09H*4) 160 | SysServVec equ word ptr cs:(SaveVects+15H*4) 161 | BrkVec equ word ptr cs:(SaveVects+1bH*4) 162 | PrgTermVec equ word ptr cs:(SaveVects+20H*4) 163 | OSIntVec equ word ptr cs:(SaveVects+21H*4) 164 | DOSBrkVec equ word ptr cs:(SaveVects+23H*4) 165 | CrtErrVec equ word ptr cs:(SaveVects+24H*4) 166 | ResTermVec equ word ptr cs:(SaveVects+27H*4) 167 | BusyWaitVec equ word ptr cs:(SaveVects+28H*4) 168 | 169 | UsrInt db 0 170 | DOSCount db 0 171 | BrkStatus db ? 172 | 173 | 174 | public InitVectors_ 175 | InitVectors_ proc near 176 | push es ; save registers 177 | push ds 178 | push si 179 | push di 180 | push dx 181 | push cx 182 | push bx 183 | mov ax,seg DGROUP 184 | mov ds,ax 185 | assume DS:DGROUP 186 | 187 | mov AH,30H ; get version number 188 | int 21H 189 | mov DS:_DOS_major,AL ; and save it away 190 | mov DS:_DOS_minor,AH 191 | ; save interrupt vectors 192 | mov si,cs 193 | mov es,si 194 | sub si,si 195 | mov ds,si 196 | mov di,offset SaveVects 197 | mov cx,1024/2 198 | cli 199 | rep movsw 200 | sti 201 | mov ax,BusyWaitVec ; set up busy wait 202 | mov CS:SaveBusyWait,ax ; swap location 203 | mov ax,BusyWaitVec+2 ; ... 204 | mov CS:SaveBusyWait+2,ax ; ... 205 | 206 | 207 | call GetPSP ; get debugger PSP 208 | mov CS:DbgPSP,AX ; and save it away 209 | 210 | call near ptr ClrIntVecs_ 211 | 212 | mov AH,34H ; get InDos flag 213 | int 21H ; ... 214 | mov word ptr CS:InDos+0,BX; save flag pointer away 215 | mov word ptr CS:InDos+2,ES; ... 216 | 217 | mov AX,3300H ; request Ctrl/Brk checking status 218 | int 21H 219 | mov CS:BrkStatus,DL 220 | mov AX,3301H ; set to check for all DOS calls 221 | mov DL,1 222 | int 21H 223 | 224 | pop bx ; restore registers 225 | pop cx 226 | pop dx 227 | pop di 228 | pop si 229 | pop ds 230 | pop es 231 | ret 232 | InitVectors_ endp 233 | 234 | 235 | ; DX:AX has load regs pointer & CX:BX has save regs pointer 236 | public RunProg_ ; run the program and return termination condition 237 | RunProg_ proc near 238 | push ES 239 | push DS 240 | push SI 241 | push DI 242 | push BP 243 | mov CS:UsrInt,0 ; no pending user interrupts 244 | mov CS:OurSS,SS ; save SS 245 | mov CS:OurSP,SP ; save SP 246 | jmp ExitDebugger ; run program 247 | public EnterDebugger 248 | EnterDebugger: cli ; interrupts off 249 | mov SS,OurSS ; restore stack segment 250 | mov SP,CS:OurSP ; restore stack pointer 251 | sti 252 | cld 253 | pop BP ; restore everything 254 | pop DI 255 | pop SI 256 | pop DS 257 | pop ES 258 | mov AL,TRAP_SKIP 259 | xchg AL,CS:TrapType ; get cause of termination 260 | cbw 261 | ret ; return to caller 262 | RunProg_ endp 263 | 264 | 265 | public FiniVectors_ 266 | FiniVectors_ proc near 267 | push es ; save registers 268 | push ds 269 | push si 270 | push di 271 | push dx 272 | push cx 273 | 274 | mov AX,3301H ; restore Ctrl/Brk checking state 275 | mov DL,CS:BrkStatus 276 | int 21H 277 | 278 | ; restore interrupt vectors 279 | mov di,cs 280 | mov ds,di 281 | sub di,di 282 | mov es,di 283 | mov si,offset SaveVects 284 | mov cx,1024/2 285 | cli 286 | rep movsw 287 | sti 288 | 289 | pop cx ; restore registers 290 | pop dx 291 | pop di 292 | pop si 293 | pop ds 294 | pop es 295 | ret 296 | FiniVectors_ endp 297 | 298 | 299 | 300 | public SetIntVecs_ 301 | SetIntVecs_ proc near 302 | 303 | push DS 304 | push ES 305 | push BX 306 | push AX 307 | 308 | sub AX,AX 309 | mov ES,AX 310 | 311 | cli 312 | 313 | ife dummy 314 | mov BX,0004H ; 1 * 4 = 4 315 | mov AX,CS:TraceRtn 316 | mov ES:[BX],AX 317 | mov AX,CS 318 | mov ES:2[BX],AX 319 | endif 320 | 321 | SetIntr 03H,BptTrap 322 | SetIntr 05H,UsrIntHandler 323 | SetIntr 15H,SysServHandler 324 | SetIntr 20H,ProgTerminate 325 | SwapIntr 28H,SaveBusyWait 326 | mov ax,seg DGROUP 327 | mov ds,ax 328 | cmp byte ptr ds:_BoundAppLoading,0 329 | _if ne 330 | SetIntr 21H,LoadOSHandler 331 | _else 332 | SetIntr 21H,OSHandler 333 | _endif 334 | SetIntr 27H,ProgTerminate 335 | 336 | sti 337 | 338 | pop AX 339 | pop BX 340 | pop ES 341 | pop DS 342 | 343 | jmp near ptr SetUsrTask_ 344 | 345 | SetIntVecs_ endp 346 | 347 | 348 | public ClrIntVecs_ 349 | ClrIntVecs_ proc near 350 | 351 | push ES 352 | push BX 353 | push AX 354 | 355 | sub AX,AX 356 | mov ES,AX 357 | 358 | cli 359 | SetIntr 01H,NullHandler 360 | SetIntr 03H,NullHandler 361 | RestIntr 05H,PrgIntVec 362 | RestIntr 15H,SysServVec 363 | RestIntr 20H,PrgTermVec 364 | RestIntr 21H,OSIntVec 365 | RestIntr 27H,ResTermVec 366 | SwapIntr 28H,SaveBusyWait 367 | sti 368 | 369 | call GetPSP 370 | mov CS:CurrPSP,AX 371 | 372 | pop AX 373 | pop BX 374 | pop ES 375 | 376 | jmp near ptr SetDbgTask_ 377 | 378 | ClrIntVecs_ endp 379 | 380 | assume ds:nothing 381 | 382 | 383 | SetBreak: mov byte ptr CS:UsrInt,-1 384 | NullHandler: iret 385 | 386 | 387 | TimerHandler: 388 | pushf ; call old handler 389 | call dword ptr TimerIntVec; ... 390 | cmp byte ptr CS:UsrInt,0; check for requested interrupt 391 | je NullHandler ; quit if no interrupt requested 392 | push ds ; save DS 393 | push bx ; save BX 394 | lds bx, CS:InDos ; get InDos pointer 395 | cmp byte ptr [bx],0 ; check if InDos is non-zero 396 | pop bx ; restore BX 397 | pop ds ; restore DS 398 | jne NullHandler ; quit if can't interrupt right now 399 | DoIntTask: mov byte ptr CS:TrapType,TRAP_USER ; user interrupt request 400 | mov byte ptr UsrInt,0 ; clear pending request 401 | jmp DebugTask 402 | 403 | 404 | SysServHandler: 405 | cmp AH,85H ; is it a SysReq key press? 406 | je UsrIntHandler ; if so then handle the interrupt 407 | jmp dword ptr SysServVec ; jump to old hander 408 | 409 | 410 | UsrIntHandler: mov CS:UsrInt, -1 ; request user interrupt 411 | iret 412 | 413 | ChkReturn: mov SS,CS:SaveIntSS 414 | mov SP,CS:SaveIntSP 415 | pop CS:SaveIntSP 416 | pop CS:SaveIntSS 417 | push BP ; save BP 418 | mov BP,SP ; get access to stack 419 | push AX ; save AX 420 | pushf ; save flags 421 | mov AX,6[BP] ; get old flags 422 | and AX,0100H ; isolate T-bit 423 | or AX,-4[BP] ; merge with new flags 424 | mov 6[BP],AX ; save new flags 425 | pop AX ; get rid of extra flags 426 | pop AX ; restore AX 427 | pop BP ; restore BP 428 | 429 | dec byte ptr CS:DOSCount 430 | jne rtrntouser 431 | cmp byte ptr CS:UsrInt,00H 432 | jne DoIntTask 433 | rtrntouser: iret 434 | 435 | 436 | public LoadOSHandler 437 | LoadOSHandler: 438 | cmp AH,48H ; if allocate memory request 439 | _if e ; - then 440 | pushf ; - do the request 441 | push cs 442 | call near ptr OSHandler 443 | push bp ; - save bp 444 | push ax ; - save ax 445 | pushf ; - get flags register into ax 446 | pop ax ; - ... 447 | mov bp,sp ; - get addressability to stack 448 | mov 8[bp],ax ; - zap the flags image 449 | pop ax ; - restore ax 450 | _if nc ; - if memory allocated 451 | push ds ; - - save ds 452 | dec ax ; - - point to DOS mem block 453 | mov ds,ax ; - - ... 454 | inc ax ; - - restore ax 455 | mov bp,cs:_SegmentChain ; - - link into our seg chain 456 | mov ds:[14],bp ; - - ... 457 | mov cs:_SegmentChain,ds ; - - ... 458 | pop ds ; - - restore ds 459 | _endif ; - endif 460 | pop bp ; - restore bp 461 | iret ; - return 462 | _else ; else 463 | cmp ah,49H ; - if free memory request 464 | _if e ; - - then 465 | push ax ; - - save ax 466 | push ds ; - - save ds 467 | mov ax,es ; - - get segment 468 | dec ax ; - - minus 1 469 | mov es,ax ; - - ... 470 | cmp ax,cs:_SegmentChain ; - - if it's our chain head 471 | _if e ; - - - then 472 | mov ax,es:[14] ; - - - bump head pointer up 473 | mov cs:_SegmentChain,ax ; - - - ... 474 | _else ; - - else 475 | mov ax,cs:_SegmentChain ; - - - h = SegmentChain 476 | _loop ; - - - loop 477 | mov ds,ax ; - - - - if h->next == chunk 478 | mov ax,es ; - - - - - then 479 | cmp ds:[14],ax ; - - - - - ... 480 | _if e ; - - - - - ... 481 | mov ax,es:[14] ; - - - - - h->nex=h->nex->nex 482 | mov ds:[14],ax ; - - - - - ... 483 | ; - - - - - Z flag set !!!!! 484 | _else ; - - - - else 485 | mov ax,ds:[14] ; - - - - - head = hext->next 486 | test ax,ax ; - - - - - test head,head 487 | _endif ; - - - - endif 488 | _until e ; - - - until end of list 489 | _endif ; - - endif 490 | mov ax,es ; - - restore es 491 | inc ax ; - - ... 492 | mov es,ax ; - - ... 493 | pop ds ; - - restore ds 494 | pop ax ; - - restore ax 495 | pushf ; - do the request 496 | push cs ; - ... 497 | call near ptr OSHandler ; ... 498 | push bp ; - save bp 499 | push ax ; - save ax 500 | pushf ; - get flags register into ax 501 | pop ax ; - ... 502 | mov bp,sp ; - get addressability to stack 503 | mov 8[bp],ax ; - zap the flags image 504 | pop ax ; - restore ax 505 | pop bp ; - restore bp 506 | iret ; - return 507 | _endif ; - endif 508 | _endif ; endif 509 | 510 | OSHandler: 511 | cmp AX,4B00H 512 | je OSJmp 513 | cmp AH,0 514 | je ProgTerminate 515 | cmp AH,31H 516 | je ProgTerminate 517 | cmp AH,4CH 518 | je ProgTerminate 519 | 520 | 521 | inc byte ptr CS:DOSCount 522 | push CS:SaveIntSS 523 | push CS:SaveIntSP 524 | mov CS:SaveIntSS,SS 525 | mov CS:SaveIntSP,SP 526 | pushf 527 | push CS 528 | push AX 529 | push BP 530 | mov BP,SP 531 | mov AX,16[BP] 532 | and AH,0FEH ; clear T-bit 533 | mov 6[BP],AX 534 | mov AX,offset ChkReturn 535 | xchg AX,2[BP] 536 | pop BP 537 | 538 | OSJmp: jmp dword ptr OSIntVec ; jump to old handler 539 | 540 | 541 | ProgTerminate: 542 | push AX ; save AX 543 | call GetPSP ; get the current PSP 544 | cmp AX,CS:TaskPSP ; is it the debugged task? 545 | pop AX ; restore AX 546 | jne OSJmp ; let DOS see it if another task 547 | terminate: push BP ; save BP 548 | mov BP,SP ; get access to stack 549 | push BX ; save BX 550 | push DS ; save DS 551 | lds BX,2[BP] ; get return offset/segment 552 | cmp byte ptr -2[BX],0CDH ; was it a software interrupt ? 553 | jne not_an_int ; if it was then 554 | sub word ptr 2[BP],2 ; - backup return addr 555 | not_an_int: pop DS ; restore DS 556 | pop BX ; restore BX 557 | pop BP ; restore BP 558 | mov byte ptr CS:TrapType,TRAP_TERMINATE ; indicate program termintation 559 | jmp DebugTask ; enter the debugger 560 | 561 | 562 | 563 | public EndUser_ 564 | EndUser_ proc near 565 | push DS ; save registers 566 | push ES 567 | push SI 568 | push DI 569 | push DX 570 | push CX 571 | push BX 572 | push AX 573 | push BP 574 | mov CS:OurSS,SS ; mark stack level 575 | mov CS:OurSP,SP ; ... 576 | 577 | ; restore interrupt vectors 578 | mov di,cs 579 | mov ds,di 580 | sub di,di 581 | mov es,di 582 | mov si,offset SaveVects 583 | mov cx,1024/2 584 | cli 585 | rep movsw 586 | sti 587 | 588 | ; DOS saves the the SS:SP value of a task in its PSP 589 | ; every time a task invokes int 21H. When a 4CH request 590 | ; is done DOS uses that stored value for a location to 591 | ; build the return interrupt frame to restart the parent 592 | ; task of the one that is being killed. since the 593 | ; last DOS call we've done might not be as deep in our 594 | ; stack as we currently are, we have to do a harmless, quick 595 | ; request so that DOS will set the proper values to restore 596 | ; SS:SP from (otherwise DOS will write over active stack 597 | ; locations). 598 | mov AH,2CH ; get time 599 | int 21H 600 | 601 | call near ptr SetUsrTask_ ; we're the user task 602 | 603 | clearatask: 604 | mov SS,CS:OurSS ; get our stack back 605 | mov SP,CS:OurSP ; . . . 606 | call GetPSP ; get current PSP 607 | cmp AX,CS:DbgPSP ; is it the debugger? 608 | je allcleared ; quit loop if so 609 | mov DS,AX ; get access to PSP 610 | mov DS:0AH,offset clearatask; set terminate offset 611 | mov DS:0CH,CS ; set terminate segment 612 | cli ; interrupts off 613 | mov SS,AX ; set up a safe stack 614 | mov SP,100H ; . . . 615 | sti ; interrupts on 616 | mov AX,4C00H ; terminate the task 617 | int 21H 618 | 619 | allcleared: 620 | pop BP ; restore registers 621 | pop AX 622 | pop BX 623 | pop CX 624 | pop DX 625 | pop DI 626 | pop SI 627 | pop ES 628 | pop DS 629 | cld 630 | ret 631 | EndUser_ endp 632 | 633 | 634 | ; DX:AX has program name, CX:BX has parm block 635 | public DOSLoadProg_ 636 | DOSLoadProg_ proc near 637 | push DS 638 | push ES 639 | 640 | mov CS:TaskPSP,0 ; assume we don't get a task 641 | mov ES,CX ; get parmblock in ES:BX 642 | mov DS,DX ; get file name in DS:DX 643 | mov DX,AX ; . . . 644 | mov AX,4B01H ; load program, maintain control 645 | int 21H ; (internal DOS call) 646 | 647 | sbb DX,DX ; set DX based on carry 648 | 649 | jne fini ; if not equal then we have no task 650 | call GetPSP ; get current PSP 651 | mov CS:TaskPSP,AX ; save task PSP address 652 | mov DS,AX ; get access to new task 653 | mov word ptr DS:0AH,offset debugprogend;set new terminate 654 | mov DS:0CH,CS ; address 655 | mov AH,25H ; set up vectors 656 | mov AL,23H ; set Ctrl/C vector 657 | mov DX,offset SetBreak 658 | push CS 659 | pop DS 660 | int 21H 661 | mov AL,24H ; set critical error vector 662 | mov DX,CrtErrVec+0 663 | mov DS,CrtErrVec+2 664 | int 21H 665 | 666 | call ClrIntVecs_ 667 | 668 | xor ax,ax ; get pointer to interrupt table 669 | mov es,ax 670 | SetIntr 08H,TimerHandler 671 | 672 | xor AX,AX ; return zero 673 | xor DX,DX ; . . . 674 | fini: 675 | pop ES 676 | pop DS 677 | ret 678 | DOSLoadProg_ endp 679 | 680 | debugprogend: 681 | mov CS:TaskPSP,0 ; don't have a task anymore 682 | mov byte ptr CS:TrapType,TRAP_TERMINATE ; program terminated 683 | jmp DebugTask 684 | 685 | 686 | public SetDbgTask_ 687 | SetDbgTask_ proc near 688 | push BX ; save BX 689 | mov BX,CS:DbgPSP ; tell DOS we're the debugger 690 | jmp short SetPSP 691 | SetDbgTask_ endp 692 | 693 | 694 | DbgDOSCall macro 695 | ; do a DOS request, but make sure to use the debugger's 696 | ; int 21 vector and NOT the program's 697 | pushf 698 | call dword ptr CS:SaveVects+21H*4 699 | endm 700 | 701 | public SetUsrTask_ 702 | SetUsrTask_ proc near 703 | push BX ; save BX 704 | mov BX,CS:CurrPSP ; tell DOS we're the current task 705 | SetPSP: 706 | pushf ; save flags 707 | push AX ; save AX 708 | mov AH,50H ; set PSP request (internal DOS call) 709 | DbgDOSCall ; do the call 710 | pop AX ; restore AX 711 | popf ; restore flags 712 | pop BX ; restore BX 713 | ret ; return 714 | SetUsrTask_ endp 715 | 716 | 717 | GetPSP proc near 718 | pushf ; save flags 719 | push BX ; save BX 720 | mov AH,51H ; get PSP request (internal DOS call) 721 | DbgDOSCall ; do the call 722 | mov AX,BX ; put PSP in proper return register 723 | pop BX ; restore BX 724 | popf ; restore flags 725 | ret ; return 726 | GetPSP endp 727 | 728 | 729 | public DOSTaskPSP_ 730 | DOSTaskPSP_ proc near 731 | mov AX,CS:TaskPSP 732 | ret 733 | DOSTaskPSP_ endp 734 | 735 | 736 | public DbgPSP_ 737 | DbgPSP_ proc near 738 | mov AX,CS:DbgPSP 739 | ret 740 | DbgPSP_ endp 741 | 742 | 743 | ; return with carry set if we don't want to watch this interrupt 744 | public ChkInt 745 | ChkInt proc near 746 | cmp BL,8FH 747 | jbe ms_overlay 748 | watch_it: clc 749 | ret 750 | ms_overlay: 751 | cmp BL,3FH 752 | je watch_it 753 | stc 754 | ret 755 | ChkInt endp 756 | 757 | EMU_OTHER equ 3cH 758 | EMU_INT equ 39H 759 | 760 | public Null87Emu_ 761 | Null87Emu_ proc near 762 | push es 763 | mov ax,0 764 | mov es,ax 765 | mov es:[EMU_INT*4+0],ax ; null out emulator interrupt 766 | mov es:[EMU_INT*4+2],ax ; ... 767 | pop es 768 | ret 769 | Null87Emu_ endp 770 | 771 | public Read87EmuState_ 772 | Read87EmuState_ proc near 773 | push ds 774 | push bx 775 | mov ds,dx 776 | mov bx,ax 777 | check_byte label byte 778 | db 0cdH, 039H, 037H ;fsave ds:[bx] 779 | pop bx 780 | pop ds 781 | call FPUExpand 782 | ret 783 | Read87EmuState_ endp 784 | 785 | public Write87EmuState_ 786 | Write87EmuState_ proc near 787 | call FPUContract 788 | push ds 789 | push bx 790 | mov ds,dx 791 | mov bx,ax 792 | db 0cdH, 039H, 027H ;frstor ds:[bx] 793 | pop bx 794 | pop ds 795 | ret 796 | Write87EmuState_ endp 797 | 798 | public Have87Emu_ 799 | Have87Emu_ proc near 800 | push es 801 | push bx 802 | xor ax,ax 803 | mov es,ax 804 | les bx,es:[EMU_INT*4] ; get emulator interrupt 805 | _guess 806 | mov ax,es 807 | or ax,bx ; is interrupt NULL? 808 | _quif e ; quit if it is 809 | cmp byte ptr es:[bx], 0cfH; is it pointing at an iret? 810 | _quif e ; quit if it is 811 | xor ax,ax 812 | push ax 813 | mov ax,es 814 | pop es 815 | cmp bx,es:[EMU_OTHER*4+0]; are both emu interrupts 816 | _if e ; pointing at the same thing? 817 | cmp ax,es:[EMU_OTHER*4+2] 818 | _endif 819 | _quif e ; quit if so 820 | cmp byte ptr cs:check_byte, 0cdH; has emu fsave been patched? 821 | _quif ne ; quit if so 822 | mov ax,1 ; have emulator 823 | _admit 824 | xor ax,ax ; no emulator 825 | _endguess 826 | pop bx 827 | pop es 828 | ret 829 | Have87Emu_ endp 830 | 831 | public ReadXMM_ 832 | ReadXMM_ proc near 833 | .286 834 | pusha 835 | mov bp,sp 836 | 837 | sub sp,512 ;size of FXSAVE buffer 838 | and sp,0FFF0h ;stack must be para-aligned 839 | mov bx, sp 840 | .686 841 | .xmm 842 | fxsave ss:[bx] 843 | lea si, [bx+32+8*16] ;locate start of XMM regs 844 | mov es, dx 845 | mov di, ax 846 | push ds 847 | push ss 848 | pop ds 849 | mov cx, 8*16 / 4 850 | rep movsd 851 | pop ds 852 | mov eax,ss:[bx+24] ;mxcsr 853 | stosd 854 | 855 | mov sp,bp 856 | popa 857 | ret 858 | .8086 859 | ReadXMM_ endp 860 | 861 | public WriteXMM_ 862 | WriteXMM_ proc near 863 | push bp 864 | mov bp,sp 865 | 866 | sub sp,512 867 | and sp,0FFF0h ;stack must be para-aligned 868 | mov bx, sp 869 | .686 870 | .xmm 871 | fxsave ss:[bx] ;init buffer with current values 872 | push ds 873 | mov ds, dx 874 | mov si, ax 875 | push ss 876 | pop es 877 | lea di,[bx+32+8*16] ;locate start of XMM regs 878 | mov cx, 8*16 / 4 879 | rep movsd 880 | lodsd 881 | mov ss:[bx+24], eax ;mxcsr 882 | pop ds 883 | fxrstor ss:[bx] ;and finally write new values 884 | 885 | mov sp,bp 886 | pop bp 887 | ret 888 | WriteXMM_ endp 889 | 890 | _TEXT ends 891 | -------------------------------------------------------------------------------- /trap_src/dosx/dosxlink.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Open Watcom Project 4 | * 5 | * Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved. 6 | * 7 | * ======================================================================== 8 | * 9 | * This file contains Original Code and/or Modifications of Original 10 | * Code as defined in and that are subject to the Sybase Open Watcom 11 | * Public License version 1.0 (the 'License'). You may not use this file 12 | * except in compliance with the License. BY USING THIS FILE YOU AGREE TO 13 | * ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is 14 | * provided with the Original Code and Modifications, and is also 15 | * available at www.sybase.com/developer/opensource. 16 | * 17 | * The Original Code and all software distributed under the License are 18 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 19 | * EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM 20 | * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR 22 | * NON-INFRINGEMENT. Please see the License for the specific language 23 | * governing rights and limitations under the License. 24 | * 25 | * ======================================================================== 26 | * 27 | * Description: DOS protected mode "remote link" to real mode. 28 | * 29 | ****************************************************************************/ 30 | 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include "packet.h" 38 | #include "trperr.h" 39 | #ifdef SERVER 40 | #ifdef PHARLAP 41 | #include "pharlap.h" 42 | #include "dxproto.h" 43 | #endif 44 | #else 45 | #include "tinyio.h" 46 | #include "trapdbg.h" 47 | #if defined(PHARLAP) 48 | #include "exedos.h" 49 | #include "exeos2.h" 50 | #include "exepe.h" 51 | #endif 52 | #endif 53 | 54 | #if defined(ACAD) 55 | #define EXTENDER_NAMES "ACAD.EXE\0" 56 | #define HELPNAME "" 57 | #elif defined(PHARLAP) 58 | #define EXTENDER_NAMES "TNT.EXE\0" "RUN386.EXE\0" 59 | #define HELPNAME "PLSHELP.EXP" 60 | #define HELPNAME_DS "PEDHELP.EXP" 61 | #define HELPNAME_NS "PENHELP.EXP" /* not supported yet */ 62 | #elif defined(DOS4G) 63 | #define EXTENDER_NAMES "DOS4GW.EXE\0" "4GWPRO.EXE\0" "DOS4G.EXE\0" "DOS4GX.EXE\0" 64 | #define HELPNAME "RSIHELP.EXP" 65 | #elif defined(CAUSEWAY) 66 | #define EXTENDER_NAMES "CWSTUB.EXE\0" 67 | #define HELPNAME "CWHELP.EXE" 68 | #elif defined(HX) 69 | #define EXTENDER_NAMES "HXHELP.EXE\0" 70 | #define HELPNAME "HXHELP.EXE" 71 | #else 72 | #error Extender and helper names not defined 73 | #endif 74 | 75 | #define LOW( c ) ((c)|0x20) /*Quick and dirty lower casing*/ 76 | 77 | #define LINK_SIGNATURE 0xdeb0deb0L 78 | 79 | #if defined(DOS4G) || defined(CAUSEWAY) || defined(HX) 80 | #define LINK_VECTOR 0x06 81 | #else 82 | #define LINK_VECTOR 0x01 83 | #endif 84 | 85 | typedef struct RMBuff { 86 | unsigned long ptr; 87 | unsigned long len; 88 | } RMBuff; 89 | 90 | #ifdef SERVER 91 | 92 | #define _DBG( s ) 93 | #define _DBG_ExitFunc( s ) 94 | 95 | #if defined(DOS4G) 96 | extern void far *RMLinToPM( unsigned long linear_addr, int pool ); 97 | #else 98 | static unsigned short Meg1; 99 | #define RMLinToPM(x,y) MK_FP(Meg1,x) 100 | #endif 101 | #define GetDosByte(x) (*(char far *)RMLinToPM(x,1)) 102 | #define GetDosLong(x) (*(unsigned long far *)RMLinToPM(x,1)) 103 | #define PutDosByte(x,d) (*(char far *)RMLinToPM(x,1)=d) 104 | #define PutDosLong(x,d) (*(unsigned long far *)RMLinToPM(x,1)=d) 105 | extern void CallRealMode( unsigned long dos_addr ); 106 | 107 | static unsigned long RMProcAddr; 108 | static RMBuff far *RMBuffPtr; 109 | 110 | #if defined(CAUSEWAY) 111 | int XVersion; 112 | #else 113 | char XVersion; 114 | #endif 115 | 116 | #if defined(CAUSEWAY) 117 | extern unsigned short GetZeroSel( void ); 118 | #pragma aux GetZeroSel = \ 119 | "mov ax,0ff00h" \ 120 | "int 31h" \ 121 | modify [bx ecx dx edi esi es] value [ax]; 122 | #endif 123 | 124 | #else 125 | 126 | static void BackToProtMode( void ); 127 | 128 | #define MK_LINEAR( p ) ( ( (long)FP_SEG( (void far *)(p) ) << 4 ) + FP_OFF( (void far *)(p) ) ) 129 | 130 | static jmp_buf RealModeState; 131 | static jmp_buf ProtModeState; 132 | static RMBuff Buff; 133 | char BackFromFork; 134 | static short OldPSP; 135 | static char BeenToProtMode; 136 | 137 | extern short DbgPSP( void ); 138 | extern short GetPSP( void ); 139 | extern void SetPSP( short ); 140 | extern int _fork( char far *pgm, char far *cmdl ); 141 | 142 | extern void doskludge( void ); 143 | #pragma aux doskludge = \ 144 | "mov ax,2a00h" \ 145 | "sub sp,50h" \ 146 | "int 21h" \ 147 | parm caller [ ax ] modify [ sp cx dx ]; 148 | 149 | extern const char far *DOSEnvFind( char * ); 150 | 151 | #endif 152 | 153 | extern unsigned short GetCS( void ); 154 | #pragma aux GetCS = "mov ax,cs" value [ ax ]; 155 | 156 | 157 | unsigned RemoteGet( char *rec, unsigned len ) 158 | { 159 | unsigned received; 160 | #ifdef SERVER 161 | unsigned long buff; 162 | 163 | _DBG(("Remote Get Calling real mode - %8.8lx %8.8lx\n", RMProcAddr, RMBuffPtr->ptr)); 164 | CallRealMode( RMProcAddr ); 165 | _DBG(("Remote Get Back from real mode\n")); 166 | buff = RMBuffPtr->ptr; 167 | received = RMBuffPtr->len; 168 | len = received; 169 | _DBG(("Remote Geting %d bytes\n",len)); 170 | while( len != 0 ) { 171 | *rec = GetDosByte( buff ); 172 | ++buff; 173 | ++rec; 174 | --len; 175 | } 176 | _DBG(("Remote Get Done\n")); 177 | #else 178 | _DBG_EnterFunc( "RemoteGet()" ); 179 | len = len; 180 | Buff.ptr = MK_LINEAR( rec ); 181 | BackToProtMode(); 182 | received = Buff.len; 183 | _DBG_DumpBytes( rec, received ); 184 | _DBG_ExitFunc( "RemoteGet()" ); 185 | #endif 186 | return( received ); 187 | } 188 | 189 | unsigned RemotePut( char *snd, unsigned len ) 190 | { 191 | #ifdef SERVER 192 | unsigned long buff; 193 | 194 | _DBG(("Remote Put - %8.8lx %8.8lx\n", RMProcAddr, RMBuffPtr->ptr)); 195 | RMBuffPtr->len = len; 196 | _DBG(("Remote Put %d bytes\n",len)); 197 | buff = RMBuffPtr->ptr; 198 | while( len != 0 ) { 199 | PutDosByte( buff, *snd ); 200 | ++buff; 201 | ++snd; 202 | --len; 203 | } 204 | _DBG(("Remote Put Calling real mode\n")); 205 | CallRealMode( RMProcAddr ); 206 | _DBG(("Remote Put Back from real mode\n")); 207 | #else 208 | _DBG_EnterFunc( "RemotePut()" ); 209 | _DBG_DumpBytes( snd, len ); 210 | Buff.len = len; 211 | Buff.ptr = MK_LINEAR( snd ); 212 | BackToProtMode(); 213 | _DBG_ExitFunc( "RemotePut()" ); 214 | #endif 215 | return( len ); 216 | } 217 | 218 | #ifdef SERVER 219 | 220 | char far *GetScreenPointer( void ) 221 | { 222 | #if defined( ACAD ) 223 | return( MK_FP( Meg1, 0xB0000 ) ); 224 | #elif defined(CAUSEWAY) 225 | return( MK_FP( Meg1, 0xB0000 ) ); 226 | #elif defined(PHARLAP) 227 | return( MK_FP( 0x1C, 0 ) ); 228 | #elif defined( DOS4G ) 229 | return( MK_FP( 0x50, 0 ) ); 230 | #endif 231 | } 232 | 233 | #else 234 | 235 | void BackToProtMode( void ) 236 | { 237 | if( setjmp( RealModeState ) == 0 ) { 238 | _DBG_Writeln( "ENTERING PROTECTED MODE" ); 239 | longjmp( ProtModeState, 0 ); 240 | } 241 | _DBG_Writeln( "RETURNED FROM PROTECTED MODE" ); 242 | } 243 | 244 | void far BackFromProtMode( void ) 245 | { 246 | BeenToProtMode = 1; 247 | if( setjmp( ProtModeState ) == 0 ) { 248 | OldPSP = GetPSP(); 249 | SetPSP( DbgPSP() ); 250 | longjmp( RealModeState, 0 ); 251 | } 252 | SetPSP( OldPSP ); 253 | } 254 | 255 | static char *CopyStr( const char far *src, char *dst ) 256 | { 257 | while( *dst = *src ) { 258 | dst++; 259 | src++; 260 | } 261 | return( dst ); 262 | } 263 | 264 | static char *SearchPath( const char far *env, const char *file, char *buff, char **pendname ) 265 | { 266 | char *endname; 267 | char *name; 268 | tiny_ret_t rc; 269 | char save[20]; 270 | unsigned len; 271 | char *ptr; 272 | 273 | if( env == NULL ) { 274 | CopyStr( ";", buff ); 275 | } else { 276 | CopyStr( ";", CopyStr( env, CopyStr( ".;", buff ) ) ); 277 | } 278 | name = buff; 279 | len = strlen( file ); 280 | while( *name ) { 281 | endname = name; 282 | while( *endname != ';' ) 283 | ++endname; 284 | memcpy( save, endname, len + 2 ); 285 | ptr = endname; 286 | if( name != ptr && ptr[-1]!=':' && ptr[-1]!='/' && ptr[-1]!='\\' ) { 287 | *ptr++ = '\\'; 288 | } 289 | memcpy( ptr, file, len + 1 ); 290 | rc = TinyOpen( name, 0 ); 291 | if( TINY_OK( rc ) ) { 292 | TinyClose( TINY_INFO( rc ) ); 293 | break; 294 | } 295 | memcpy( endname, save, len + 2 ); 296 | name = endname + 1; 297 | } 298 | *pendname = endname; 299 | return( name ); 300 | } 301 | 302 | static char *CheckPath( const char far *path, char *fullpath, char **endname ) 303 | { 304 | const char *namep; 305 | char *name; 306 | 307 | for( namep = EXTENDER_NAMES; *namep != '\0'; ) { 308 | name = SearchPath( path, namep, fullpath, endname ); 309 | if( *name != '\0' ) 310 | return( name ); 311 | while( *namep++ != '\0' ) {} // skip to next extender name 312 | } 313 | return( NULL ); 314 | } 315 | 316 | static char *FindExtender( char *fullpath, char **endname ) 317 | { 318 | #if defined(DOS4G) 319 | char *name; 320 | const char far *d4gname; 321 | unsigned len; 322 | 323 | d4gname = DOSEnvFind( "DOS4GPATH" ); 324 | if( d4gname != NULL ) { 325 | _DBG_Write("Got DOS4GPATH -<"); 326 | _DBG_Write(d4gname); 327 | _DBG_Writeln(">"); 328 | len = _fstrlen( d4gname ); 329 | if( len > 4 ) { 330 | const char far *ext = d4gname + len - 4; 331 | if( ext[0] == '.' 332 | && LOW( ext[1] ) == 'e' 333 | && LOW( ext[2] ) == 'x' 334 | && LOW( ext[3] ) == 'e' ) { 335 | _DBG_Writeln( "is exe\r\n" ); 336 | *endname = CopyStr( d4gname, fullpath ); 337 | return( fullpath ); 338 | } 339 | } 340 | name = CheckPath( d4gname, fullpath, endname ); 341 | if( name != NULL ) { 342 | _DBG_Writeln( "found in path\r\n" ); 343 | return( name ); 344 | } 345 | } 346 | #endif 347 | return( CheckPath( DOSEnvFind( "PATH" ), fullpath, endname ) ); 348 | } 349 | 350 | #if defined(PHARLAP) 351 | 352 | static const char *GetHelpName( char *exe_name ) 353 | { 354 | /* 355 | if executable is: 356 | PE format, subsystem PE_SS_PL_DOSSTYLE (0x42) then PEDHELP.EXP 357 | or: 358 | PE format, other subsystems then PENHELP.EXP 359 | otherwise: 360 | PLSHELP.EXP 361 | */ 362 | tiny_ret_t rc; 363 | tiny_handle_t handle; 364 | unsigned_32 off; 365 | union { 366 | dos_exe_header dos; 367 | pe_header pe; 368 | } head; 369 | 370 | handle = -1; 371 | rc = TinyOpen( exe_name, 0 ); 372 | if( TINY_ERROR( rc ) ) 373 | goto exp; 374 | handle = TINY_INFO( rc ); 375 | TinyRead( handle, &head.dos, sizeof( head.dos ) ); 376 | if( head.dos.signature != DOS_SIGNATURE ) 377 | goto exp; 378 | TinySeek( handle, OS2_NE_OFFSET, SEEK_SET ); 379 | TinyRead( handle, &off, sizeof( off ) ); 380 | TinySeek( handle, off, SEEK_SET ); 381 | TinyRead( handle, &head.pe, sizeof( head.pe ) ); 382 | TinyClose( handle ); 383 | handle = -1; 384 | switch( head.pe.signature ) { 385 | case PE_SIGNATURE: 386 | case PL_SIGNATURE: 387 | if( head.pe.subsystem == PE_SS_PL_DOSSTYLE ) { 388 | _DBG_Writeln( "Want PEDHELP" ); 389 | return( HELPNAME_DS ); 390 | } 391 | _DBG_Writeln( "Want PENHELP" ); 392 | return( HELPNAME_NS ); 393 | } 394 | exp: 395 | if( handle != -1 ) 396 | TinyClose( handle ); 397 | _DBG_Writeln( "Want PLSHELP" ); 398 | return( HELPNAME ); 399 | } 400 | #endif 401 | #endif 402 | 403 | char *RemoteLink( char *parm, char server ) 404 | { 405 | #ifdef SERVER 406 | unsigned long link; 407 | #if defined(ACAD) 408 | { 409 | XVersion = 2; 410 | if( GetCS() & 3 ) { 411 | Meg1 = 0x37; 412 | } else { 413 | Meg1 = 0x60; 414 | } 415 | } 416 | #elif defined(PHARLAP) 417 | { 418 | CONFIG_INF config; 419 | static char buff[256]; 420 | 421 | _dx_config_inf(&config, buff ); 422 | XVersion = config.c_major; 423 | if( XVersion >= 3 ) { 424 | Meg1 = config.c_dos_sel; 425 | } else { 426 | Meg1 = 0x60; 427 | } 428 | } 429 | #elif defined(CAUSEWAY) 430 | Meg1 = GetZeroSel(); 431 | #endif 432 | link = GetDosLong( LINK_VECTOR * 4 ); 433 | if( link >= (1024UL * 1024UL) || GetDosLong( link ) != LINK_SIGNATURE ) { 434 | return( TRP_ERR_not_from_command ); 435 | } 436 | RMBuffPtr = RMLinToPM( GetDosLong( link + 4 ), 0 ); 437 | RMProcAddr = GetDosLong( link + 8 ); 438 | PutDosLong( LINK_VECTOR * 4, GetDosLong( link + 12 ) ); 439 | #else 440 | static char fullpath[256]; /* static because ss != ds */ 441 | static char buff[256]; 442 | static char *endname; 443 | char *name; 444 | char *buffp; 445 | char *endparm; 446 | void far *link[4]; 447 | void far * far * link_ptr; 448 | unsigned len; 449 | #if defined(PHARLAP) 450 | char *exe_name; 451 | #endif 452 | 453 | _DBG_EnterFunc( "RemoteLink()" ); 454 | BackFromFork = 0; 455 | link_ptr = (void far *)(LINK_VECTOR * 4); 456 | link[ 3 ] = *link_ptr; 457 | link[ 2 ] = MK_FP( GetCS(), (unsigned )BackFromProtMode ); 458 | link[ 1 ] = (void far *)MK_LINEAR( &Buff ); 459 | link[ 0 ] = (void far *)LINK_SIGNATURE; 460 | *link_ptr = (void far *)MK_LINEAR( &link ); 461 | if( parm == NULL ) 462 | parm = "\0\0"; 463 | while( *parm == ' ' ) 464 | ++parm; 465 | if( *parm == '`' ) { 466 | buffp = buff; 467 | ++parm; 468 | for( ;; ) { 469 | *buffp = *parm; 470 | ++buffp; 471 | if( *parm == '\0' ) 472 | break; 473 | ++parm; 474 | if( parm[-1] == '`' ) { 475 | break; 476 | } 477 | } 478 | *buffp = '\0'; 479 | } 480 | while( *parm == ' ' ) 481 | ++parm; 482 | if( setjmp( RealModeState ) == 0 ) { 483 | name = FindExtender( fullpath, &endname ); 484 | if( name == NULL ) { 485 | _DBG_ExitFunc( "RemoteLink(), unable to find extender" ); 486 | return( TRP_ERR_no_extender ); 487 | } 488 | _DBG_Write( "Extender name: " ); 489 | _DBG_NoTabWriteln( name ); 490 | while( *endname++ != '\0' ) {} // skip after extender name + '\0' 491 | #if defined(ACAD) 492 | buffp = buff; 493 | buff[ 0 ] = '\0'; 494 | #else 495 | { 496 | static char *endhelp; 497 | const char *help_name; 498 | 499 | #if defined(PHARLAP) 500 | exe_name = parm; 501 | while( *exe_name++ != '\0' ) {} 502 | help_name = GetHelpName( exe_name ); 503 | #else 504 | help_name = HELPNAME; 505 | #endif 506 | buffp = SearchPath( DOSEnvFind( "PATH" ), help_name, buff, &endhelp ); 507 | if( !*buffp ) { 508 | _DBG_ExitFunc( "RemoteLink(), unable to find extender help file" ); 509 | return( TRP_ERR_no_extender ); 510 | } 511 | } 512 | #endif 513 | _DBG_Write( "Extender help name: " ); 514 | _DBG_NoTabWriteln( buffp ); 515 | endparm = CopyStr( parm, endname + 1 ); // reserve length byte 516 | endparm = CopyStr( buffp, CopyStr( " ", endparm ) ); 517 | #if defined(PHARLAP) 518 | endparm = CopyStr( " ", endparm ); 519 | endparm = CopyStr( exe_name, endparm ); // add extra executable name 520 | #endif 521 | len = endparm - ( endname + 1 ); 522 | if( len > 126 ) 523 | len = 126; 524 | *endname = len; // setup length byte 525 | endparm = endname + len + 1; 526 | endparm[0] = '\r'; 527 | endparm[1] = '\0'; 528 | _DBG_Write( "Extender Cmd line: " ); 529 | _DBG_NoTabWriteln( endname + 1 ); 530 | _DBG_Writeln( "calling _fork() to start extender/debugee" ); 531 | if( _fork( name, endname ) != 0 ) { 532 | _DBG_ExitFunc( "RemoteLink(), unable to start extender" ); 533 | return( TRP_ERR_cant_start_extender ); 534 | } 535 | } else if( BackFromFork || !BeenToProtMode ) { 536 | _DBG_ExitFunc( "RemoteLink(), extender could not start extender " 537 | "help file" ); 538 | return( TRP_ERR_cant_start_extender ); 539 | } 540 | #endif 541 | parm = parm; 542 | server = server; 543 | _DBG_ExitFunc( "RemoteLink()" ); 544 | return( NULL ); 545 | } 546 | 547 | void RemoteUnLink( void ) 548 | { 549 | #ifdef SERVER 550 | CallRealMode( RMProcAddr ); 551 | #else 552 | _DBG_EnterFunc( "RemoteUnLink()" ); 553 | if( setjmp( RealModeState ) == 0 ) { 554 | doskludge(); /* Ask brian. I don't feel like writing a book */ 555 | SetPSP( OldPSP ); 556 | longjmp( ProtModeState, 0 ); 557 | } 558 | _DBG_ExitFunc( "RemoteUnLink()" ); 559 | #endif 560 | } 561 | 562 | char RemoteConnect( void ) 563 | { 564 | return( 1 ); 565 | } 566 | 567 | void RemoteDisco( void ) 568 | { 569 | } 570 | -------------------------------------------------------------------------------- /trap_src/dosx/hx/dos.trp/makefile: -------------------------------------------------------------------------------- 1 | #pmake: build trap lcl os_dos dsx cpu_386 x86 2 | 3 | host_os = dos 4 | host_cpu = i86 5 | 6 | os = dos 7 | srv = hx 8 | cpu = x86 9 | which = TRAP 10 | 11 | extra_c_flags = -DHX 12 | 13 | !include $(trap_dir)/lcl/dos/dosx/dosx.mif 14 | !include $(trap_dir)/master.mif 15 | -------------------------------------------------------------------------------- /ui_src/dos/uibios.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Open Watcom Project 4 | * 5 | * Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved. 6 | * 7 | * ======================================================================== 8 | * 9 | * This file contains Original Code and/or Modifications of Original 10 | * Code as defined in and that are subject to the Sybase Open Watcom 11 | * Public License version 1.0 (the 'License'). You may not use this file 12 | * except in compliance with the License. BY USING THIS FILE YOU AGREE TO 13 | * ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is 14 | * provided with the Original Code and Modifications, and is also 15 | * available at www.sybase.com/developer/opensource. 16 | * 17 | * The Original Code and all software distributed under the License are 18 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 19 | * EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM 20 | * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR 22 | * NON-INFRINGEMENT. Please see the License for the specific language 23 | * governing rights and limitations under the License. 24 | * 25 | * ======================================================================== 26 | * 27 | * Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE 28 | * DESCRIBE IT HERE! 29 | * 30 | ****************************************************************************/ 31 | 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include "uidos.h" 39 | #include "biosui.h" 40 | #include "uidef.h" 41 | #include "dpmi.h" 42 | 43 | typedef struct { 44 | unsigned short int_num; 45 | unsigned short real_ds; 46 | unsigned short real_es; 47 | unsigned short real_fs; 48 | unsigned short real_gs; 49 | long real_eax; 50 | long real_edx; 51 | } PHARLAP_block; 52 | 53 | void intern DBCSCharacterMap( void ); 54 | 55 | static MONITOR ui_data = { 56 | 25, 57 | 80, 58 | M_CGA, 59 | NULL, 60 | NULL, 61 | NULL, 62 | NULL, 63 | 4, 64 | 1 65 | }; 66 | 67 | 68 | unsigned BIOSVidPage; 69 | 70 | #ifdef __386__ 71 | void far *firstmeg( unsigned segment, unsigned offset ) 72 | { 73 | #if defined(__OSI__) || __WATCOMC__ >= 1000 74 | return( MK_FP( _ExtenderRealModeSelector, (unsigned) (segment << 4) + offset ) ); 75 | #else 76 | if( _IsRational() ) { 77 | return( MK_FP( FP_SEG( &BIOSVidPage ), (unsigned) ( segment << 4 ) + offset ) ); 78 | } else { 79 | return( MK_FP( REAL_SEGMENT, (unsigned) ( segment << 4 ) + offset ) ); 80 | } 81 | #endif 82 | } 83 | #endif 84 | 85 | #ifdef __386__ 86 | void IdleInterrupt( void ) 87 | { 88 | #ifdef __OSI__ 89 | return; /* Can't do anything */ 90 | #else 91 | if( _IsRational() ) { 92 | DPMIIdle(); /* Assume DPMI if Rational; else dunno */ 93 | } 94 | return; 95 | #endif 96 | } 97 | #else 98 | extern void DOSIdleInterrupt( void ); 99 | #pragma aux DOSIdleInterrupt = "int 28h"; 100 | 101 | void IdleInterrupt( void ) 102 | { 103 | DOSIdleInterrupt(); 104 | } 105 | #endif 106 | 107 | void intern setvideomode( unsigned mode ) 108 | /***************************************/ 109 | { 110 | BIOSSetMode( mode ); 111 | } 112 | 113 | 114 | bool global uiset80col( void ) 115 | /****************************/ 116 | 117 | { 118 | register bool status; 119 | 120 | status = FALSE; 121 | if( UIData->width != 80 ) { 122 | if( UIData->colour == M_MONO ) { 123 | setvideomode( 7 ); 124 | } else if( UIData->colour == M_BW ) { 125 | setvideomode( 2 ); 126 | } else { 127 | setvideomode( 3 ); 128 | } 129 | status = TRUE; 130 | } 131 | return( status ); 132 | } 133 | 134 | extern unsigned char DOS_int( unsigned short, unsigned short, unsigned short ); 135 | #pragma aux DOS_int = \ 136 | _INT_21 \ 137 | parm [ax] [cx] [dx] value [al]; 138 | 139 | #define desqview_present() (DOS_int(0x2b01,0x4445,0x5351)!=0xff) 140 | 141 | /* 142 | The code for video_buffer is identical for DOS/V and desqview 143 | (Get Video Buffer: int 10h, AH=FEh) 144 | */ 145 | 146 | void far * global video_buffer( void far *vbuff ) 147 | /***********************************************/ 148 | { 149 | #ifdef __386__ 150 | union REGPACK regs; 151 | rm_call_struct dblock; 152 | 153 | if( _IsPharLap() ) { 154 | memset( ®s, 0, sizeof( regs ) ); 155 | regs.h.ah = 0xfe; 156 | regs.x.edi = FP_OFF( vbuff ); 157 | regs.w.es = FP_SEG( vbuff ); 158 | intr( BIOS_VIDEO, ®s ); 159 | if( FP_OFF( vbuff ) != regs.x.edi ) { 160 | /* we use FP_OFF since old_selector==0x34 and new_selector==0x37 */ 161 | vbuff = MK_FP( regs.w.es, regs.x.edi ); 162 | } 163 | } else if( _IsRational() ) { 164 | memset( &dblock, 0, sizeof( dblock ) ); 165 | dblock.eax = 0xfe00; /* get video buffer addr */ 166 | dblock.es = FP_OFF( vbuff ) >> 4; 167 | dblock.edi = (FP_OFF( vbuff ) & 0x0f); 168 | DPMISimulateRealModeInterrupt( BIOS_VIDEO, 0, 0, &dblock ); 169 | return( firstmeg( dblock.es, dblock.edi ) ); 170 | } 171 | return( vbuff ); 172 | #else 173 | extern void far * get_video_buffer( void far * ); 174 | #pragma aux get_video_buffer = \ 175 | 0xb4 0xfe /* mov ah,0xfe */ \ 176 | 0xcd 0x10 /* int 0x10 */ \ 177 | parm caller [es di] \ 178 | value [es di] \ 179 | modify [ah]; 180 | 181 | return( get_video_buffer( vbuff ) ); 182 | #endif 183 | } 184 | 185 | 186 | typedef struct { 187 | unsigned char start_range; 188 | unsigned char end_range; 189 | } dbcs_pair; 190 | 191 | #ifndef __386__ 192 | 193 | extern dbcs_pair far * dbcs_vector_table( void ); 194 | #pragma aux dbcs_vector_table = \ 195 | "push ds" \ 196 | "mov ax,6300h" /* get DBCS vector table */ \ 197 | "int 21h" \ 198 | "mov di,ds" \ 199 | "pop ds" \ 200 | value [di si] \ 201 | modify [ax]; 202 | 203 | #else 204 | 205 | dbcs_pair far * intern dbcs_vector_table( void ) 206 | /***************************************************/ 207 | { 208 | union REGPACK regs; 209 | static dbcs_pair dbcs_dummy = { 0, 0 }; 210 | 211 | if( UIData->colour == M_MONO ) return( &dbcs_dummy ); 212 | if( _IsPharLap() ) { 213 | PHARLAP_block pblock; 214 | 215 | memset( &pblock, 0, sizeof( pblock ) ); 216 | memset( ®s, 0, sizeof( regs ) ); 217 | pblock.real_eax = 0x6300; /* get DBCS vector table */ 218 | pblock.int_num = 0x21; /* DOS call */ 219 | regs.x.eax = 0x2511; /* issue real-mode interrupt */ 220 | regs.x.edx = FP_OFF( &pblock ); /* DS:EDX -> parameter block */ 221 | regs.w.ds = FP_SEG( &pblock ); 222 | intr( 0x21, ®s ); 223 | if( pblock.real_ds == 0xFFFF ) { // wierd OS/2 value 224 | return( &dbcs_dummy ); 225 | } else { 226 | return( firstmeg( (unsigned) pblock.real_ds, (unsigned) regs.w.si ) ); 227 | } 228 | } else if( _IsRational() ) { 229 | rm_call_struct dblock; 230 | 231 | memset( &dblock, 0, sizeof( dblock ) ); 232 | dblock.eax = 0x6300; /* get DBCS vector table */ 233 | DPMISimulateRealModeInterrupt( 0x21, 0, 0, &dblock ); 234 | if( (dblock.flags & 1) == 0 ) { 235 | return( firstmeg( dblock.ds, dblock.esi ) ); 236 | } 237 | } 238 | return( &dbcs_dummy ); 239 | } 240 | 241 | #endif 242 | 243 | static dbcs_pair Pairs[5]; // safe enough for now 244 | static int Init; 245 | 246 | void intern initdbcs( void ) 247 | { 248 | dbcs_pair *p; 249 | dbcs_pair far *s; 250 | 251 | s = dbcs_vector_table(); 252 | p = Pairs; 253 | while( s->start_range != 0 ) { 254 | p->start_range = s->start_range; 255 | p->end_range = s->end_range; 256 | ++p; 257 | ++s; 258 | } 259 | p->start_range = 0; 260 | p->end_range = 0; 261 | Init = TRUE; 262 | } 263 | 264 | int global uiisdbcs( void ) 265 | { 266 | if( !Init ) initdbcs(); 267 | return( Pairs[0].start_range != 0 ); 268 | } 269 | 270 | int global uionnec( void ) 271 | { 272 | return( FALSE ); 273 | } 274 | 275 | int global uicharlen( int ch ) 276 | { 277 | dbcs_pair *p; 278 | 279 | 280 | if( !Init ) initdbcs(); 281 | for( p = Pairs; p->start_range != 0; ++p ) { 282 | if( ch >= p->start_range && ch <= p->end_range ) return( 2 ); 283 | } 284 | return( 1 ); 285 | } 286 | 287 | #define ALPHA_SMALL_BW 0 288 | #define ALPHA_SMALL_COL 1 289 | #define ALPHA_LARGE_BW 2 290 | #define ALPHA_LARGE_COL 3 291 | #define GR_MED_4COL 4 // 16K memory (40 characters wide) 292 | #define GR_MED_BW 5 // 16K memory (40 characters wide) 293 | #define GR_HIGH_BW 6 // 16K memory (80 characters wide) 294 | #define MONOCHROME 7 295 | #define GR_LOW_16COL 8 // 16K memory (20 characters wide) 296 | #define GR_MED_16COL 9 // 32K memory 297 | #define GR_HIGH_4COL 10 // 32K memory 298 | #define EGA_LOW_16COL 13 // 64K memory 299 | #define EGA_HIGH_16COL 14 // 64K memory 300 | #define EGA_HIGH_MONO 15 // 64K memory 301 | #define EGA_HIGH_4COL 16 // 64K memory 302 | #define VGA_2COL 17 303 | #define VGA_16COL 18 304 | #define VGA_256COL 19 305 | #define TSENG_44x132 34 // Text Mode 306 | #define TSENG_25x132 35 // Text Mode 307 | #define TSENG_28x132 36 // Text Mode 308 | #define TSENG_60x80 38 // Text Mode 309 | #define TSENG_40x100 42 // Text Mode 310 | #define ACER_25X132 35 // Text Mode 311 | #define ACER_44X132 51 // Text Mode 312 | #define TRIDENT_start 80 // Text Modes 80-90 313 | #define TRIDENT_end 90 // Text Mode 314 | #define DELL_43X132 84 // Text Mode 315 | #define DELL_25X132 85 // Text Mode 316 | 317 | int IsTextMode( void ) 318 | { 319 | unsigned char text_mode = 0; 320 | #if 0 321 | unsigned char mode; 322 | unsigned char page; 323 | struct cursor_pos cursor_position; 324 | unsigned short __FAR *video_mem; 325 | unsigned short char_attr_bios; 326 | unsigned short char_attr_vmem; 327 | 328 | /* get current video mode */ 329 | mode = BIOSGetMode(); 330 | /* get current video page */ 331 | page = BIOSGetPage(); 332 | /* get cursor position for current page */ 333 | cursor_position = BIOSGetCurPos( page ); 334 | if( mode < GR_MED_4COL || mode == MONOCHROME || mode > VGA_256COL ) { 335 | video_mem = (unsigned short __FAR *) UIData->screen.origin; 336 | /* set cursor position to top left corner of screen */ 337 | BIOSSetCurPos( 0, 0, page ); 338 | /* get character/attribute at that location */ 339 | char_attr_bios = BIOSGetCharAttr( page ); 340 | /* get character/attribute from screen memory */ 341 | char_attr_vmem = *video_mem; 342 | if( char_attr_bios == char_attr_vmem ) { 343 | /* change the character we read through BIOS call */ 344 | char_attr_bios ^= 1; 345 | /* write out character using BIOS */ 346 | BIOSSetCharAttr( char_attr_bios, page ); 347 | /* get character/attribute from screen memory */ 348 | char_attr_vmem = *video_mem; 349 | if( char_attr_bios == char_attr_vmem ) { 350 | /* restore character that was there */ 351 | *video_mem = char_attr_bios ^ 1; 352 | text_mode = 1; 353 | } 354 | } 355 | } 356 | /* restore cursor position for current page */ 357 | BIOSSetCurPos( cursor_position.row, cursor_position.col, page ); 358 | #else 359 | // the old code has problems in dosemu if resolution is != 80x25 360 | // this code here relies on VGA, so not really safe, but works ... 361 | _asm { 362 | mov dx, 3ceh 363 | in al, dx 364 | mov ah, al 365 | mov al, 6 366 | out dx, al 367 | inc dx 368 | in al, dx 369 | and al, 1 370 | xor al, 1 371 | mov text_mode, al 372 | dec dx 373 | mov al, ah 374 | out dx, al 375 | } 376 | #endif 377 | return( text_mode ); 378 | } 379 | 380 | bool intern initmonitor( void ) 381 | /*****************************/ 382 | { 383 | register bool ega; 384 | register unsigned char mode; 385 | struct ega_info info; 386 | 387 | if( UIData == NULL ) { 388 | UIData = &ui_data; 389 | } 390 | 391 | BIOSVidPage = BIOSGetPage(); 392 | mode = BIOSGetMode(); 393 | UIData->width = BIOSGetColumns(); 394 | UIData->height = 25; 395 | info = BIOSEGAInfo(); 396 | if( info.switches < 0x0C && info.mono <= 0x01 && info.mem <= 0x03 ) { 397 | UIData->height = BIOSGetRows(); 398 | ega = TRUE; 399 | } else { 400 | ega = FALSE; 401 | } 402 | if( ( mode == MONOCHROME ) || ( mode == EGA_HIGH_MONO ) ) { 403 | UIData->colour = M_MONO; 404 | } else if( ( mode == ALPHA_SMALL_COL ) || ( mode == ALPHA_LARGE_COL ) ) { 405 | if( ega ) { 406 | UIData->colour = M_EGA; 407 | } else { 408 | UIData->colour = M_CGA; 409 | } 410 | } else if( ( mode == ALPHA_SMALL_BW ) || ( mode == ALPHA_LARGE_BW ) ) { 411 | UIData->colour = M_BW; 412 | } else if( mode > VGA_256COL ) { 413 | /* 414 | if mode is out of known range then assume it's a VGA/SVGA mode 415 | */ 416 | UIData->colour = M_VGA; 417 | } else { 418 | return( FALSE ); 419 | } 420 | 421 | return( TRUE ); 422 | } 423 | 424 | 425 | int intern initbios( void ) 426 | /*************************/ 427 | { 428 | int initialized; 429 | unsigned short far *poffset; 430 | LPPIXEL old_origin; 431 | 432 | initialized = FALSE; 433 | if( initmonitor() ) { 434 | UIData->desqview = (desqview_present() != 0); 435 | UIData->f10menus = TRUE; 436 | 437 | poffset = firstmeg( BIOS_PAGE, SCREEN_OFFSET ); 438 | if( UIData->colour == M_MONO ) { 439 | UIData->screen.origin = firstmeg( 0xb000, *poffset ); 440 | } else { 441 | UIData->screen.origin = firstmeg( 0xb800, *poffset ); 442 | } 443 | if( UIData->desqview ) { 444 | UIData->screen.origin = 445 | (PIXEL far *)video_buffer( UIData->screen.origin ); 446 | } 447 | if( uiisdbcs() ) { 448 | old_origin = UIData->screen.origin; 449 | UIData->screen.origin = 450 | (PIXEL far *)video_buffer( UIData->screen.origin ); 451 | if( old_origin != UIData->screen.origin ) { 452 | UIData->desqview = TRUE; 453 | } 454 | DBCSCharacterMap(); /* in UIMAPCH.C */ 455 | } 456 | UIData->screen.increment = UIData->width; 457 | 458 | /* if we are in a text mode then continue the initialization */ 459 | if( IsTextMode() ) { 460 | uiinitcursor(); 461 | initkeyboard(); 462 | UIData->mouse_acc_delay = 5; /* ticks */ 463 | UIData->mouse_rpt_delay = 1; /* ticks */ 464 | UIData->mouse_clk_delay = 5; /* ticks */ 465 | UIData->tick_delay = 9; /* ticks */ 466 | UIData->mouse_speed = 8; /* mickeys to ticks ratio */ 467 | initialized = TRUE; 468 | } 469 | } 470 | return( initialized ); 471 | } 472 | 473 | unsigned global uiclockdelay( unsigned milli ) 474 | { 475 | /* this routine converts milli-seconds into platform */ 476 | /* dependant units - used to set mouse & timer delays */ 477 | return( milli * 18 / 1000 ); 478 | } 479 | 480 | 481 | void intern finibios( void ) 482 | /**************************/ 483 | { 484 | uifinicursor(); 485 | } 486 | 487 | 488 | /* update the physical screen with contents of virtual copy */ 489 | 490 | void intern physupdate( SAREA *area ) 491 | /*************************************/ 492 | { 493 | int i; 494 | unsigned short offset; 495 | unsigned short count; 496 | 497 | /* 498 | The code for desqview_update is identical for DOS/V 499 | (Update Video Display: int 10h, AH=FFh, CX=count, ES:DI=buffer) 500 | */ 501 | 502 | #ifdef __386__ 503 | union REGPACK regs; 504 | #else 505 | #pragma aux desqview_update = 0xcd 0x10 parm [ah] [es] [di] [cx]; 506 | extern void desqview_update( unsigned char, unsigned, unsigned, unsigned ); 507 | #endif 508 | 509 | if( UIData->desqview ) { 510 | count = area->width * sizeof( PIXEL ); 511 | for( i = area->row; i < (area->row + area->height); i++ ) { 512 | offset = ( i * UIData->width + area->col ) * sizeof( PIXEL ); 513 | 514 | #ifdef __386__ 515 | memset( ®s, 0, sizeof( regs ) ); 516 | if( _IsPharLap() ) { 517 | 518 | // This code does not work as advertised under DOS/V 519 | // regs.h.ah = 0xff; /* update logical screen buffer request */ 520 | // regs.w.es = FP_SEG( UIData->screen.origin ); 521 | // regs.x.edi = FP_OFF( UIData->screen.origin ); 522 | // regs.x.edi += offset; 523 | // regs.w.cx = count; 524 | // intr( BIOS_VIDEO, ®s ); 525 | 526 | PHARLAP_block pblock; 527 | 528 | memset( &pblock, 0, sizeof( pblock ) ); 529 | pblock.int_num = BIOS_VIDEO; /* VIDEO call */ 530 | pblock.real_eax = 0xff00; /* update from v-screen */ 531 | pblock.real_es = FP_OFF( UIData->screen.origin ) >> 4; 532 | regs.x.edi = (FP_OFF( UIData->screen.origin ) & 0x0f) + offset; 533 | regs.w.cx = count; 534 | regs.x.eax = 0x2511; /* issue real-mode interrupt */ 535 | regs.x.edx = FP_OFF( &pblock ); /* DS:EDX -> parameter block */ 536 | regs.w.ds = FP_SEG( &pblock ); 537 | intr( 0x21, ®s ); 538 | 539 | } else if( _IsRational() ) { 540 | rm_call_struct dblock; 541 | 542 | memset( &dblock, 0, sizeof( dblock ) ); 543 | dblock.eax = 0xff00; /* update from v-screen */ 544 | dblock.es = FP_OFF( UIData->screen.origin ) >> 4; 545 | dblock.edi = (FP_OFF( UIData->screen.origin ) & 0x0f) 546 | + offset; 547 | dblock.ecx = count; 548 | DPMISimulateRealModeInterrupt( BIOS_VIDEO, 0, 0, &dblock ); 549 | } 550 | #else 551 | desqview_update( 0xff, FP_SEG( UIData->screen.origin ), 552 | FP_OFF( UIData->screen.origin ) + offset, count ); 553 | #endif 554 | } /* for */ 555 | } /* if */ 556 | } 557 | -------------------------------------------------------------------------------- /wv_src/dbgexec.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Open Watcom Project 4 | * 5 | * Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved. 6 | * 7 | * ======================================================================== 8 | * 9 | * This file contains Original Code and/or Modifications of Original 10 | * Code as defined in and that are subject to the Sybase Open Watcom 11 | * Public License version 1.0 (the 'License'). You may not use this file 12 | * except in compliance with the License. BY USING THIS FILE YOU AGREE TO 13 | * ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is 14 | * provided with the Original Code and Modifications, and is also 15 | * available at www.sybase.com/developer/opensource. 16 | * 17 | * The Original Code and all software distributed under the License are 18 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 19 | * EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM 20 | * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR 22 | * NON-INFRINGEMENT. Please see the License for the specific language 23 | * governing rights and limitations under the License. 24 | * 25 | * ======================================================================== 26 | * 27 | * Description: Run program until the next debugger event. 28 | * 29 | ****************************************************************************/ 30 | 31 | 32 | #include 33 | #include 34 | #include 35 | #include "dbgdefn.h" 36 | #include "dbgreg.h" 37 | #include "dbgtoken.h" 38 | #include "dbgtoggl.h" 39 | #include "dbginfo.h" 40 | #include "dbgbreak.h" 41 | #include "dbglit.h" 42 | #include "dbginp.h" 43 | #include "dbghook.h" 44 | #include "dbgrep.h" 45 | #include "trpcore.h" 46 | #include "mad.h" 47 | #include "dui.h" 48 | #include "enterdb.h" 49 | 50 | 51 | extern bool AdvMachState( int ); 52 | extern bool DispBPMsg( bool ); 53 | extern bool InsertBPs( bool ); 54 | extern void RemoveBPs( void ); 55 | extern bool InsertWPs( void ); 56 | extern bool UpdateWPs( void ); 57 | extern unsigned CheckBPs( unsigned, unsigned ); 58 | extern void Ring( void ); 59 | extern unsigned MakeProgRun( bool ); 60 | extern void DoSetWatchPnt( unsigned int, brkp * ); 61 | extern bool TBreak( void ); 62 | extern void PopInpStack( void ); 63 | extern bool PurgeInpStack( void ); 64 | extern void ReadDbgRegs( void ); 65 | extern void WriteDbgRegs( void ); 66 | extern void SectTblRead( machine_state * ); 67 | extern address GetRegIP( void ); 68 | extern bool AddLibInfo( bool, bool * ); 69 | extern char *StrCopy( char *, char * ); 70 | extern char *Format( char *buff, char *fmt, ... ); 71 | extern unsigned RemoteGetMsgText( char *, unsigned ); 72 | extern long RemoteThawThread( dtid_t ); 73 | extern long RemoteFreezeThread( dtid_t ); 74 | extern bool SourceStep( void ); 75 | extern bool SetUpTrace( bool ); 76 | extern void CheckForNewThreads( bool ); 77 | extern void CheckSegAlias( void ); 78 | extern void SetMemBefore( bool ); 79 | extern void SetMemAfter( bool ); 80 | extern void SetCodeDot( address ); 81 | extern char DlgFatal( void ); 82 | extern void InvalidateTblCache( void ); 83 | extern bool CheckStackPos( void ); 84 | extern void RecordEvent( char *p ); 85 | extern void RecordGo( char *p ); 86 | extern void CheckEventRecorded( void ); 87 | extern char *GetCmdName( int ); 88 | extern void RecordAsynchEvent( void ); 89 | extern dtid_t RemoteSetThread( dtid_t ); 90 | extern char *GetLastImageName( void ); 91 | extern bool DLLMatch( void ); 92 | extern void DUIPlayDead( bool ); 93 | extern bool TraceSimulate( void ); 94 | extern bool TraceStart( bool ); 95 | extern mad_trace_how TraceHow( bool force_into ); 96 | extern unsigned TraceCheck( unsigned ); 97 | extern void TraceStop( bool ); 98 | extern void ReMapPoints( image_entry *); 99 | extern void DbgUpdate( update_list ); 100 | extern void NameThread( dtid_t tid, char *name ); 101 | extern unsigned ProgPoke( address, void *, unsigned ); 102 | extern bool DlgScanDataAddr( char *str, address *value ); 103 | extern bool DlgScanLong( char *str, long *value ); 104 | extern unsigned NewCurrRadix( unsigned rad ); 105 | extern cmd_list *AllocCmdList(char *,unsigned int ); 106 | extern void FreeCmdList(cmd_list *); 107 | extern void PushCmdList(cmd_list *); 108 | extern void TypeInpStack(input_type); 109 | extern char *CnvNearestAddr( address, char *, unsigned ); 110 | extern void PopInpStack( void ); 111 | extern void ProcACmd( void ); 112 | extern bool SymUserModLoad( char *fname, address *loadaddr ); 113 | extern bool SymUserModUnload( char *fname ); 114 | 115 | extern input_stack *InpStack; 116 | extern machine_state *DbgRegs; 117 | extern tokens CurrToken; 118 | extern screen_state ScrnState; 119 | extern brkp DbgTmpBrk; 120 | extern char *TxtBuff; 121 | extern thread_state *HeadThd; 122 | extern thread_state *ExecThd; 123 | static char *MsgText; 124 | extern brkp UserTmpBrk; 125 | 126 | static int InCall = 0; 127 | 128 | char dbgbuff[256]; 129 | #if 0 130 | #define DBGMSG 131 | #include 132 | extern void __stdcall OutputDebugStringA( char * ); 133 | #define DebugMsg( x, ... ) sprintf( dbgbuff, x, __VA_ARGS__ ); OutputDebugStringA( dbgbuff ) 134 | #define DebugMsgC( x ) OutputDebugStringA( x ) 135 | #else 136 | #define DebugMsg( x, ... ) 137 | #define DebugMsgC( x ) 138 | #endif 139 | 140 | static void NoCRLF( char *str ) 141 | /*****************************/ 142 | { 143 | char *p; 144 | 145 | for( p = str; *p != '\0'; ++p ) { 146 | if( *p == '\r' ) *p = ' '; 147 | if( *p == '\n' ) *p = ' '; 148 | } 149 | } 150 | 151 | void SetProgState( unsigned run_conditions ) 152 | { 153 | ReadDbgRegs(); 154 | if( run_conditions & COND_THREAD_EXTRA ) { 155 | _SwitchOn( SW_THREAD_EXTRA_CHANGED ); 156 | } 157 | if( run_conditions & COND_THREAD ) { 158 | DbgRegs->tid = RemoteSetThread( 0 ); 159 | CheckForNewThreads( TRUE ); 160 | } 161 | if( run_conditions & COND_ALIASING ) CheckSegAlias(); 162 | } 163 | 164 | static void SetThreadStates( void ) 165 | { 166 | thread_state *thd; 167 | 168 | for( thd = HeadThd; thd != NULL; thd = thd->link ) { 169 | if( thd->tid == DbgRegs->tid ) { 170 | RemoteThawThread( thd->tid ); 171 | } else if( _IsOn( SW_EXECUTE_LONG ) && !SourceStep() ) { 172 | RemoteFreezeThread( thd->tid ); 173 | } else { 174 | switch( thd->state ) { 175 | case THD_THAW: 176 | RemoteThawThread( thd->tid ); 177 | break; 178 | case THD_FREEZE: 179 | RemoteFreezeThread( thd->tid ); 180 | break; 181 | } 182 | } 183 | } 184 | } 185 | 186 | static void AddMessageText( char *str ) 187 | /*************************************/ 188 | { 189 | unsigned len; 190 | 191 | if( MsgText == NULL ) { 192 | len = 0; 193 | } else { 194 | len = strlen( MsgText ); 195 | } 196 | MsgText = DbgRealloc( MsgText, len + strlen( str ) + 1 ); 197 | StrCopy( str, MsgText + len ); 198 | } 199 | 200 | bool SetMsgText( char *message, unsigned *conditions ) 201 | /****************************************************/ 202 | { 203 | char *equal,*comma1,*comma2; 204 | address addr,buff_addr; 205 | long buff_len,sym_len; 206 | long num_returns; 207 | cmd_list *cmds; 208 | 209 | if( memcmp( message, DEBUGGER_THREADID_COMMAND, 210 | sizeof( DEBUGGER_THREADID_COMMAND )-1 ) == 0 ) { 211 | message += sizeof( DEBUGGER_THREADID_COMMAND )-1; 212 | equal = strchr( message, '=' ); 213 | if( equal == NULL ) return( TRUE ); 214 | *equal = '\0'; 215 | CheckForNewThreads( FALSE ); 216 | NoCRLF( equal+1 ); 217 | NameThread( strtoul( message, NULL, 16 ), equal+1 ); 218 | return( FALSE ); 219 | } else if( memcmp( message, DEBUGGER_SETTRUE_COMMAND, 220 | sizeof( DEBUGGER_SETTRUE_COMMAND )-1 ) == 0 ) { 221 | unsigned old = NewCurrRadix( 16 ); 222 | NoCRLF( message ); 223 | if( DlgScanDataAddr( message + sizeof( DEBUGGER_SETTRUE_COMMAND )-1, &addr ) ) { 224 | ProgPoke( addr, "\x1", 1 ); 225 | } 226 | NewCurrRadix( old ); 227 | return( FALSE ); 228 | } else if( memcmp( message, DEBUGGER_EXECUTE_COMMAND, 229 | sizeof( DEBUGGER_EXECUTE_COMMAND )-1 ) == 0 ) { 230 | message += sizeof( DEBUGGER_EXECUTE_COMMAND )-1; 231 | NoCRLF( message ); 232 | if( InCall == 0 ) { 233 | cmds = AllocCmdList( "go/keep", strlen( "go/keep" ) ); 234 | PushCmdList( cmds ); 235 | TypeInpStack( INP_HOOK ); 236 | FreeCmdList( cmds ); 237 | } 238 | cmds = AllocCmdList( message, strlen( message ) ); 239 | PushCmdList( cmds ); 240 | TypeInpStack( INP_HOOK ); 241 | FreeCmdList( cmds ); 242 | *conditions |= COND_STOP; 243 | return( FALSE ); 244 | } else if( memcmp( message, DEBUGGER_MESSAGE_COMMAND, 245 | sizeof( DEBUGGER_MESSAGE_COMMAND )-1 ) == 0 ) { 246 | message += sizeof( DEBUGGER_MESSAGE_COMMAND )-1; 247 | NoCRLF( message ); 248 | AddMessageText( message ); 249 | return( FALSE ); 250 | } else if( memcmp( message, DEBUGGER_LOOKUP_COMMAND, 251 | sizeof( DEBUGGER_LOOKUP_COMMAND )-1 ) == 0 ) { 252 | message += sizeof( DEBUGGER_LOOKUP_COMMAND )-1; 253 | comma1 = strchr( message, ',' ); 254 | if( comma1 == NULL ) return( TRUE ); 255 | *comma1++ = '\0'; 256 | comma2 = strchr( comma1, ',' ); 257 | if( comma2 == NULL ) return( TRUE ); 258 | *comma2++ = '\0'; 259 | NoCRLF( comma2 ); 260 | if( !DlgScanDataAddr( message, &addr ) ) return( TRUE ); 261 | if( !DlgScanDataAddr( comma1, &buff_addr ) ) return( TRUE ); 262 | if( !DlgScanLong( comma2, &buff_len ) ) return( TRUE ); 263 | CnvNearestAddr( addr, TxtBuff, TXT_LEN ); 264 | sym_len = strlen( TxtBuff )+1; 265 | if( sym_len > buff_len ) { 266 | TxtBuff[buff_len-1] = '\0'; 267 | sym_len = buff_len; 268 | } 269 | ProgPoke( buff_addr, TxtBuff, sym_len ); 270 | return( FALSE ); 271 | } else if( memcmp( message, DEBUGGER_LOADMODULE_COMMAND, 272 | sizeof( DEBUGGER_LOADMODULE_COMMAND )-1 ) == 0 ) { 273 | message += sizeof( DEBUGGER_LOADMODULE_COMMAND )-1; 274 | comma1 = strchr( message, ',' ); 275 | if( comma1 == NULL ) 276 | return( TRUE ); 277 | *comma1++ = '\0'; 278 | NoCRLF( comma1 ); 279 | if( !DlgScanDataAddr( message, &addr ) ) 280 | return( TRUE ); 281 | SymUserModLoad( comma1, &addr ); 282 | return( FALSE ); 283 | } else if( memcmp( message, DEBUGGER_UNLOADMODULE_COMMAND, 284 | sizeof( DEBUGGER_UNLOADMODULE_COMMAND )-1 ) == 0 ) { 285 | message += sizeof( DEBUGGER_UNLOADMODULE_COMMAND )-1; 286 | NoCRLF( message ); 287 | SymUserModUnload( message ); 288 | return( FALSE ); 289 | } else if( memcmp( message, DEBUGGER_BREAKRETURN_COMMAND, 290 | sizeof( DEBUGGER_BREAKRETURN_COMMAND )-1 ) == 0 ) { 291 | message += sizeof( DEBUGGER_BREAKRETURN_COMMAND )-1; 292 | NoCRLF( message ); 293 | if( !DlgScanLong( message, &num_returns ) ) 294 | return( TRUE ); 295 | // TODO: do something with num_returns value 296 | return( FALSE ); 297 | } else { 298 | AddMessageText( message ); 299 | return( TRUE ); 300 | } 301 | } 302 | 303 | static bool RecordMsgText( unsigned *conditions ) 304 | { 305 | char *p,*p2; 306 | unsigned flags; 307 | bool rc = FALSE; 308 | 309 | do { 310 | flags = RemoteGetMsgText( TxtBuff, TXT_LEN ); 311 | p2 = TxtBuff; 312 | for( p=TxtBuff;*p != '\0' ;p++ ) { 313 | if( *p != '\r' && *p != '\n' ) { 314 | *p2++ = *p; 315 | } 316 | } 317 | if( MsgText != NULL ) { 318 | DUIDlgTxt( MsgText ); 319 | DbgFree( MsgText ); 320 | MsgText = NULL; 321 | } 322 | *p2++ = '\n'; 323 | *p2 = '\0'; 324 | rc = SetMsgText( TxtBuff, conditions ); 325 | } while( flags & MSG_MORE ); 326 | return( rc ); 327 | } 328 | 329 | 330 | typedef enum { 331 | ES_NORMAL, 332 | ES_STEP_ONE, 333 | ES_FORCE_BREAK 334 | } execute_state; 335 | 336 | /* enum MTRH_xxx: 337 | MTRH_STOP, 0 338 | MTRH_SIMULATE, 1 339 | MTRH_STEP, 2 340 | MTRH_STEPBREAK, 3 341 | MTRH_BREAK 4 342 | 343 | COND_STOPPERS = (COND_TRACE|COND_BREAK|COND_WATCH|COND_USER 344 | |COND_TERMINATE|COND_EXCEPTION|COND_STOP) 345 | 346 | */ 347 | 348 | unsigned ExecProg( bool tracing, bool do_flip, bool want_wps ) 349 | { 350 | bool have_brk_at_ip; 351 | bool act_wps; 352 | bool first_time; 353 | mad_trace_how how; 354 | execute_state es; 355 | unsigned conditions; 356 | unsigned run_conditions; 357 | bool already_stopping; 358 | bool force_stop; 359 | 360 | DebugMsg("WD, ExecProg( tracing=%u, do_flip=%u, want_wps=%u ): enter\r\n", tracing, do_flip, want_wps ); 361 | if( !want_wps ) ++InCall; 362 | tracing = TraceStart( tracing ); 363 | WriteDbgRegs(); 364 | first_time = TRUE; 365 | es = ES_NORMAL; 366 | run_conditions = 0; 367 | DUIPlayDead( TRUE ); 368 | for( ;; ) { 369 | switch( es ) { 370 | case ES_FORCE_BREAK: 371 | case ES_NORMAL: 372 | if( tracing ) { 373 | how = TraceHow( FALSE ); 374 | } else { 375 | _SwitchOn( SW_EXECUTE_LONG ); 376 | how = MTRH_BREAK; 377 | } 378 | break; 379 | case ES_STEP_ONE: 380 | how = TraceHow( TRUE ); 381 | break; 382 | } 383 | if( how == MTRH_STOP ) break; 384 | switch( how ) { 385 | case MTRH_BREAK: 386 | DbgUpdate( UP_CSIP_JUMPED ); 387 | _SwitchOn( SW_TOUCH_SCREEN_BUFF ); 388 | /* fall through */ 389 | case MTRH_SIMULATE: 390 | case MTRH_STEP: 391 | case MTRH_STEPBREAK: 392 | if( _IsOff( SW_TOUCH_SCREEN_BUFF ) ) break; 393 | /* fall through */ 394 | default: 395 | if( !(ScrnState & USR_SCRN_ACTIVE) && do_flip ) { 396 | DUIStop(); 397 | } 398 | _SwitchOff( SW_TOUCH_SCREEN_BUFF ); 399 | break; 400 | } 401 | if( first_time ) { 402 | /* got to be down here so that SW_EXECUTE_LONG is properly set */ 403 | SetThreadStates(); 404 | first_time = FALSE; 405 | } 406 | have_brk_at_ip = InsertBPs( (es == ES_FORCE_BREAK) ); 407 | act_wps = UpdateWPs(); 408 | if( how == MTRH_BREAK ) { 409 | if( have_brk_at_ip ) { 410 | DebugMsgC("WD, ExecProg(): how=MTRH_BREAK && break at CS:EIP - changing to ES_STEP_ONE\r\n" ); 411 | es = ES_STEP_ONE; 412 | RemoveBPs(); 413 | continue; /* back to top */ 414 | } 415 | if( act_wps && want_wps ) { 416 | InsertWPs(); 417 | } 418 | } 419 | DebugMsg("WD, ExecProg(): es=%X how=%X have_brk_at_ip=%u\r\n", es, how, have_brk_at_ip ); 420 | 421 | SetMemBefore( tracing ); 422 | switch( how ) { 423 | case MTRH_SIMULATE: 424 | if( TraceSimulate() ) { 425 | conditions = COND_TRACE; 426 | break; 427 | } 428 | /* fall through */ 429 | case MTRH_STEP: 430 | /* only updates stack/execution */ 431 | conditions = MakeProgRun( TRUE ); 432 | break; 433 | default: 434 | /* only updates stack/execution */ 435 | conditions = MakeProgRun( FALSE ); 436 | break; 437 | } 438 | if( _IsOn( SW_EXECUTE_LONG ) ) { 439 | if( ScrnState & DBG_SCRN_ACTIVE ) { 440 | _SwitchOn( SW_MIGHT_HAVE_LOST_DISPLAY ); 441 | } 442 | _SwitchOff( SW_EXECUTE_LONG ); 443 | } 444 | SetMemAfter( tracing ); 445 | run_conditions &= ~COND_WATCH; 446 | run_conditions |= conditions; 447 | 448 | DebugMsg("WD, ExecProg(): conditions=%X run_conditions=%X\r\n", conditions, run_conditions ); 449 | 450 | RemoveBPs(); 451 | if( conditions & COND_MESSAGE ) { 452 | if( !RecordMsgText( &conditions ) ) { 453 | conditions &= ~COND_MESSAGE; 454 | } 455 | } 456 | conditions = CheckBPs( conditions, run_conditions ); 457 | if( _IsOn( SW_BREAK_ON_DEBUG_MESSAGE ) && ( conditions & COND_MESSAGE ) ) { 458 | conditions |= COND_STOP; 459 | } 460 | if( how == MTRH_STEPBREAK && (conditions & COND_BREAK) && DbgTmpBrk.status.b.hit ) { 461 | conditions &= ~COND_BREAK; 462 | conditions |= COND_TRACE; 463 | } 464 | if( conditions & COND_LIBRARIES ) { 465 | already_stopping = ( conditions & COND_STOPPERS ) != 0; 466 | conditions &= ~COND_LIBRARIES; 467 | force_stop = FALSE; 468 | if( AddLibInfo( already_stopping, &force_stop ) ) { 469 | if( force_stop || DLLMatch() ) { 470 | conditions |= COND_STOP | COND_LIBRARIES; 471 | } 472 | } 473 | ReMapPoints( NULL ); 474 | } 475 | if( conditions & COND_SECTIONS ) { 476 | SectTblRead( DbgRegs ); 477 | InvalidateTblCache(); 478 | } 479 | if( (es == ES_STEP_ONE) && (conditions & COND_TRACE) ) { 480 | conditions &= ~COND_TRACE; 481 | } 482 | if( tracing ) { 483 | DebugMsgC("WD, ExecProg(): calling TraceCheck()\r\n" ); 484 | conditions = TraceCheck( conditions ); 485 | DebugMsg("WD, ExecProg(): conditions=%X\r\n", conditions ); 486 | } 487 | if( !(conditions & COND_STOPPERS) && TBreak() ) { 488 | conditions |= COND_USER; 489 | break; 490 | } 491 | if( conditions & COND_STOPPERS ) break; 492 | 493 | DebugMsg("WD, ExecProg(): will continue, conditions=%X\r\n", conditions ); 494 | 495 | switch( es ) { 496 | case ES_STEP_ONE: 497 | es = ES_FORCE_BREAK; 498 | break; 499 | case ES_FORCE_BREAK: 500 | es = ES_NORMAL; 501 | break; 502 | } 503 | if( (run_conditions & COND_WATCH) && es == ES_NORMAL ) { 504 | /* 505 | We got a spurious watch point indication. Make the 506 | next instruction single step since we might be 507 | dealing with a control flow opcode on a machine without 508 | a T-bit (e.g. Alpha). 509 | */ 510 | es = ES_STEP_ONE; 511 | } 512 | } 513 | TraceStop( tracing ); 514 | DUIPlayDead( FALSE ); 515 | SetProgState( run_conditions ); 516 | _SwitchOff( SW_KNOW_EMULATOR ); 517 | if( !want_wps ) --InCall; 518 | DebugMsgC("WD, ExecProg(): exit\r\n" ); 519 | return( conditions ); 520 | } 521 | 522 | 523 | static void DisplayMsgText( void ) 524 | /********************************/ 525 | { 526 | if( MsgText != NULL ) { 527 | DUIDlgTxt( MsgText ); 528 | DbgFree( MsgText ); 529 | MsgText = NULL; 530 | } 531 | } 532 | 533 | bool ReportTrap( unsigned conditions, bool stack_cmds ) 534 | { 535 | bool cmds_pushed; 536 | char *p; 537 | 538 | #if 0 /* japheth: no annoying MessageBox()! */ 539 | if( conditions & COND_EXCEPTION ) { 540 | RecordMsgText( &conditions ); // get the 'access violation, etc' message 541 | p = StrCopy( LIT( Task_Exception ), TxtBuff ); 542 | if( MsgText != NULL ) StrCopy( MsgText, p ); 543 | MsgText = DbgRealloc( MsgText, strlen( TxtBuff ) + 1 ); 544 | StrCopy( TxtBuff, MsgText ); 545 | DUIMsgBox( MsgText ); 546 | } 547 | #endif 548 | if( conditions & (COND_EXCEPTION|COND_TERMINATE) ) { 549 | Ring(); 550 | } 551 | DisplayMsgText(); 552 | if( conditions & COND_USER ) { 553 | DUIInfoBox( LIT( User_Interupt ) ); 554 | PurgeInpStack(); 555 | RecordAsynchEvent(); 556 | } else if( conditions & COND_TERMINATE ) { 557 | DUIInfoBox( LIT( Task_Completed ) ); 558 | _SwitchOff( SW_HAVE_TASK ); 559 | } else if( conditions & COND_LIBRARIES ) { 560 | Format( TxtBuff, "%s '%s'", LIT( Break_on_DLL_Load ), GetLastImageName() ); 561 | DUIInfoBox( TxtBuff ); 562 | } else if( conditions & COND_EXCEPTION ) { /* japheth: simple status text for exceptions */ 563 | RecordMsgText( &conditions ); // get the 'access violation, etc' message 564 | p = StrCopy( LIT( Task_Exception ), TxtBuff ); 565 | if( MsgText != NULL ) StrCopy( MsgText, p ); 566 | DUIStatusText( TxtBuff ); 567 | } else { 568 | DUIStatusText( LIT( Empty ) ); 569 | } 570 | cmds_pushed = DispBPMsg( stack_cmds ); 571 | DbgUpdate( UP_MEM_CHANGE | UP_CSIP_CHANGE | UP_REG_CHANGE | 572 | UP_CODE_EXECUTED | UP_THREAD_STATE ); 573 | return( cmds_pushed ); 574 | } 575 | 576 | 577 | unsigned Execute( bool tracing, bool do_flip ) 578 | { 579 | unsigned conditions; 580 | bool stack_cmds; 581 | static unsigned executing = 0; 582 | 583 | if( !CheckStackPos() ) return( COND_USER ); 584 | if( !AdvMachState( ACTION_EXECUTE ) ) return( COND_USER ); 585 | 586 | if( executing == 0 ) { 587 | ++executing; 588 | HookNotify( TRUE, HOOK_EXEC_START ); 589 | --executing; 590 | } 591 | 592 | /* get rid of useless pending input information */ 593 | for( ;; ) { 594 | if( CurrToken != T_LINE_SEPARATOR ) break; 595 | if( InpStack == NULL ) break; 596 | if( InpStack->type & (INP_HOLD|INP_STOP_PURGE) ) break; 597 | if( InpStack->rtn( InpStack->handle, INP_RTN_EOL ) ) continue; 598 | PopInpStack(); 599 | } 600 | _SwitchOff( SW_TRAP_CMDS_PUSHED ); 601 | conditions = ExecProg( tracing, do_flip, TRUE ); 602 | SetCodeDot( GetRegIP() ); 603 | stack_cmds = TRUE; 604 | if( tracing && (conditions & COND_BREAK) ) stack_cmds = FALSE; 605 | if( ReportTrap( conditions, stack_cmds ) ) { 606 | _SwitchOn( SW_TRAP_CMDS_PUSHED ); 607 | } 608 | if( executing == 0 ) { 609 | ++executing; 610 | HookNotify( TRUE, HOOK_EXEC_END ); 611 | --executing; 612 | } 613 | if( conditions & COND_TERMINATE ) { 614 | HookNotify( TRUE, HOOK_PROG_END ); 615 | } 616 | return( conditions ); 617 | } 618 | 619 | unsigned Go( bool do_flip ) 620 | { 621 | char *p; 622 | unsigned conditions; 623 | 624 | p = StrCopy( GetCmdName( CMD_GO ), TxtBuff ); 625 | if( UserTmpBrk.status.b.active ) { 626 | p = Format( p, " %A", UserTmpBrk.loc.addr ); 627 | RecordEvent( TxtBuff ); 628 | } else { 629 | RecordGo( TxtBuff ); 630 | } 631 | conditions = Execute( FALSE, do_flip ); 632 | CheckEventRecorded(); 633 | return( conditions ); 634 | } 635 | -------------------------------------------------------------------------------- /wv_src/dbgmain.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Open Watcom Project 4 | * 5 | * Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved. 6 | * 7 | * ======================================================================== 8 | * 9 | * This file contains Original Code and/or Modifications of Original 10 | * Code as defined in and that are subject to the Sybase Open Watcom 11 | * Public License version 1.0 (the 'License'). You may not use this file 12 | * except in compliance with the License. BY USING THIS FILE YOU AGREE TO 13 | * ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is 14 | * provided with the Original Code and Modifications, and is also 15 | * available at www.sybase.com/developer/opensource. 16 | * 17 | * The Original Code and all software distributed under the License are 18 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 19 | * EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM 20 | * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR 22 | * NON-INFRINGEMENT. Please see the License for the specific language 23 | * governing rights and limitations under the License. 24 | * 25 | * ======================================================================== 26 | * 27 | * Description: Debugger mainline. 28 | * 29 | ****************************************************************************/ 30 | 31 | 32 | #include "dbgdata.h" 33 | #include "dbgerr.h" 34 | #include "dbginfo.h" 35 | #include "dbglit.h" 36 | #include "spawn.h" 37 | #include "dui.h" 38 | #include 39 | #include "trpcore.h" 40 | #include "trpcapb.h" 41 | 42 | 43 | // This list of extern functions is in alphabetic order.: 44 | extern cmd_list *AllocCmdList( char *,unsigned int ); 45 | extern void ClearInpStack( input_type ); 46 | extern void FingClose( void ); 47 | extern void FingFront( void ); 48 | extern void FingOpen( void ); 49 | extern void FiniAboutMessage( void ); 50 | extern void FiniBrowse( void ); 51 | extern void FiniCall( void ); 52 | extern void FiniCmd( void ); 53 | extern void FiniDLLList( void ); 54 | extern void FiniDbgInfo( void ); 55 | extern void FiniFont( void ); 56 | extern void FiniGadget( void ); 57 | extern void FiniHook( void ); 58 | extern void FiniIOWindow( void ); 59 | extern void FiniLiterals( void ); 60 | extern void FiniLocalInfo( void ); 61 | extern void FiniLook( void ); 62 | extern void FiniMADInfo( void ); 63 | extern void FiniMachState( void ); 64 | extern void FiniMacros( void ); 65 | extern void FiniMemWindow( void ); 66 | extern void FiniMenus( void ); 67 | extern void FiniPaint( void ); 68 | extern void FiniScan( void ); 69 | extern void FiniScreen( void ); 70 | extern void FiniSource( void ); 71 | extern void FiniToolBar( void ); 72 | extern void FiniTrace( void ); 73 | extern void FiniTrap( void ); 74 | extern char *Format( char *,char *,... ); 75 | extern void FreeCmdList( cmd_list * ); 76 | extern void FreezeInpStack( void ); 77 | extern char *GetCmdEntry( char *tab, int index, char *buff ); 78 | extern trap_shandle GetSuppId( char * ); 79 | extern void GrabHandlers( void ); 80 | extern void InitAboutMessage( void ); 81 | extern void InitBPs( void ); 82 | extern void InitBrowse( void ); 83 | extern bool InitCmd( void ); 84 | extern void InitDLLList( void ); 85 | extern void InitDbgInfo( void ); 86 | extern void InitFont( void ); 87 | extern void InitGadget( void ); 88 | extern void InitHelp( void ); 89 | extern void InitHook( void ); 90 | extern void InitIOWindow( void ); 91 | extern void InitLiterals( void ); 92 | extern void InitLocalInfo( void ); 93 | extern void InitLook( void ); 94 | extern void InitMADInfo( void ); 95 | extern void InitMachState( void ); 96 | extern void InitMemWindow( void ); 97 | extern void InitMenus( void ); 98 | extern void InitPaint( void ); 99 | extern void InitScan( void ); 100 | extern void InitScreen( void ); 101 | extern void InitSource( void ); 102 | extern void InitToolBar( void ); 103 | extern void InitTrap( char * ); 104 | extern void LangSetFini( void ); 105 | extern bool LangSetInit( void ); 106 | extern void LoadProg( void ); 107 | extern void LogFini( void ); 108 | extern void LogInit( void ); 109 | extern void PathFini( void ); 110 | extern void PathInit( void ); 111 | extern void PointFini( void ); 112 | extern void PopInpStack( void ); 113 | extern void PredefFini( void ); 114 | extern void PredefInit( void ); 115 | extern void ProcAccel( void ); 116 | extern void ProcBreak( void ); 117 | extern void ProcCall( void ); 118 | extern void ProcCapture( void ); 119 | extern void ProcCmd( void ); 120 | extern void ProcDisplay( void ); 121 | extern void ProcDo( void ); 122 | extern void ProcError( void ); 123 | extern void ProcExamine( void ); 124 | extern void ProcFlip( void ); 125 | extern void ProcFont( void ); 126 | extern void ProcGo( void ); 127 | extern void ProcHelp( void ); 128 | extern void ProcHook( void ); 129 | extern void ProcIf( void ); 130 | extern void ProcInput( void ); 131 | extern void ProcInvoke( void ); 132 | extern void ProcLog( void ); 133 | extern void ProcNew( void ); 134 | extern void ProcPaint( void ); 135 | extern void ProcPrint( void ); 136 | extern void ProcQuit( void ); 137 | extern void ProcRegister( void ); 138 | extern void ProcRemark( void ); 139 | extern void ProcSet( void ); 140 | extern void ProcShow( void ); 141 | extern void ProcSystem( void ); 142 | extern void ProcThread( void ); 143 | extern void ProcTrace( void ); 144 | extern void ProcView( void ); 145 | extern void ProcWhile( void ); 146 | extern void ProcWindow( void ); 147 | extern void ProfileInvoke( char * ); 148 | extern bool PurgeInpStack( void ); 149 | extern void PushCmdList( cmd_list *cmds ); 150 | extern void RecordFini( void ); 151 | extern void RecordInit( void ); 152 | extern void ReleaseProgOvlay( bool ); 153 | extern char *ReScan( char * ); 154 | extern void RestoreHandlers( void ); 155 | extern void Ring( void ); 156 | extern void Scan( void ); 157 | extern unsigned int ScanCmd( char * ); 158 | extern unsigned int ScanLen( void ); 159 | extern char *ScanPos( void ); 160 | extern void StartupErr( char * ); 161 | extern void Suicide( void ); 162 | extern void SupportFini( void ); 163 | extern void SymCompFini( void ); 164 | extern void SysFileInit( void ); 165 | extern bool TBreak( void ); 166 | extern void VarDisplayFini( void ); 167 | extern void VarDisplayInit( void ); 168 | extern void WndDlgFini( void ); 169 | extern void WndMemInit( void ); 170 | 171 | extern char *InitCmdList; 172 | extern char *TrpFile; 173 | extern char *CmdStart; 174 | extern char *NameBuff; 175 | extern char *TxtBuff; 176 | extern tokens CurrToken; 177 | extern unsigned char DefRadix; 178 | extern unsigned char CurrRadix; 179 | extern debug_level DbgLevel; 180 | extern debug_level ActiveWindowLevel; 181 | extern char DbgBuffers[]; 182 | extern int ScanSavePtr; 183 | extern address NilAddr; 184 | extern char *InvokeFile; 185 | 186 | OVL_EXTERN void ProcNil( void ); 187 | 188 | static char szHdpmi[] = "HDPMI"; 189 | 190 | /* Internal - to be moved */ 191 | int CapabilitiesGet8ByteBreakpointSupport( void ); 192 | int CapabilitiesGetExactBreakpointSupport( void ); 193 | int CapabilitiesSet8ByteBreakpointSupport( bool status ); 194 | int CapabilitiesSetExactBreakpointSupport( bool status ); 195 | 196 | #define pick( a, b, c ) extern void b( void ); 197 | #include "dbgcmd.h" 198 | 199 | static char CmdNameTab[] = { 200 | #define pick( a, b, c ) c 201 | #include "dbgcmd.h" 202 | }; 203 | 204 | 205 | 206 | static void ( * const CmdJmpTab[] )( void ) = { 207 | &ProcNil, 208 | #define pick( a, b, c ) &b, 209 | #include "dbgcmd.h" 210 | }; 211 | 212 | 213 | char *GetCmdName( int index ) 214 | { 215 | static char buff[ MAX_CMD_NAME+1 ]; 216 | GetCmdEntry( CmdNameTab, index, buff ); 217 | return( buff ); 218 | } 219 | 220 | 221 | /* 222 | * DebugInit -- mainline for initialization 223 | */ 224 | 225 | void DebugInit( void ) 226 | { 227 | _SwitchOn( SW_ERROR_STARTUP ); 228 | _SwitchOn( SW_CHECK_SOURCE_EXISTS ); 229 | SET_NIL_ADDR( NilAddr ); 230 | TxtBuff = &DbgBuffers[0]; 231 | NameBuff = &DbgBuffers[TXT_LEN+1]; 232 | CurrRadix = DefRadix = 10; 233 | DbgLevel = MIX; 234 | ActiveWindowLevel = MIX; 235 | _SwitchOn( SW_BELL ); 236 | _SwitchOn( SW_FLIP ); 237 | _SwitchOn( SW_RECURSE_CHECK ); 238 | _SwitchOff( SW_ADDING_SYMFILE ); 239 | _SwitchOff( SW_TASK_RUNNING ); 240 | RecordInit(); 241 | LogInit(); 242 | InitMADInfo(); 243 | InitMachState(); 244 | PathInit(); 245 | InitDbgInfo(); 246 | InitTrap( TrpFile ); 247 | if( !LangSetInit() ) { 248 | FiniTrap(); 249 | StartupErr( LIT( STARTUP_Loading_PRS ) ); 250 | } 251 | if( !InitCmd() ) { 252 | FiniTrap(); 253 | StartupErr( LIT( ERR_NO_MEMORY ) ); 254 | } 255 | InitScan(); 256 | InitLook(); 257 | InitBPs(); 258 | InitSource(); 259 | InitDLLList(); 260 | InitScreen(); 261 | DUIInit(); 262 | InitHook(); 263 | VarDisplayInit(); 264 | } 265 | 266 | /* 267 | * ProcNil -- process NIL command 268 | */ 269 | 270 | OVL_EXTERN void ProcNil( void ) 271 | { 272 | if( ScanLen() == 0 ) Scan(); 273 | Error( ERR_NONE, LIT( ERR_BAD_COMMAND ), ScanPos(), ScanLen() ); 274 | } 275 | 276 | 277 | /* 278 | * 279 | */ 280 | 281 | void ReportTask( task_status task, unsigned code ) 282 | { 283 | switch( task ) { 284 | case TASK_NEW: 285 | _SwitchOn( SW_HAVE_TASK ); 286 | DUIStatusText( LIT( New_Task ) ); 287 | DUIDlgTxt( LIT( New_Task ) ); 288 | break; 289 | case TASK_NOT_LOADED: 290 | _SwitchOff( SW_HAVE_TASK ); 291 | Format( TxtBuff, LIT( Task_Not_Loaded ), code ); 292 | DUIMsgBox( TxtBuff ); 293 | Ring(); Ring(); 294 | break; 295 | case TASK_NONE: 296 | _SwitchOff( SW_HAVE_TASK ); 297 | DUIStatusText( LIT( No_Task ) ); 298 | DUIDlgTxt( LIT( No_Task ) ); 299 | break; 300 | } 301 | } 302 | 303 | 304 | /* 305 | * ChkBreak -- report an error if there is a pending user interrupt 306 | */ 307 | 308 | void ChkBreak( void ) 309 | { 310 | if( TBreak() ) Error( ERR_NONE, LIT( ERR_DBG_INTERRUPT ) ); 311 | } 312 | 313 | 314 | /* 315 | * ProcACmd -- process a command 316 | */ 317 | 318 | 319 | void ProcACmd( void ) 320 | { 321 | unsigned cmd; 322 | 323 | ChkBreak(); 324 | CmdStart = ScanPos(); 325 | switch( CurrToken ) { 326 | case T_CMD_SEPARATOR: 327 | Scan(); 328 | break; 329 | case T_DIV: 330 | Scan(); 331 | ProcDo(); 332 | break; 333 | case T_LT: 334 | Scan(); 335 | ProcInvoke(); 336 | break; 337 | case T_GT: 338 | Scan(); 339 | ProcLog(); 340 | break; 341 | case T_QUESTION: 342 | Scan(); 343 | ProcPrint(); 344 | break; 345 | case T_MUL: 346 | Scan(); 347 | ProcRemark(); 348 | break; 349 | case T_EXCLAMATION: 350 | Scan(); 351 | ProcSystem(); 352 | break; 353 | case T_TILDE: 354 | Scan(); 355 | ProcThread(); 356 | break; 357 | default: 358 | cmd = ScanCmd( CmdNameTab ); 359 | if( cmd == 0 && _IsOn( SW_IMPLICIT ) ) { 360 | ProcInvoke(); 361 | } else { 362 | (*CmdJmpTab[ cmd ])(); 363 | } 364 | break; 365 | } 366 | ScanSavePtr = 0; /* clean up previous ScanSave locations */ 367 | } 368 | 369 | 370 | OVL_EXTERN void Profile( void ) 371 | { 372 | if( InvokeFile != NULL ) { 373 | ProfileInvoke( InvokeFile ); 374 | _Free( InvokeFile ); 375 | InvokeFile = NULL; 376 | ProcInput(); 377 | } 378 | } 379 | 380 | static void PushInitCmdList( void ) 381 | { 382 | cmd_list *cmds; 383 | 384 | if( InitCmdList != NULL ) { 385 | cmds = AllocCmdList( InitCmdList, strlen( InitCmdList ) ); 386 | _Free( InitCmdList ); 387 | InitCmdList = NULL; 388 | PushCmdList( cmds ); 389 | FreeCmdList( cmds ); 390 | } 391 | } 392 | 393 | /* 394 | * DebugMain -- mainline for initialization 395 | */ 396 | 397 | void DisableHDPMI( void ); 398 | /* japheth: disable hdpmi; the host instance is to be used exclusively by WD */ 399 | #pragma aux DisableHDPMI = \ 400 | "push es" \ 401 | "pushad" \ 402 | "mov esi, offset szHdpmi" \ 403 | "mov ax, 168ah" \ 404 | "int 2Fh" \ 405 | "cmp al,0" \ 406 | "jnz nohdpmi" \ 407 | "push es" \ 408 | "push edi" \ 409 | "mov ax, 4" \ 410 | "call fword ptr [esp]" \ 411 | "add esp,8" \ 412 | "nohdpmi:" \ 413 | "popad" \ 414 | "pop es" \ 415 | parm [] \ 416 | modify exact []; 417 | 418 | void DebugMain( void ) 419 | { 420 | bool save; 421 | 422 | DisableHDPMI(); 423 | GrabHandlers(); 424 | SysFileInit(); 425 | WndMemInit(); 426 | InitLiterals(); 427 | InitLocalInfo(); 428 | ProcCmd(); 429 | 430 | Spawn( &DebugInit ); 431 | FingOpen(); 432 | DUIFreshAll(); 433 | 434 | LoadProg(); 435 | 436 | save = DUIStopRefresh( TRUE ); 437 | FreezeInpStack(); 438 | _SwitchOn( SW_RUNNING_PROFILE ); 439 | Spawn( &Profile ); /* run profile command file */ 440 | _SwitchOff( SW_RUNNING_PROFILE ); 441 | PushInitCmdList(); 442 | DUIStopRefresh( save ); 443 | FingClose(); 444 | DUIShow(); 445 | } 446 | 447 | 448 | 449 | /* 450 | * DebugExit -- end the debugger (Kill! Crush! Destroy!) 451 | */ 452 | 453 | void DebugExit( void ) 454 | { 455 | if( DUIClose() ) { 456 | Suicide(); 457 | } 458 | } 459 | 460 | 461 | void DebugFini( void ) 462 | { 463 | PointFini(); 464 | #if !( defined( __GUI__ ) && defined( __OS2__ ) ) 465 | ReleaseProgOvlay( TRUE ); // see dlgfile.c 466 | #endif 467 | VarDisplayFini(); 468 | FiniHook(); 469 | FiniCmd(); 470 | LogFini(); 471 | while( !PurgeInpStack() ) { 472 | ClearInpStack( INP_STOP_PURGE ); 473 | } 474 | LangSetFini(); 475 | SupportFini(); 476 | FiniTrap(); 477 | RecordFini(); 478 | FiniMachState(); 479 | FiniDbgInfo(); 480 | FiniScan(); 481 | FiniLook(); 482 | FiniDLLList(); 483 | FiniSource(); 484 | FiniCall(); 485 | PathFini(); 486 | DUIFini(); 487 | SymCompFini(); 488 | FiniScreen(); 489 | FiniMADInfo(); 490 | FiniTrace(); 491 | RestoreHandlers(); 492 | _Free( TrpFile ); 493 | FiniLiterals(); 494 | FiniLocalInfo(); 495 | } 496 | 497 | /* 498 | * Find if the current trap file supports the capabilities service 499 | */ 500 | trap_shandle SuppCapabilitiesId = 0; 501 | 502 | bool InitCapabilities( void ) 503 | { 504 | /* Always reset in case of trap switch */ 505 | Supports8ByteBreakpoints = 0; 506 | SupportsExactBreakpoints = 0; 507 | 508 | SuppCapabilitiesId = GetSuppId( CAPABILITIES_SUPP_NAME ); 509 | if( SuppCapabilitiesId == 0 ) 510 | return( FALSE ); 511 | 512 | CapabilitiesGet8ByteBreakpointSupport(); 513 | CapabilitiesGetExactBreakpointSupport(); 514 | 515 | if( Supports8ByteBreakpoints ) 516 | CapabilitiesSet8ByteBreakpointSupport( TRUE ); 517 | 518 | if( SupportsExactBreakpoints && _IsOn( SW_BREAK_ON_WRITE ) ) 519 | CapabilitiesSetExactBreakpointSupport( TRUE ); 520 | 521 | return( TRUE ); 522 | } 523 | 524 | #define SUPP_CAPABILITIES_SERVICE( in, request ) \ 525 | in.supp.core_req = REQ_PERFORM_SUPPLEMENTARY_SERVICE; \ 526 | in.supp.id = SuppCapabilitiesId; \ 527 | in.req = request; 528 | 529 | int CapabilitiesGet8ByteBreakpointSupport() 530 | { 531 | mx_entry in[1]; 532 | mx_entry out[1]; 533 | capabilities_get_8b_bp_req acc; 534 | capabilities_get_8b_bp_ret ret; 535 | 536 | if( SuppCapabilitiesId == 0 ) 537 | return( -1 ); 538 | 539 | SUPP_CAPABILITIES_SERVICE( acc, REQ_CAPABILITIES_GET_8B_BP ); 540 | in[0].ptr = &acc; 541 | in[0].len = sizeof( acc ); 542 | out[0].ptr = &ret; 543 | out[0].len = sizeof( ret ); 544 | 545 | TrapAccess( 1, &in, 1, &out ); 546 | if( ret.err != 0 ) { 547 | return( FALSE ); 548 | } else { 549 | Supports8ByteBreakpoints = 1; /* The trap supports 8 byte breakpoints */ 550 | return( TRUE ); 551 | } 552 | } 553 | 554 | int CapabilitiesSet8ByteBreakpointSupport( bool status ) 555 | { 556 | mx_entry in[1]; 557 | mx_entry out[1]; 558 | capabilities_set_8b_bp_req acc; 559 | capabilities_set_8b_bp_ret ret; 560 | 561 | if( SuppCapabilitiesId == 0 ) 562 | return( -1 ); 563 | 564 | SUPP_CAPABILITIES_SERVICE( acc, REQ_CAPABILITIES_SET_8B_BP ); 565 | acc.status = status ? TRUE : FALSE; 566 | 567 | in[0].ptr = &acc; 568 | in[0].len = sizeof( acc ); 569 | out[0].ptr = &ret; 570 | out[0].len = sizeof( ret ); 571 | 572 | TrapAccess( 1, &in, 1, &out ); 573 | if( ret.err != 0 ) { 574 | return( FALSE ); 575 | } else { 576 | Supports8ByteBreakpoints = ret.status ? TRUE : FALSE; 577 | return( TRUE ); 578 | } 579 | } 580 | 581 | int CapabilitiesGetExactBreakpointSupport( void ) 582 | { 583 | mx_entry in[1]; 584 | mx_entry out[1]; 585 | capabilities_get_8b_bp_req acc; 586 | capabilities_get_8b_bp_ret ret; 587 | 588 | 589 | if( SuppCapabilitiesId == 0 ) 590 | return( -1 ); 591 | 592 | SUPP_CAPABILITIES_SERVICE( acc, REQ_CAPABILITIES_GET_EXACT_BP ); 593 | in[0].ptr = &acc; 594 | in[0].len = sizeof( acc ); 595 | out[0].ptr = &ret; 596 | out[0].len = sizeof( ret ); 597 | 598 | TrapAccess( 1, &in, 1, &out ); 599 | if( ret.err != 0 ) { 600 | return( FALSE ); 601 | } else { 602 | /* The trap may support it, but it is not possible currently */ 603 | SupportsExactBreakpoints = ret.status ? TRUE : FALSE; 604 | return( TRUE ); 605 | } 606 | } 607 | 608 | int CapabilitiesSetExactBreakpointSupport( bool status ) 609 | { 610 | mx_entry in[1]; 611 | mx_entry out[1]; 612 | capabilities_set_8b_bp_req acc; 613 | capabilities_set_8b_bp_ret ret; 614 | 615 | if( SuppCapabilitiesId == 0 ) 616 | return( -1 ); 617 | 618 | SUPP_CAPABILITIES_SERVICE( acc, REQ_CAPABILITIES_SET_EXACT_BP ); 619 | acc.status = status ? TRUE : FALSE; 620 | 621 | in[0].ptr = &acc; 622 | in[0].len = sizeof( acc ); 623 | out[0].ptr = &ret; 624 | out[0].len = sizeof( ret ); 625 | 626 | TrapAccess( 1, &in, 1, &out ); 627 | if( ret.err != 0 ) { 628 | return( FALSE ); 629 | } else { 630 | _SwitchSet( SW_BREAK_ON_WRITE, ret.status ? TRUE : FALSE ); 631 | return( TRUE ); 632 | } 633 | } 634 | -------------------------------------------------------------------------------- /wv_src/dbgtrace.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Open Watcom Project 4 | * 5 | * Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved. 6 | * 7 | * ======================================================================== 8 | * 9 | * This file contains Original Code and/or Modifications of Original 10 | * Code as defined in and that are subject to the Sybase Open Watcom 11 | * Public License version 1.0 (the 'License'). You may not use this file 12 | * except in compliance with the License. BY USING THIS FILE YOU AGREE TO 13 | * ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is 14 | * provided with the Original Code and Modifications, and is also 15 | * available at www.sybase.com/developer/opensource. 16 | * 17 | * The Original Code and all software distributed under the License are 18 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 19 | * EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM 20 | * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR 22 | * NON-INFRINGEMENT. Please see the License for the specific language 23 | * governing rights and limitations under the License. 24 | * 25 | * ======================================================================== 26 | * 27 | * Description: User program step and trace support. 28 | * 29 | ****************************************************************************/ 30 | 31 | 32 | #include "dbgdefn.h" 33 | #include "dbgtoken.h" 34 | #include "dbgreg.h" 35 | #include "dbgerr.h" 36 | #include "dbgtoggl.h" 37 | #include "dbginfo.h" 38 | #include "dbgbreak.h" 39 | #include "dbglit.h" 40 | #include "dbginp.h" 41 | #include "dbgrep.h" 42 | #include "dbgmem.h" 43 | #include "trpcore.h" 44 | #include "mad.h" 45 | 46 | 47 | enum { 48 | TS_NONE, 49 | TS_ACTIVE, 50 | TS_POSTPONED, 51 | TS_REACTIVATED 52 | }; 53 | 54 | #pragma pack( push, 8 ) /* make sure everything's aligned for speed */ 55 | typedef struct { 56 | address brkpt; /* address of DbgTmpBrk */ 57 | address watch_stack; /* stack pointer at call */ 58 | brk_status userstat; /* initial state of UserTmpBrk */ 59 | debug_level req_level; /* trace level requested */ 60 | debug_level cur_level; /* trace level we are in */ 61 | address oldaddr; /* address where this trace started */ 62 | int type; /* trace type */ 63 | address savecode; /* old Code{Loc/Dot} */ 64 | address saveaddr; /* original CS:IP */ 65 | unsigned state : 3; /* is there a trace active */ 66 | unsigned stop_on_call : 1;/* we've returned -- stop on call */ 67 | unsigned stop_now : 1; /* did we execute a call since ^ set ?*/ 68 | unsigned trace_out : 1; /* want to trace out of a call */ 69 | unsigned doing_call : 1; /* are we doing a call instruction? */ 70 | unsigned in_thunk : 1; /* inside a THUNK routine */ 71 | unsigned in_dll_thunk : 1; /* inside a DLL THUNK routine */ 72 | unsigned give_it_up : 1; /* inside a DLL THUNK routine */ 73 | unsigned unwinding : 1; /* unwinding from a recursive breakpoint ? */ 74 | dtid_t etid; /* thread id that we're tracing */ 75 | address curraddr; /* current address being traced */ 76 | mad_disasm_control prev_control; /* control information for prev ins */ 77 | mad_disasm_control curr_control; /* control information for curr ins */ 78 | mad_trace_how how; /* how to trace this instruction */ 79 | unsigned ddsize; /* size of a mad_disasm_data */ 80 | unsigned tdsize; /* size of a mad_trace_data */ 81 | mad_disasm_data *dd; /* disasm info for curr instr */ 82 | mad_trace_data *td; /* trace info for curr instr */ 83 | } trace_state; 84 | #pragma pack( pop ) 85 | 86 | #define KEEPGOING 0 87 | #define STOP 1 88 | #define PROCCMD 2 89 | 90 | static trace_state TraceState; 91 | 92 | extern brkp UserTmpBrk; 93 | extern brkp DbgTmpBrk; 94 | extern debug_level DbgLevel; 95 | extern debug_level ActiveWindowLevel; 96 | extern machine_state *DbgRegs; 97 | extern tokens CurrToken; 98 | extern char Opcode; 99 | extern char SecondByte; 100 | extern char *TxtBuff; 101 | extern unsigned OvlSize; 102 | extern system_config SysConfig; 103 | extern address NilAddr; 104 | 105 | 106 | extern void FDoneSource( void * ); 107 | extern void *OpenSrcFile( cue_handle *ch ); 108 | extern cue_file_id CueFileId( cue_handle * ); 109 | extern unsigned CueFile( cue_handle *ch, char *file, unsigned max ); 110 | extern unsigned long CueLine( cue_handle *ch ); 111 | extern void OptMemAddr( memory_expr, address * ); 112 | extern int_16 GetDataWord( void ); 113 | extern long GetDataLong( void ); 114 | extern void Scan( void ); 115 | extern unsigned int ScanCmd( char * ); 116 | extern void ReqEOC( void ); 117 | extern int AddrComp( address, address ); 118 | extern unsigned Execute( bool, bool ); 119 | extern void GetCurrOpcode( void ); 120 | extern void Warn( char * ); 121 | extern char *GetCmdEntry( char *, int, char * ); 122 | extern char *GetCmdName( int ); 123 | extern void ConfigLine( char * ); 124 | extern bool SimIntr( char, unsigned int ); 125 | extern void WndPmtNormal( void ); 126 | extern address GetRegIP( void ); 127 | extern void SetRegIP( address ); 128 | extern address GetRegSP( void ); 129 | extern bool RemoteOvlTransAddr( address * ); 130 | extern bool TransOvlRetAddr( address *, unsigned int ); 131 | extern void PushInpStack( void *, bool (*)(), bool ); 132 | extern char *ReScan( char * ); 133 | extern void TypeInpStack( input_type ); 134 | extern void SetCodeLoc( address ); 135 | extern void SetCodeDot( address ); 136 | extern address GetCodeDot( void ); 137 | extern void AddrFloat( address * ); 138 | extern void AddrFix( address * ); 139 | extern void AddrSection( address *, unsigned ); 140 | extern bool IsSupportRoutine( sym_handle * ); 141 | extern char *Format( char *buff, char *fmt, ... ); 142 | extern void RecordEvent( char *p ); 143 | extern void CheckEventRecorded( void ); 144 | extern dtid_t RemoteSetThread( dtid_t ); 145 | extern void ReadDbgRegs( void ); 146 | extern void WriteDbgRegs( void ); 147 | extern void ReportMADFailure( mad_status ); 148 | 149 | static char LevelTab[] = { 150 | #define pick( a,b ) b 151 | #include "dbglevel.h" 152 | }; 153 | 154 | static char TraceTab2[] = { 155 | #define pick( a,b ) b 156 | #include "dbgtrace.h" 157 | }; 158 | 159 | #if 0 160 | #define DBGMSG 161 | #include 162 | extern void __stdcall OutputDebugStringA( char * ); 163 | char dbgbuff[256]; 164 | #define DebugMsg( x, ... ) sprintf( dbgbuff, x, __VA_ARGS__ ); OutputDebugStringA( dbgbuff ) 165 | #define DebugMsgC( x ) OutputDebugStringA( x ) 166 | #else 167 | #define DebugMsg( x, ... ) 168 | #define DebugMsgC( x ) 169 | #endif 170 | 171 | void ResizeTraceData( void ) 172 | { 173 | void *new; 174 | unsigned size; 175 | 176 | size = MADDisasmDataSize(); 177 | if( size > TraceState.ddsize ) { 178 | new = TraceState.dd; 179 | _Realloc( new, size ); 180 | if( new == NULL ) { 181 | ReportMADFailure( MS_NO_MEM ); 182 | } else { 183 | TraceState.dd = new; 184 | TraceState.ddsize = size; 185 | } 186 | } 187 | size = MADTraceSize(); 188 | if( size > TraceState.tdsize ) { 189 | new = TraceState.td; 190 | _Realloc( new, size ); 191 | if( new == NULL ) { 192 | ReportMADFailure( MS_NO_MEM ); 193 | } else { 194 | TraceState.td = new; 195 | TraceState.tdsize = size; 196 | } 197 | } 198 | } 199 | 200 | static void TraceGetData( void ) 201 | { 202 | address addr; 203 | 204 | addr = GetRegIP(); 205 | if( AddrComp( TraceState.curraddr, addr ) != 0 ) { 206 | TraceState.curraddr = addr; 207 | MADDisasm( TraceState.dd, &addr, 0 ); 208 | TraceState.prev_control = TraceState.curr_control; 209 | TraceState.curr_control = MADDisasmControl( TraceState.dd, &DbgRegs->mr ); 210 | } 211 | } 212 | 213 | bool TraceStart( bool tracing ) 214 | { 215 | MADTraceInit( TraceState.td, &DbgRegs->mr ); 216 | return( tracing ); 217 | } 218 | 219 | mad_trace_how TraceHow( bool force_into ) 220 | { 221 | static const mad_trace_kind MTRKind[] = { MTRK_INTO, MTRK_OVER, MTRK_NEXT }; 222 | mad_trace_kind kind; 223 | mad_trace_how how; 224 | 225 | TraceGetData(); 226 | switch( TraceState.curr_control & MDC_TYPE_MASK ) { 227 | case MDC_CALL: 228 | case MDC_SYSCALL: 229 | TraceState.doing_call = TRUE; 230 | break; 231 | default: 232 | TraceState.doing_call = FALSE; 233 | break; 234 | } 235 | if( TraceState.give_it_up ) { 236 | DbgTmpBrk.status.b.active = FALSE; 237 | TraceState.give_it_up = FALSE; 238 | how = MTRH_BREAK; 239 | return( how ); 240 | } else if( force_into ) { 241 | kind = MTRK_INTO; 242 | } else if( TraceState.trace_out ) { 243 | TraceState.trace_out = FALSE; 244 | TraceState.in_dll_thunk = FALSE; 245 | kind = MTRK_OUT; 246 | } else { 247 | kind = MTRKind[ TraceState.type ]; 248 | } 249 | if( !force_into && DbgTmpBrk.status.b.active ) { 250 | how = MTRH_BREAK; 251 | _SwitchOn( SW_EXECUTE_LONG ); 252 | } else { 253 | how = MADTraceOne( TraceState.td, TraceState.dd, kind, 254 | &DbgRegs->mr, &DbgTmpBrk.loc.addr ); 255 | } 256 | switch( how ) { 257 | case MTRH_BREAK: 258 | case MTRH_STEPBREAK: 259 | DbgTmpBrk.status.b.active = TRUE; 260 | } 261 | if( DbgTmpBrk.status.b.active ) { 262 | /* for recursion detection */ 263 | if( !TraceState.unwinding ) TraceState.watch_stack = GetRegSP(); 264 | } 265 | TraceState.how = how; 266 | return( how ); 267 | } 268 | 269 | bool TraceSimulate( void ) 270 | { 271 | mad_status ms; 272 | 273 | ReadDbgRegs(); /* only SP & IP are valid on entry */ 274 | ms = MADTraceSimulate( TraceState.td, TraceState.dd, 275 | &DbgRegs->mr, &DbgRegs->mr ); 276 | if( ms != MS_OK ) return( FALSE ); 277 | WriteDbgRegs(); 278 | return( TRUE ); 279 | } 280 | 281 | bool TraceModifications( MAD_MEMREF_WALKER *wk, void *d ) 282 | { 283 | switch( TraceState.how ) { 284 | case MTRH_SIMULATE: 285 | case MTRH_STEP: 286 | case MTRH_STEPBREAK: 287 | if( MADDisasmInsUndoable( TraceState.dd ) != MS_OK ) return( FALSE ); 288 | if( MADDisasmMemRefWalk( TraceState.dd, wk, &DbgRegs->mr, d ) == WR_CONTINUE ) { 289 | return( TRUE ); 290 | } 291 | break; 292 | } 293 | return( FALSE ); 294 | } 295 | 296 | void TraceStop( bool tracing ) 297 | { 298 | MADTraceFini( TraceState.td ); 299 | } 300 | 301 | void TraceKill( void ) 302 | { 303 | TraceState.state = TS_NONE; 304 | } 305 | 306 | static void TracePostponed( void ) 307 | { 308 | switch( TraceState.state ) { 309 | case TS_ACTIVE: 310 | case TS_REACTIVATED: 311 | TraceState.state = TS_POSTPONED; 312 | TraceState.brkpt = DbgTmpBrk.loc.addr; 313 | } 314 | } 315 | 316 | bool SourceStep( void ) 317 | { 318 | return( TraceState.cur_level == SOURCE ); 319 | } 320 | 321 | /* 322 | * CheckTraceSourceStop - see if we want this trap because it ends a 323 | * a source level trace command 324 | */ 325 | 326 | 327 | static bool CheckTraceSourceStop( bool *have_source ) 328 | { 329 | DIPHDL( cue, line ); 330 | DIPHDL( cue, oldline ); 331 | DIPHDL( sym, sym ); 332 | address line_addr; 333 | search_result sr; 334 | sym_info info; 335 | void *viewhndl; 336 | 337 | *have_source = FALSE; 338 | TraceState.in_thunk = FALSE; 339 | sr = DeAliasAddrSym( NO_MOD, TraceState.curraddr, sym ); 340 | if( sr != SR_NONE 341 | && SymInfo( sym, NULL, &info ) == DS_OK 342 | && info.kind == SK_PROCEDURE 343 | && info.compiler ) { 344 | /* in a thunk */ 345 | TraceState.in_thunk = TRUE; 346 | return( FALSE ); 347 | } 348 | viewhndl = NULL; 349 | *have_source = DeAliasAddrCue( NO_MOD, TraceState.curraddr, line ) != SR_NONE; 350 | if( *have_source && _IsOn( SW_CHECK_SOURCE_EXISTS ) && 351 | ( viewhndl = OpenSrcFile( line ) ) != NULL ) { 352 | if( viewhndl != NULL ) FDoneSource( viewhndl ); 353 | line_addr = CueAddr( line ); 354 | if( AddrComp( TraceState.oldaddr, line_addr ) != 0 ) { 355 | if( DeAliasAddrCue( NO_MOD, TraceState.oldaddr, oldline ) != SR_NONE 356 | && CueLine( line ) == CueLine( oldline ) 357 | && CueColumn( line ) == CueColumn( oldline ) 358 | && CueFileId( line ) == CueFileId( oldline ) 359 | && CueMod( line ) == CueMod( oldline ) ) { 360 | /* 361 | We've moved to a different starting address for the 362 | cue, but all the source information is the same, so 363 | update the current cue start address and keep on going. 364 | (This can happen with C++ switch statements since 365 | there's a jump in the middle of the switch code.) 366 | */ 367 | TraceState.oldaddr = line_addr; 368 | return( FALSE ); 369 | } 370 | switch( TraceState.curr_control & MDC_TYPE_MASK ) { 371 | case MDC_RET: 372 | case MDC_SYSRET: 373 | break; 374 | default: 375 | return( TRUE ); 376 | } 377 | if( AddrComp( line_addr, TraceState.curraddr ) == 0 ) { 378 | return( TRUE ); 379 | } 380 | TraceState.oldaddr = line_addr; 381 | TraceState.stop_on_call = TRUE; 382 | } else if( TraceState.stop_now ) { 383 | return( TRUE ); 384 | } 385 | return( FALSE ); 386 | } 387 | if( TraceState.req_level == MIX ) { 388 | if( sr == SR_NONE ) return( TRUE ); 389 | if( !IsSupportRoutine( sym ) ) return( TRUE ); 390 | } 391 | return( FALSE ); 392 | } 393 | 394 | bool CheckForDLLThunk( void ) 395 | /***************************/ 396 | { 397 | address next_ins; 398 | DIPHDL( cue, line ); 399 | 400 | switch( TraceState.prev_control & MDC_TYPE_MASK ) { 401 | case MDC_CALL: 402 | case MDC_SYSCALL: 403 | break; 404 | default: 405 | return( FALSE ); 406 | } 407 | switch( TraceState.curr_control & (MDC_TYPE_MASK+MDC_CONDITIONAL_MASK) ) { 408 | case MDC_JUMP+MDC_UNCONDITIONAL: 409 | break; 410 | default: 411 | return( FALSE ); 412 | } 413 | ReadDbgRegs(); /* only SP & IP are valid on entry */ 414 | switch( MADDisasmInsNext( TraceState.dd, &DbgRegs->mr, &next_ins ) ) { 415 | case MS_OK: 416 | return( DeAliasAddrCue( NO_MOD, next_ins, line ) == SR_EXACT ); 417 | //NYI: this next case can be removed once all the MAD's are up to snuff 418 | case MS_ERR|MS_UNSUPPORTED: 419 | return( TRUE ); 420 | } 421 | return( FALSE ); 422 | } 423 | 424 | 425 | /* 426 | * CheckTrace - check to see if we really want this trace trap 427 | */ 428 | 429 | unsigned TraceCheck( unsigned conditions ) 430 | { 431 | bool have_source; 432 | bool recursed; 433 | 434 | TraceGetData(); 435 | if( DbgTmpBrk.status.b.hit && (conditions & COND_STOPPERS) ) { 436 | DebugMsgC( "WD, TraceCheck: DgbTmpBrk hit \r\n" ); 437 | DbgTmpBrk.status.b.active = FALSE; 438 | conditions &= ~COND_STOPPERS; 439 | conditions |= COND_TRACE; 440 | } 441 | if( !(conditions & COND_TRACE) ) return( conditions ); 442 | 443 | DebugMsgC( "WD, TraceCheck: MS 1\r\n" ); 444 | if( DbgTmpBrk.status.b.hit && TraceState.type == TRACE_OVER ) { 445 | /* japheth: no check for recursion in assembly level - it won't work */ 446 | if( TraceState.cur_level == ASM ) 447 | recursed = 0; 448 | else 449 | recursed = MADTraceHaveRecursed( TraceState.watch_stack, &DbgRegs->mr ) == MS_OK; 450 | if( _IsOn( SW_RECURSE_CHECK ) && recursed && ( TraceState.doing_call || TraceState.unwinding ) ) { 451 | DebugMsg( "WD, TraceCheck: MS 1.1, recursed=%u doing_call=%u unwinding=%u\r\n", recursed, TraceState.doing_call, TraceState.unwinding ); 452 | /* we're down some levels in a recursive call -- want to unwind. */ 453 | TraceState.unwinding = TRUE; 454 | NullStatus( &DbgTmpBrk ); 455 | DbgTmpBrk.status.b.active = TRUE; 456 | return( conditions & ~COND_STOPPERS ); 457 | } 458 | TraceState.unwinding = FALSE; 459 | if( (conditions & COND_THREAD) 460 | && TraceState.etid != RemoteSetThread( 0 ) ) { 461 | DebugMsgC( "WD, TraceCheck: MS 1.2\r\n" ); 462 | /* stepped over a call and another thread ran into bp - keep going */ 463 | NullStatus( &DbgTmpBrk ); 464 | DbgTmpBrk.status.b.active = TRUE; 465 | return( conditions & ~COND_STOPPERS ); 466 | } 467 | } 468 | DebugMsgC( "WD, TraceCheck: MS 2\r\n" ); 469 | if( OvlSize != 0 470 | && (RemoteOvlTransAddr( &TraceState.curraddr ) || TransOvlRetAddr( &TraceState.curraddr, 0 )) ) { 471 | /* have traced into an overlay vector or overlay mgr return routine 472 | -- want to get overlay loaded and enter real routine */ 473 | DbgTmpBrk.loc.addr = TraceState.curraddr; 474 | NullStatus( &DbgTmpBrk ); 475 | DbgTmpBrk.status.b.active = TRUE; 476 | return( conditions & ~COND_STOPPERS ); 477 | } 478 | if( TraceState.cur_level == ASM ) return( conditions | COND_TRACE ); 479 | DebugMsgC( "WD, TraceCheck: MS 3\r\n" ); 480 | if( CheckTraceSourceStop( &have_source ) ) { 481 | DebugMsgC( "WD, TraceCheck: CheckTraceSourceStop returned TRUE\r\n" ); 482 | if( CheckForDLLThunk() ) return( conditions & ~COND_STOPPERS ); 483 | return( conditions | COND_TRACE ); 484 | } 485 | DebugMsgC( "WD, TraceCheck: tracing source\r\n" ); 486 | /* 487 | at this point, we know we're tracing source only! 488 | */ 489 | if( TraceState.in_dll_thunk ) { 490 | if( TraceState.type == TRACE_INTO && !TraceState.in_thunk ) { 491 | TraceState.trace_out = TRUE; 492 | if( !TraceState.unwinding ) TraceState.watch_stack = GetRegSP(); 493 | } 494 | return( conditions & ~COND_STOPPERS ); 495 | } 496 | NullStatus( &DbgTmpBrk ); 497 | switch( TraceState.prev_control & MDC_TYPE_MASK ) { 498 | case MDC_RET: 499 | case MDC_SYSRET: 500 | if( !TraceState.in_thunk && !have_source ) { 501 | TraceState.give_it_up = TRUE; 502 | return( conditions & ~COND_STOPPERS ); 503 | } 504 | break; 505 | case MDC_CALL: 506 | case MDC_SYSCALL: 507 | if( CheckForDLLThunk() ) { 508 | TraceState.in_dll_thunk = TRUE; 509 | return( conditions & ~COND_STOPPERS ); 510 | } 511 | if( TraceState.stop_on_call ) TraceState.stop_now = TRUE; 512 | if( TraceState.type == TRACE_INTO && !TraceState.in_thunk ) { 513 | TraceState.trace_out = TRUE; 514 | if( !TraceState.unwinding ) TraceState.watch_stack = GetRegSP(); 515 | } 516 | return( conditions & ~COND_STOPPERS ); 517 | } 518 | return( conditions & ~COND_STOPPERS ); 519 | } 520 | 521 | static char DoTrace( debug_level curr_level ) 522 | { 523 | unsigned conditions; 524 | DIPHDL( cue, line ); 525 | 526 | if( curr_level == SOURCE ) { 527 | if( TraceState.type == TRACE_NEXT ) { 528 | if( DeAliasAddrCue( NO_MOD, GetCodeDot(), line ) == SR_NONE 529 | || CueAdjust( line, 1, line ) != DS_OK ) { 530 | Warn( LIT( WARN_No_Nxt_Src_Ln ) ); 531 | return( STOP ); 532 | } 533 | DbgTmpBrk.loc.addr = CueAddr( line ); 534 | DbgTmpBrk.status.b.active = TRUE; 535 | } 536 | if( TraceState.state == TS_ACTIVE ) { 537 | DeAliasAddrCue( NO_MOD, GetCodeDot(), line ); 538 | TraceState.oldaddr = CueAddr( line ); 539 | TraceState.stop_on_call = FALSE; 540 | TraceState.stop_now = FALSE; 541 | } 542 | } 543 | TraceState.unwinding = FALSE; 544 | TraceState.watch_stack = NilAddr; 545 | TraceState.doing_call = FALSE; 546 | TraceState.trace_out = FALSE; 547 | TraceState.in_dll_thunk = FALSE; 548 | TraceState.etid = DbgRegs->tid; 549 | conditions = Execute( TRUE, _IsOn( SW_FLIP ) ); 550 | if( _IsOn( SW_TRAP_CMDS_PUSHED ) ) { 551 | _SwitchOff( SW_TRAP_CMDS_PUSHED ); 552 | return( PROCCMD ); 553 | } 554 | if( conditions & COND_TRACE ) return( STOP ); 555 | return( KEEPGOING ); 556 | } 557 | 558 | void PerformTrace( void ) 559 | { 560 | char ret; 561 | char level[20]; 562 | char over[20]; 563 | 564 | TraceState.userstat = UserTmpBrk.status.b; 565 | TraceState.curr_control = MDC_OPER | MDC_TAKEN; 566 | NullStatus( &UserTmpBrk ); 567 | NullStatus( &DbgTmpBrk ); 568 | switch( TraceState.state ) { 569 | case TS_ACTIVE: 570 | GetCmdEntry( LevelTab, TraceState.cur_level + 1, level ); 571 | GetCmdEntry( TraceTab2, TraceState.type + 1, over ); 572 | Format( TxtBuff, "%s/%s/%s", GetCmdName( CMD_TRACE ), level, over ); 573 | RecordEvent( TxtBuff ); 574 | ret = DoTrace( TraceState.cur_level ); 575 | CheckEventRecorded(); 576 | if( ret != PROCCMD ) { 577 | TraceKill(); 578 | } else { 579 | TracePostponed(); 580 | } 581 | UserTmpBrk.status.b = TraceState.userstat; 582 | SetCodeDot( GetCodeDot() ); 583 | break; 584 | case TS_POSTPONED: 585 | TraceState.state = TS_REACTIVATED; 586 | if( !DbgTmpBrk.status.b.active ) { 587 | DbgTmpBrk.loc.addr = TraceState.brkpt; 588 | NullStatus( &DbgTmpBrk ); 589 | DbgTmpBrk.status.b.active = TRUE; 590 | } 591 | ret = DoTrace( TraceState.cur_level ); 592 | if( ret != PROCCMD ) { 593 | TraceKill(); 594 | } else { 595 | TracePostponed(); 596 | } 597 | UserTmpBrk.status.b = TraceState.userstat; 598 | SetCodeDot( GetCodeDot() ); 599 | break; 600 | } 601 | TraceState.curraddr = NilAddr; 602 | TraceState.prev_control = MDC_OPER | MDC_TAKEN; 603 | TraceState.curr_control = MDC_OPER | MDC_TAKEN; 604 | } 605 | 606 | 607 | /* 608 | * DoneTraceCmd 609 | */ 610 | 611 | OVL_EXTERN bool DoneTraceCmd( char *cmds, inp_rtn_action action ) 612 | { 613 | switch( action ) { 614 | case INP_RTN_INIT: 615 | ReScan( cmds ); 616 | return( TRUE ); 617 | case INP_RTN_EOL: 618 | if( TraceState.state == TS_NONE ) return( FALSE ); 619 | PerformTrace(); 620 | return( TRUE ); 621 | case INP_RTN_FINI: 622 | return( TRUE ); 623 | } 624 | return( FALSE ); // silence compiler 625 | } 626 | 627 | /* 628 | * PushTraceCmd 629 | */ 630 | 631 | static void PushTraceCmd( void ) 632 | { 633 | PushInpStack( "\0", &DoneTraceCmd, TRUE ); 634 | TypeInpStack( INP_HOLD ); 635 | } 636 | 637 | /* 638 | * ProcTrace -- process trace command 639 | */ 640 | 641 | bool HasLineInfo( address addr ) 642 | { 643 | mod_handle mod; 644 | 645 | if( DeAliasAddrMod( addr, &mod ) == SR_NONE ) return( FALSE ); 646 | if( ModHasInfo( mod, HK_CUE ) != DS_OK ) return( FALSE ); 647 | return( TRUE ); 648 | } 649 | 650 | void ExecTrace( trace_cmd_type type, debug_level level ) 651 | { 652 | TraceState.type = type; 653 | TraceState.state = TS_ACTIVE; 654 | TraceState.savecode = GetCodeDot(); 655 | TraceState.saveaddr = GetRegIP(); 656 | SetCodeLoc( TraceState.saveaddr ); 657 | TraceState.req_level = level; 658 | switch( level ) { 659 | case MIX: 660 | if( ActiveWindowLevel == ASM || !HasLineInfo( TraceState.saveaddr ) ) { 661 | TraceState.cur_level = ASM; 662 | } else { 663 | TraceState.cur_level = SOURCE; 664 | } 665 | break; 666 | case SOURCE: 667 | if( !HasLineInfo( TraceState.saveaddr ) ) { 668 | Error( ERR_NONE, LIT( ERR_NO_SOURCE_INFO ) ); 669 | } 670 | /* fall through */ 671 | default: 672 | TraceState.cur_level = level; 673 | } 674 | TraceState.userstat = UserTmpBrk.status.b; 675 | SetRegIP( GetCodeDot() ); 676 | NullStatus( &DbgTmpBrk ); 677 | PushTraceCmd(); 678 | } 679 | 680 | 681 | void ProcTrace( void ) 682 | { 683 | int level_index; 684 | int type_index; 685 | debug_level trace_level; 686 | trace_cmd_type trace_type; 687 | address addr; 688 | 689 | type_index = 0; 690 | level_index = 0; 691 | if( CurrToken == T_DIV ) { 692 | Scan(); /* try first set of commands */ 693 | level_index = ScanCmd( LevelTab ); 694 | if( level_index == 0 ) { 695 | type_index = ScanCmd( TraceTab2 ); 696 | if( type_index == 0 ) { 697 | Error( ERR_LOC, LIT( ERR_BAD_OPTION ), GetCmdName( CMD_TRACE ) ); 698 | } 699 | } else { 700 | if( CurrToken == T_DIV ) { /* do second set of commands */ 701 | Scan(); 702 | type_index = ScanCmd( TraceTab2 ); 703 | if( type_index == 0 ) { 704 | Error( ERR_LOC, LIT( ERR_BAD_OPTION ), GetCmdName( CMD_TRACE ) ); 705 | } 706 | } 707 | } 708 | } 709 | addr = GetCodeDot(); 710 | OptMemAddr( EXPR_CODE, &addr ); 711 | ReqEOC(); 712 | trace_level = level_index == 0 ? DbgLevel : level_index-1; 713 | trace_type = type_index == 0 ? TRACE_OVER : type_index-1; 714 | ExecTrace( trace_type, trace_level ); 715 | } 716 | 717 | 718 | void FiniTrace( void ) 719 | { 720 | _Free( TraceState.td ); 721 | TraceState.td = NULL; 722 | TraceState.tdsize = 0; 723 | _Free( TraceState.dd ); 724 | TraceState.dd = NULL; 725 | TraceState.ddsize = 0; 726 | } 727 | 728 | 729 | /* 730 | * LevelSet -- process set/level command 731 | */ 732 | 733 | void LevelSet( void ) 734 | { 735 | int trace_level; 736 | 737 | trace_level = ScanCmd( LevelTab ); 738 | if( trace_level == 0 ) Error( ERR_LOC, LIT( ERR_BAD_SUBCOMMAND ), GetCmdName( CMD_SET ) ); 739 | ReqEOC(); 740 | DbgLevel = trace_level - 1; 741 | } 742 | 743 | void LevelConf( void ) 744 | { 745 | GetCmdEntry( LevelTab, DbgLevel + 1, TxtBuff ); 746 | ConfigLine( TxtBuff ); 747 | } 748 | -------------------------------------------------------------------------------- /wv_src/dsx/pcscrnio.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Open Watcom Project 4 | * 5 | * Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved. 6 | * 7 | * ======================================================================== 8 | * 9 | * This file contains Original Code and/or Modifications of Original 10 | * Code as defined in and that are subject to the Sybase Open Watcom 11 | * Public License version 1.0 (the 'License'). You may not use this file 12 | * except in compliance with the License. BY USING THIS FILE YOU AGREE TO 13 | * ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is 14 | * provided with the Original Code and Modifications, and is also 15 | * available at www.sybase.com/developer/opensource. 16 | * 17 | * The Original Code and all software distributed under the License are 18 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 19 | * EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM 20 | * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR 22 | * NON-INFRINGEMENT. Please see the License for the specific language 23 | * governing rights and limitations under the License. 24 | * 25 | * ======================================================================== 26 | * 27 | * Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE 28 | * DESCRIBE IT HERE! 29 | * 30 | ****************************************************************************/ 31 | 32 | 33 | #include 34 | 35 | #if defined(__OSI__) 36 | extern void __Int10(); 37 | #define _INT_10 "call __Int10" 38 | #else 39 | #define _INT_10 "int 0x10" 40 | #endif 41 | 42 | 43 | #define VIDMONOINDXREG 0x03b4 44 | #define VIDCOLRINDXREG 0x03d4 45 | #define _seq_write( reg, val ) _ega_write( SEQ_PORT, reg, val ) 46 | #define _graph_write( reg, val ) _ega_write( GRA_PORT, reg, val ) 47 | #define _seq_read( reg ) _vga_read( SEQ_PORT, reg ) 48 | #define _graph_read( reg ) _vga_read( GRA_PORT, reg ) 49 | 50 | 51 | enum ega_seqencer { 52 | SEQ_PORT = 0x3c4, 53 | SEQ_RESET = 0, 54 | SEQ_CLOCK_MODE = 1, 55 | SEQ_MAP_MASK = 2, 56 | SEQ_CHAR_MAP_SEL= 3, 57 | SEQ_MEM_MODE = 4, 58 | /* reset register */ 59 | RES_NOT_ASYNCH = 0x01, 60 | RES_NOT_SYNCH = 0x02, 61 | /* clock mode register */ 62 | CLK_8_DOTS = 0x01, 63 | CLK_SHIFT_LOAD = 0x04, 64 | CLK_DOT_CLOCK = 0x08, 65 | /* map mask register */ 66 | MSK_MAP_0 = 0x01, 67 | MSK_MAP_1 = 0x02, 68 | MSK_MAP_2 = 0x04, 69 | MSK_MAP_3 = 0x08, 70 | /* character map register */ 71 | CHR_MAPA_0 = 0x00, 72 | CHR_MAPA_1 = 0x01, 73 | CHR_MAPA_2 = 0x02, 74 | CHR_MAPA_3 = 0x03, 75 | CHR_MAPB_0 = 0x00, 76 | CHR_MAPB_1 = 0x04, 77 | CHR_MAPB_2 = 0x08, 78 | CHR_MAPB_3 = 0x0c, 79 | /* memory mode register */ 80 | MEM_ALPHA = 0x01, 81 | MEM_EXTENDED = 0x02, 82 | MEM_NOT_ODD_EVEN= 0x04 83 | }; 84 | 85 | enum ega_graphics_controller { 86 | GRA_PORT = 0x3ce, 87 | GRA_SET_RESET = 0, 88 | GRA_ENABLE_SR = 1, 89 | GRA_COLOR_COMP = 2, 90 | GRA_DATA_ROT = 3, 91 | GRA_READ_MAP = 4, 92 | GRA_GRAPH_MODE = 5, 93 | GRA_MISC = 6, 94 | GRA_COLOR_CARE = 7, 95 | GRA_BIT_MASK = 8, 96 | /* set/reset register */ 97 | SR_MAP_0 = 0x01, 98 | SR_MAP_1 = 0x02, 99 | SR_MAP_2 = 0x04, 100 | SR_MAP_3 = 0x08, 101 | /* enable set/reset register */ 102 | ESR_MAP_0 = 0x01, 103 | ESR_MAP_1 = 0x02, 104 | ESR_MAP_2 = 0x04, 105 | ESR_MAP_3 = 0x08, 106 | /* colour compare register */ 107 | COL_MAP_0 = 0x01, 108 | COL_MAP_1 = 0x02, 109 | COL_MAP_2 = 0x04, 110 | COL_MAP_3 = 0x08, 111 | /* data rotate register */ 112 | /* bottom three bits are the right rotate count */ 113 | ROT_UNMOD = 0x00, 114 | ROT_AND = 0x08, 115 | ROT_OR = 0x10, 116 | ROT_XOR = 0x18, 117 | /* read map select register */ 118 | RMS_MAP_0 = 0x00, 119 | RMS_MAP_1 = 0x01, 120 | RMS_MAP_2 = 0x02, 121 | RMS_MAP_3 = 0x03, 122 | /* graphics mode register */ 123 | GRM_EN_ROT = 0x00, 124 | GRM_SYS_LATCH = 0x01, 125 | GRM_BIT_PLANE = 0x02, 126 | GRM_ILL = 0x03, 127 | GRM_TEST = 0x04, 128 | GRM_READ_MODE = 0x08, 129 | GRM_ODD_EVEN = 0x10, 130 | GRM_SHIFT = 0x20, 131 | /* miscellaneous register */ 132 | MIS_GRAPH_MODE = 0x01, 133 | MIS_CHAIN = 0x02, 134 | MIS_A000_128 = 0x00, 135 | MIS_A000_64 = 0x04, 136 | MIS_B000_32 = 0x08, 137 | MIS_B800_32 = 0x0c, 138 | /* colour don't care register */ 139 | CDC_CARE_MAP_0 = 0x01, 140 | CDC_CARE_MAP_1 = 0x02, 141 | CDC_CARE_MAP_2 = 0x04, 142 | CDC_CARE_MAP_3 = 0x08 143 | /* bit mask register */ 144 | /* bit N set to one causes that bit in each plane not to be written */ 145 | }; 146 | 147 | enum vid_state_info { 148 | VID_STATE_HARDWARE = 0x1, 149 | VID_STATE_BIOS = 0x2, 150 | VID_STATE_DAC_N_COLOURS = 0x4, 151 | VID_STATE_SUPERVGA = 0x8, 152 | VID_STATE_ALL = 0xF 153 | }; 154 | 155 | 156 | extern void BIOSSetPage( unsigned_8 pagenb ); 157 | #if 0 158 | #pragma aux BIOSSetPage = \ 159 | " push ebp " \ 160 | " mov ah, 5 " \ 161 | _INT_10 \ 162 | " pop ebp " \ 163 | parm [ al ] \ 164 | modify exact [ ah ]; 165 | #else 166 | #pragma aux BIOSSetPage = \ 167 | "push ds" \ 168 | "push 0040h" \ 169 | "pop ds" \ 170 | "mov ds:[62h],al" \ 171 | "mov ah, 00" \ 172 | "mov cx, ds:[4Ch]" \ 173 | "mul cx" \ 174 | "mov ds:[4Eh], ax" \ 175 | "mov cx, ax" \ 176 | "shr cx, 1" \ 177 | "mov dx, ds:[63h]" \ 178 | "mov al, 0Ch" \ 179 | "mov ah, ch" \ 180 | "out dx, ax" \ 181 | "inc al" \ 182 | "mov ah, cl" \ 183 | "out dx, ax" \ 184 | "pop ds" \ 185 | parm [ al ] \ 186 | modify exact [ ah cx dx ]; 187 | #endif 188 | 189 | extern unsigned_8 BIOSGetPage( void ); 190 | #pragma aux BIOSGetPage = \ 191 | " push ebp " \ 192 | " mov ah, 0fh " \ 193 | _INT_10 \ 194 | " pop ebp " \ 195 | modify exact [ ax bh ] \ 196 | value [ bh ]; 197 | 198 | extern unsigned_8 BIOSGetMode( void ); 199 | #pragma aux BIOSGetMode = \ 200 | " push ebp " \ 201 | " mov ah, 0fh " \ 202 | _INT_10 \ 203 | " pop ebp " \ 204 | modify exact [ ax bh ]; 205 | 206 | extern void BIOSSetMode( unsigned_8 mode ); 207 | #pragma aux BIOSSetMode = \ 208 | " push ebp " \ 209 | " mov ah, 0 " \ 210 | _INT_10 \ 211 | " pop ebp " \ 212 | parm [ al ] \ 213 | modify exact [ ah ]; 214 | 215 | extern unsigned_16 BIOSGetCurPos( unsigned_8 pagenb ); 216 | #pragma aux BIOSGetCurPos = \ 217 | " push ebp " \ 218 | " mov ah, 3 " \ 219 | _INT_10 \ 220 | " pop ebp " \ 221 | parm [ bh ] \ 222 | modify exact [ cx dx ] \ 223 | value [ dx ]; 224 | 225 | extern void BIOSSetCurPos( unsigned_16 rowcol, unsigned_8 pagenb ); 226 | #pragma aux BIOSSetCurPos = \ 227 | " push ebp " \ 228 | " mov ah, 2 " \ 229 | _INT_10 \ 230 | " pop ebp " \ 231 | parm [ dx ] [ bh ] \ 232 | modify exact [ ah ]; 233 | 234 | extern unsigned_16 BIOSGetCurTyp( unsigned_8 pagenb ); 235 | #pragma aux BIOSGetCurTyp = \ 236 | " push ebp " \ 237 | " mov ah, 3 " \ 238 | _INT_10 \ 239 | " pop ebp " \ 240 | parm [ bh ] \ 241 | modify exact [ ah cx dx ] \ 242 | value [ cx ]; 243 | 244 | extern void BIOSSetCurTyp( unsigned_16 startend ); 245 | #pragma aux BIOSSetCurTyp = \ 246 | " push ebp " \ 247 | " mov ah, 1 " \ 248 | _INT_10 \ 249 | " pop ebp " \ 250 | parm [ cx ] \ 251 | modify exact [ ah ]; 252 | 253 | extern unsigned_8 BIOSGetAttr( unsigned_8 pagenb ); 254 | #pragma aux BIOSGetAttr = \ 255 | " push ebp " \ 256 | " mov ah, 8 " \ 257 | _INT_10 \ 258 | " pop ebp " \ 259 | parm [ bh ] \ 260 | modify exact [ ax ] \ 261 | value [ ah ]; 262 | 263 | extern void BIOSSetAttr( unsigned_8 attr ); 264 | #pragma aux BIOSSetAttr = \ 265 | " push ebp " \ 266 | " mov cx, 0 " \ 267 | " mov dx, 3250h " \ 268 | " mov ax, 600h " \ 269 | _INT_10 \ 270 | " pop ebp " \ 271 | parm [ bh ] \ 272 | modify exact [ ax cx dx ]; 273 | 274 | extern uint_8 _ReadCRTCReg( uint_16 vidport, uint_8 regnb ); 275 | #pragma aux _ReadCRTCReg = \ 276 | "out dx, al ", \ 277 | "inc dx ", \ 278 | "in al, dx " \ 279 | parm [ dx ] [ al ] \ 280 | modify exact [ al dx ]; 281 | 282 | extern void _WriteCRTCReg( uint_16 vidport, uint_8 regnb, uint_8 value ); 283 | #pragma aux _WriteCRTCReg = \ 284 | "out dx, al ", \ 285 | "inc dx ", \ 286 | "mov al, ah ", \ 287 | "out dx, al " \ 288 | parm [ dx ] [ al ] [ ah ] \ 289 | modify exact [ al dx ]; 290 | 291 | #if 0 292 | 293 | extern unsigned_8 VIDGetRow( unsigned_16 vidport ); 294 | #pragma aux VIDGetRow = \ 295 | " mov al, 0fh ", \ 296 | " out dx, al ", \ 297 | " inc dx ", \ 298 | " in al, dx " \ 299 | parm [ dx ] \ 300 | modify exact [ al dx ]; 301 | 302 | extern void VIDSetRow( unsigned_16 vidport, unsigned_8 row ); 303 | #pragma aux VIDSetRow = \ 304 | " mov al, 0fh ", \ 305 | " out dx, al ", \ 306 | " inc dx ", \ 307 | " mov al, ah ", \ 308 | " out dx, al " \ 309 | parm [ dx ] [ ah ] \ 310 | modify exact [ ax dx ]; 311 | 312 | extern void VIDSetPos( unsigned_16 vidport, unsigned_16 cursorpos ); 313 | #pragma aux VIDSetPos = \ 314 | " mov al, 0fh ", \ 315 | " out dx, al ", \ 316 | " inc dx ", \ 317 | " mov al, bl ", \ 318 | " out dx, al ", \ 319 | " dec dx ", \ 320 | " mov al, 0eh ", \ 321 | " out dx, al ", \ 322 | " inc dx ", \ 323 | " mov al, bh ", \ 324 | " out dx, al " \ 325 | parm [ dx ] [ bx ] \ 326 | modify exact [ al dx ]; 327 | 328 | extern unsigned_16 VIDGetPos( unsigned_16 vidport ); 329 | #pragma aux VIDGetPos = \ 330 | " mov al, 0fh ", \ 331 | " out dx, al ", \ 332 | " inc dx ", \ 333 | " in al, dx ", \ 334 | " mov ah, al ", \ 335 | " dec dx ", \ 336 | " mov al, 0eh ", \ 337 | " out dx, al ", \ 338 | " inc dx ", \ 339 | " in al, dx ", \ 340 | " xchg ah, al " \ 341 | parm [ dx ] \ 342 | modify exact [ ax dx ]; 343 | 344 | extern unsigned_8 VIDGetCol( unsigned_16 vidport ); 345 | #pragma aux VIDGetCol = \ 346 | " mov al, 0eh ", \ 347 | " out dx, al ", \ 348 | " inc dx ", \ 349 | " in al, dx " \ 350 | parm [ dx ] \ 351 | modify exact [ al dx ]; 352 | 353 | extern void VIDSetCurTyp( unsigned_16 vidport, unsigned_16 cursortyp ); 354 | #pragma aux VIDSetCurTyp = \ 355 | " push ax ", \ 356 | " mov al, 0ah ", \ 357 | " out dx, al ", \ 358 | " inc dx ", \ 359 | " mov al, ah ", \ 360 | " out dx, al ", \ 361 | " dec dx ", \ 362 | " mov al, 0bh ", \ 363 | " out dx, al ", \ 364 | " inc dx ", \ 365 | " pop ax ", \ 366 | " out dx, al " \ 367 | parm [ dx ] [ ax ] \ 368 | modify exact [ al dx ]; 369 | 370 | extern unsigned_16 VIDGetCurTyp( unsigned_16 vidport ); 371 | #pragma aux VIDGetCurTyp = \ 372 | " mov al, 0bh ", \ 373 | " out dx, al ", \ 374 | " inc dx ", \ 375 | " in al, dx ", \ 376 | " mov ah, al ", \ 377 | " dec dx ", \ 378 | " mov al, 0ah ", \ 379 | " out dx, al ", \ 380 | " inc dx ", \ 381 | " in al, dx ", \ 382 | " xchg ah, al " \ 383 | parm [ dx ] \ 384 | modify exact [ ax dx ]; 385 | 386 | #endif 387 | 388 | extern void VIDWait( void ); 389 | #pragma aux VIDWait = \ 390 | " jmp x " \ 391 | " x: " \ 392 | modify exact [ ]; 393 | 394 | extern unsigned BIOSEGAInfo( void ); 395 | #pragma aux BIOSEGAInfo = \ 396 | " push ebp " \ 397 | " mov ah, 12h " \ 398 | " mov bx, 0ff10h " \ 399 | _INT_10 \ 400 | " shl ebx, 10h " \ 401 | " mov bx, cx " \ 402 | " pop ebp " \ 403 | modify exact [ ah ebx cx ] \ 404 | value [ ebx ]; 405 | 406 | extern unsigned_8 BIOSGetRows( void ); 407 | #pragma aux BIOSGetRows = \ 408 | " push es " \ 409 | " push ebp " \ 410 | " mov ax, 1130h " \ 411 | " mov bh, 0 " \ 412 | _INT_10 \ 413 | " inc dl " \ 414 | " pop ebp " \ 415 | " pop es " \ 416 | /* modify exact [ ax bh cx dl ] */ \ 417 | modify exact [ ax ebx ecx edx edi ] /* workaround bug in DOS4G */\ 418 | value [ dl ]; 419 | 420 | extern unsigned_16 BIOSGetPoints( void ); 421 | #pragma aux BIOSGetPoints = \ 422 | " push es " \ 423 | " push ebp " \ 424 | " mov ax, 1130h " \ 425 | " mov bh, 0 " \ 426 | _INT_10 \ 427 | " pop ebp " \ 428 | " pop es " \ 429 | /* modify exact [ ax bh cx dl ] */ \ 430 | modify exact [ ax ebx ecx edx edi ] /* workaround bug in DOS4G */\ 431 | value [ cx ]; 432 | 433 | extern void BIOSEGAChrSet( unsigned_8 vidroutine ); 434 | #pragma aux BIOSEGAChrSet = \ 435 | " push ebp " \ 436 | " mov ah, 11h " \ 437 | " mov bl, 0 " \ 438 | _INT_10 \ 439 | " pop ebp " \ 440 | parm [ al ] \ 441 | modify exact [ ah bl ]; 442 | 443 | extern void _ega_write( unsigned_16, unsigned_8, unsigned_8 ); 444 | #pragma aux _ega_write = \ 445 | " out dx, ax " \ 446 | parm [ dx ] [ al ] [ ah ] \ 447 | modify exact [ ]; 448 | 449 | extern unsigned_8 _vga_read( unsigned_16, unsigned_8 ); 450 | #pragma aux _vga_read = \ 451 | " out dx, al ", \ 452 | " inc dx ", \ 453 | " in al, dx " \ 454 | parm [ dx ] [ al ] \ 455 | modify exact [ al dx ]; 456 | 457 | extern void _disablev( unsigned_16 ); 458 | #pragma aux _disablev = \ 459 | " again: " \ 460 | " in al, dx ", \ 461 | " test al, 8 ", \ 462 | " je again ", \ 463 | " mov dx, 3c0h ", \ 464 | " mov al, 11h ", \ 465 | " out dx, al ", \ 466 | " mov al, 0 ", \ 467 | " out dx, al " \ 468 | parm [ dx ] \ 469 | modify exact [ al dx ]; 470 | 471 | extern void _enablev( unsigned_16 ); 472 | #pragma aux _enablev = \ 473 | " again: " \ 474 | " in al, dx ", \ 475 | " test al, 8 ", \ 476 | " je again ", \ 477 | " mov dx, 3c0h ", \ 478 | " mov al, 31h ", \ 479 | " out dx, al ", \ 480 | " mov al, 0 ", \ 481 | " out dx, al " \ 482 | parm [ dx ] \ 483 | modify exact [ al dx ]; 484 | 485 | extern unsigned_16 _vidstatesize( unsigned_16 requestedstate ); 486 | #if 0 /* japheth. use VESA functions */ 487 | #pragma aux _vidstatesize = \ 488 | " mov ax, 1c00h " \ 489 | _INT_10 \ 490 | " cmp al, 1ch " \ 491 | " je end " \ 492 | " mov bx, 0 " \ 493 | " end: " \ 494 | parm [ cx ] \ 495 | modify exact [ ax bx ] \ 496 | value [ bx ]; 497 | #else 498 | #pragma aux _vidstatesize = \ 499 | " mov ax, 4F04h " \ 500 | " mov dl, 0 " \ 501 | " mov cx, 0fh " \ 502 | _INT_10 \ 503 | " cmp ax, 4Fh " \ 504 | " je end " \ 505 | " mov bx, 0 " \ 506 | " end: " \ 507 | parm [ cx ] \ 508 | modify exact [ ax bx ] \ 509 | value [ bx ]; 510 | #endif 511 | 512 | extern void Fillb( void __far *dst, unsigned_8 value, unsigned_16 count ); 513 | #pragma aux Fillb = \ 514 | "db 0x65" \ 515 | " rep stosb " \ 516 | parm [ gs edi ] [ al ] [ ecx ] \ 517 | modify exact [ edi ecx ]; 518 | --------------------------------------------------------------------------------