Release 950706
Wed Jul 5 19:06:35 1995 Alexandre Julliard <julliard@sunsite.unc.edu>
* [controls/scroll.c]
Fixed drawing bug that caused part of a non-client scroll bar
to be painted even when the scroll-bar was hidden.
* [debugger/break.c] [debugger/dbg.y]
Rewrote breakpoint handling to work in 16-bit mode.
Implemented single-stepping ('step' and 'next' instructions).
* [debugger/debug.l]
Format specifier is now a separate token.
Entering an empty line at the debugger prompt causes the previous
command to be repeated, like under gdb.
* [debugger/debug.l] [debugger/registers.c]
Differentiate 16-bit and 32-bit registers without taking current
mode into account ($eax is always 32-bit, $ax always 16-bit).
* [debugger/stack.c]
Fixed stack information routines to differentiate between 16-bit
and 32-bit stacks.
* [loader/task.c]
Option -debug now sets a breakpoint at the first instruction of
every loaded task.
* [miscemu/instr.c]
Added handling of lock, repe and repne prefixes.
* [objects/dib.c]
Changed StretchDIBits() to do the correct thing, even if it's still
not really optimal.
* [windows/graphics.c]
Fixes in RoundRect(), thanks to Babak Masalehdan.
* [windows/message.c]
Tried to fix mouse event handling with respect to disabled
windows.
* [windows/painting.c]
Clear WIN_NEEDS_NCPAINT flag before sending WM_NCPAINT to avoid
infinite loops.
* [windows/win.c]
Fixed IsWindowVisible() to return FALSE when one of the parent
windows is hidden.
Sat Jul 1 22:08:21 1995 Martin von Loewis <loewis@informatik.hu-berlin.de>
* [if1632/compobj.spec][misc/compobj.c]
CoGetMalloc: New function
Added relay entries for COMPOBJ ordinals above 100
CoInitialize: Changed parameter to DWORD
* [if1632/ole2.spec]
Exported implementation of OleBuildVersion
* [if1632/ole2disp.spec][misc/ole2disp.c][misc/Imakefile]
ole2disp.c: New file
SysAllocString, SysReallocString, SysAllocStringLen,
SysReAllocStringLen, SysFreeString, SysStringLen: new functions
* [if1632/ole2nls.spec][include/winnls.h][misc/ole2nls.c]
CompareStringA: New function
Thu Jun 29 19:42:02 1995 Marcus Meissner <msmeissn@faui01.informatik.uni-erlangen.de>
* [objects/font.c] [if1632/gdi.spec]
New stubs for CreateScalableFontResource, GetGlyphOutline.
Thu Jun 29 13:47:08 GMT 1995 Göran Thyni (goran@norrsken.bildbasen.se)
* [misc/commdlg.c]
Extensive changes and bug fixes to FileDialog handling,
behaves more like native Windows.
Wed Jun 28 13:04:44 1995 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
* [controls/listbox.c] [controls/combo.c]
Some minor optimizations.
* [memory/local.c]
LOCAL_FindFreeBlock(): Never use the last one.
* [memory/global.c]
GlobalReAlloc(): GMEM_MODIFY must not be ignored when size==0.
* [misc/file.c]
read() returns an error when length==0. This is not what Windows
programs expect, so pay attention to this in _lread(). Changed this
in _lwrite(), _hread(), _hwrite(), too.
* [loader/resource.c]
LoadIcon(): Ignore bih->biSizeImage, some icons have wrong values in
there.
* [if1632/shell.spec] [misc/shell.c]
Wrong spec file entries caused havoc: HKEY has 32 bit, not 16.
Accept some more combinations of parameters in the Reg..() functions.
* [if1632/toolhelp.spec]
Make InterruptRegister() and InterruptUnregister() return false.
* [windows/hook.c]
CallNextHookEx() used to crash when called with a null hhook. Fixed.
Wed Jun 28 10:14:34 1995 Martin von Loewis <martin@informatik.hu-berlin.de>
* [include/neexe.h][loader/ne_image.c]
NE_LoadSegment: Detect iterated segments
* [misc/ole2nls.c]
LOCALE_SLONGDATE: fixed typo
* [miscemu/int5c.c]
Reordered include files to avoid conflicts with Linux libc.5.1
* [rc/winerc.c]
Added -b option to process binary resource files into C arrays
* [include/callback.h]
CallWndProc: Added dummy ds parameter for libwine
* [include/gdi.h][include/user.h]
USER_HEAP_ALLOC, GDI_HEAP_ALLOC: dropped flags parameter
* [include/ldt.h][include/stackframe.h]
defined segment conversion macros for libwine
* [misc/atom.c]
Defined USER_HeapSel for libwine
* [misc/main.c]
Disable -dll option for libwine
* [misc/user.c]
removed GetFreeSystemResources, SystemHeapInfo from libwine for now
* [toolkit/heap.c]
fixed LocalLock prototype
* [toolkit/sup.c]
sync'ed load_mz_header, load_ne_header with structures
* [toolkit/winmain.c]
Disabled resource DLLs for libwine for now
Mon Jun 26 19:30:24 1995 Hans de Graaff (graaff@twi72.twi.tudelft.nl)
* [misc/main.c]
Fixed -enhanced option to report a 386 CPU instead of a 286.
Fri Jun 23 23:18:25 1995 Marcus Meissner <msmeissn@faui01.informatik.uni-erlangen.de>
* [misc/dos_fs.c]
Remove maximum open dosdirent limit (fixing the winfile.exe
problem) by using telldir()/seekdir().
Fri Jun 23 13:42:25 1995 Hans de Graaff (graaff@twi72.twi.tudelft.nl)
* [misc/profile.c]
Fixed problem parsing empty lines within sections in .ini files.
diff --git a/debugger/break.c b/debugger/break.c
index 711c495..e143669 100644
--- a/debugger/break.c
+++ b/debugger/break.c
@@ -1,3 +1,9 @@
+/*
+ * Debugger break-points handling
+ *
+ * Copyright 1994 Martin von Loewis
+ * Copyright 1995 Alexandre Julliard
+ */
#include <stdio.h>
#include <stdlib.h>
@@ -5,100 +11,42 @@
#ifdef linux
#include <sys/utsname.h>
#endif
-#include <windows.h>
-#include "db_disasm.h"
+#include "windows.h"
+#include "debugger.h"
-#define N_BP 25
+#define INT3 0xcc /* int 3 opcode */
+#define STEP_FLAG 0x100 /* single-step flag */
-extern int dbg_mode;
+#define MAX_BREAKPOINTS 25
-struct wine_bp{
- unsigned long addr;
- unsigned long next_addr;
- char in_use;
- char enabled;
- unsigned char databyte;
-};
-
-static struct wine_bp wbp[N_BP] = {{0,},};
-
-static int current_bp = -1;
-static int cont_mode=0; /* 0 - continuous execution
- 1 - advancing after breakpoint
- 2 - single step - not implemented
- */
-
-void info_break(void)
+typedef struct
{
- int j;
- fprintf(stderr,"Breakpoint status\n");
- for(j=0; j<N_BP; j++)
- if(wbp[j].in_use)
- fprintf(stderr,"%d: %c %8lx\n", j, (wbp[j].enabled ? 'y' : 'n'),
- wbp[j].addr);
-}
+ unsigned int segment;
+ unsigned int addr;
+ BYTE addrlen;
+ BYTE opcode;
+ BOOL enabled;
+ BOOL in_use;
+} BREAKPOINT;
-void disable_break(int bpnum)
+static BREAKPOINT breakpoints[MAX_BREAKPOINTS] = { { 0, }, };
+
+static int next_bp = 1; /* breakpoint 0 is reserved for step-over */
+
+
+/***********************************************************************
+ * DEBUG_ChangeOpcode
+ *
+ * Change the opcode at segment:addr.
+ */
+static void DEBUG_SetOpcode( unsigned int segment, unsigned int addr, BYTE op )
{
- if(bpnum >= N_BP || bpnum < 0)
- fprintf(stderr,"Breakpoint number out of range\n");
-
- wbp[bpnum].enabled = 0;
-}
-
-void enable_break(int bpnum)
-{
- if(bpnum >= N_BP || bpnum < 0)
- fprintf(stderr,"Breakpoint number out of range\n");
-
- wbp[bpnum].enabled = 1;
-}
-
-void add_break(unsigned long addr)
-{
- int j;
- for(j=0; j<N_BP; j++)
- if(!wbp[j].in_use)
- {
- wbp[j].in_use = 1;
- wbp[j].enabled = 1;
- wbp[j].addr = addr;
- wbp[j].next_addr = 0;
- return;
- }
- fprintf(stderr,"No more breakpoints\n");
-}
-
-static void bark()
-{
- static int barked=0;
- if(barked)return;
- barked=1;
- perror("Sorry, can't set break point");
-#ifdef linux
- {struct utsname buf;
- uname(&buf);
- if(strcmp(buf.sysname,"Linux")==0)
- { if(strcmp(buf.release,"1.1.62")<0)
- fprintf(stderr,"Your current Linux release is %s. "
- "You should upgrade to 1.1.62 or higher\n"
- "Alternatively, in /usr/src/linux/fs/exec.c,"
- " change MAP_SHARED to MAP_PRIVATE.\n", buf.release);
- } else
- fprintf(stderr,"Why did you compile for Linux, while your system is"
- " actually %s?\n",buf.sysname);
- }
-#endif
-}
-
-void insert_break(int flag)
-{
- unsigned char * pnt;
- int j;
-
- for(j=0; j<N_BP; j++)
- if(wbp[j].enabled)
- {
+ if (segment)
+ {
+ *(BYTE *)PTR_SEG_OFF_TO_LIN( segment, addr ) = op;
+ }
+ else /* 32-bit code, so we have to change the protection first */
+ {
/* There are a couple of problems with this. On Linux prior to
1.1.62, this call fails (ENOACCESS) due to a bug in fs/exec.c.
This code is currently not tested at all on BSD.
@@ -108,54 +56,221 @@
Not that portability matters, this code is i386 only anyways...
How do I get the old protection in order to restore it later on?
*/
- if(mprotect((caddr_t)(wbp[j].addr & (~4095)), 4096,
- PROT_READ|PROT_WRITE|PROT_EXEC) == -1){
- bark();
+ if (mprotect((caddr_t)(addr & (~4095)), 4096,
+ PROT_READ|PROT_WRITE|PROT_EXEC) == -1)
+ {
+ perror( "Can't set break point" );
return;
}
- pnt = (unsigned char *) wbp[j].addr;
- if(flag) {
- wbp[j].databyte = *pnt;
- *pnt = 0xcc; /* Change to an int 3 instruction */
- } else {
- *pnt = wbp[j].databyte;
- }
- mprotect((caddr_t)(wbp[j].addr & ~4095), 4096, PROT_READ|PROT_EXEC);
- }
-}
-
-/* Get the breakpoint number that we broke upon */
-int get_bpnum(unsigned int addr)
-{
- int j;
-
- for(j=0; j<N_BP; j++)
- if(wbp[j].enabled)
- if(wbp[j].addr == addr) return j;
-
- return -1;
-}
-
-void toggle_next(int num)
-{
- unsigned int addr;
- addr=wbp[num].addr;
- if(wbp[num].next_addr == 0)
- wbp[num].next_addr = db_disasm( 0, addr, (dbg_mode == 16) );
- wbp[num].addr=wbp[num].next_addr;
- wbp[num].next_addr=addr;
-}
-
-int should_continue(int bpnum)
-{
- if(bpnum<0)return 0;
- toggle_next(bpnum);
- if(bpnum==current_bp){
- current_bp=-1;
- cont_mode=0;
- return 1;
+ *(BYTE *)addr = op;
+ mprotect((caddr_t)(addr & ~4095), 4096, PROT_READ|PROT_EXEC);
}
- cont_mode=1;
- current_bp=bpnum;
- return 0;
+}
+
+
+/***********************************************************************
+ * DEBUG_SetBreakpoints
+ *
+ * Set or remove all the breakpoints.
+ */
+void DEBUG_SetBreakpoints( BOOL set )
+{
+ int i;
+
+ for (i = 0; i < MAX_BREAKPOINTS; i++)
+ {
+ if (breakpoints[i].in_use && breakpoints[i].enabled)
+ DEBUG_SetOpcode( breakpoints[i].segment, breakpoints[i].addr,
+ set ? INT3 : breakpoints[i].opcode );
+ }
+}
+
+
+/***********************************************************************
+ * DEBUG_FindBreakpoint
+ *
+ * Find the breakpoint for a given address. Return the breakpoint
+ * number or -1 if none.
+ */
+int DEBUG_FindBreakpoint( unsigned int segment, unsigned int addr )
+{
+ int i;
+
+ for (i = 0; i < MAX_BREAKPOINTS; i++)
+ {
+ if (breakpoints[i].in_use && breakpoints[i].enabled &&
+ breakpoints[i].segment == segment && breakpoints[i].addr == addr)
+ return i;
+ }
+ return -1;
+}
+
+
+/***********************************************************************
+ * DEBUG_AddBreakpoint
+ *
+ * Add a breakpoint.
+ */
+void DEBUG_AddBreakpoint( unsigned int segment, unsigned int addr )
+{
+ int num;
+ BYTE *p;
+
+ if (segment == 0xffffffff) segment = CS;
+ if (segment == WINE_CODE_SELECTOR) segment = 0;
+
+ if (next_bp < MAX_BREAKPOINTS)
+ num = next_bp++;
+ else /* try to find an empty slot */
+ {
+ for (num = 1; num < MAX_BREAKPOINTS; num++)
+ if (!breakpoints[num].in_use) break;
+ if (num >= MAX_BREAKPOINTS)
+ {
+ fprintf( stderr, "Too many breakpoints. Please delete some.\n" );
+ return;
+ }
+ }
+ p = segment ? (BYTE *)PTR_SEG_OFF_TO_LIN( segment, addr ) : (BYTE *)addr;
+ breakpoints[num].segment = segment;
+ breakpoints[num].addr = addr;
+ breakpoints[num].addrlen = !segment ? 32 :
+ (GET_SEL_FLAGS(segment) & LDT_FLAGS_32BIT) ? 32 : 16;
+ breakpoints[num].opcode = *p;
+ breakpoints[num].enabled = TRUE;
+ breakpoints[num].in_use = TRUE;
+ fprintf( stderr, "Breakpoint %d at ", num );
+ print_address( segment, addr, breakpoints[num].addrlen );
+ fprintf( stderr, "\n" );
+}
+
+
+/***********************************************************************
+ * DEBUG_DelBreakpoint
+ *
+ * Delete a breakpoint.
+ */
+void DEBUG_DelBreakpoint( int num )
+{
+ if ((num <= 0) || (num >= next_bp) || !breakpoints[num].in_use)
+ {
+ fprintf( stderr, "Invalid breakpoint number %d\n", num );
+ return;
+ }
+ breakpoints[num].enabled = FALSE;
+ breakpoints[num].in_use = FALSE;
+}
+
+
+/***********************************************************************
+ * DEBUG_EnableBreakpoint
+ *
+ * Enable or disable a break point.
+ */
+void DEBUG_EnableBreakpoint( int num, BOOL enable )
+{
+ if ((num <= 0) || (num >= next_bp) || !breakpoints[num].in_use)
+ {
+ fprintf( stderr, "Invalid breakpoint number %d\n", num );
+ return;
+ }
+ breakpoints[num].enabled = enable;
+}
+
+
+/***********************************************************************
+ * DEBUG_InfoBreakpoints
+ *
+ * Display break points information.
+ */
+void DEBUG_InfoBreakpoints(void)
+{
+ int i;
+
+ fprintf( stderr, "Breakpoints:\n" );
+ for (i = 1; i < next_bp; i++)
+ {
+ if (breakpoints[i].in_use)
+ {
+ fprintf( stderr, "%d: %c ", i, breakpoints[i].enabled ? 'y' : 'n');
+ print_address( breakpoints[i].segment, breakpoints[i].addr,
+ breakpoints[i].addrlen );
+ fprintf( stderr, "\n" );
+ }
+ }
+}
+
+
+/***********************************************************************
+ * DEBUG_ShouldContinue
+ *
+ * Determine if we should continue execution after a SIGTRAP signal when
+ * executing in the given mode.
+ */
+BOOL DEBUG_ShouldContinue( struct sigcontext_struct *context,
+ enum exec_mode mode )
+{
+ unsigned int segment, addr;
+ int bpnum;
+
+ /* If not single-stepping, back up over the int3 instruction */
+ if (!(EFL & STEP_FLAG)) EIP--;
+
+ segment = (CS == WINE_CODE_SELECTOR) ? 0 : CS;
+ addr = EIP;
+ bpnum = DEBUG_FindBreakpoint( segment, addr );
+ breakpoints[0].enabled = 0; /* disable the step-over breakpoint */
+
+ if ((bpnum != 0) && (bpnum != -1))
+ {
+ fprintf( stderr, "Stopped on breakpoint %d at ", bpnum );
+ print_address( breakpoints[bpnum].segment, breakpoints[bpnum].addr,
+ breakpoints[bpnum].addrlen );
+ fprintf( stderr, "\n" );
+ return FALSE;
+ }
+ /* no breakpoint, continue if in continuous mode */
+ return (mode == EXEC_CONT);
+}
+
+
+/***********************************************************************
+ * DEBUG_RestartExecution
+ *
+ * Set the breakpoints to the correct state to restart execution
+ * in the given mode.
+ */
+void DEBUG_RestartExecution( struct sigcontext_struct *context,
+ enum exec_mode mode, int instr_len )
+{
+ unsigned int segment, addr;
+
+ segment = (CS == WINE_CODE_SELECTOR) ? 0 : CS;
+ addr = EIP;
+
+ if (DEBUG_FindBreakpoint( segment, addr ) != -1)
+ mode = EXEC_STEP_INSTR; /* If there's a breakpoint, skip it */
+
+ switch(mode)
+ {
+ case EXEC_CONT: /* Continuous execution */
+ EFL &= ~STEP_FLAG;
+ DEBUG_SetBreakpoints( TRUE );
+ break;
+
+ case EXEC_STEP_OVER: /* Stepping over a call */
+ EFL &= ~STEP_FLAG;
+ breakpoints[0].segment = segment;
+ breakpoints[0].addr = addr + instr_len;
+ breakpoints[0].enabled = TRUE;
+ breakpoints[0].in_use = TRUE;
+ breakpoints[0].opcode = segment ?
+ *(BYTE *)PTR_SEG_OFF_TO_LIN(segment,addr+instr_len) : *(BYTE *)addr;
+ DEBUG_SetBreakpoints( TRUE );
+ break;
+
+ case EXEC_STEP_INSTR: /* Single-stepping an instruction */
+ EFL |= STEP_FLAG;
+ break;
+ }
}