No longer directly accessing debuggee memory.
Execution context (mode, steps...) are now linked to a thread.
Removed some X11 crst hacks.
Rewrote info/walk commands.
Removed direct debugger invocation code (and moved the rest to the new
winedbg.c file).
diff --git a/debugger/memory.c b/debugger/memory.c
index 63d1d52..07759ee 100644
--- a/debugger/memory.c
+++ b/debugger/memory.c
@@ -8,147 +8,126 @@
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
-#include "wine/winbase16.h"
+#include <string.h>
#include "debugger.h"
-#include "miscemu.h"
+#include "winbase.h"
-
-/************************************************************
- *
- * Check if linear pointer in [addr, addr+size[
- * read (rwflag == 1)
- * or
- * write (rwflag == 0)
- ************************************************************/
-
-BOOL DEBUG_checkmap_bad( const char *addr, size_t size, int rwflag)
-{
- FILE *fp;
- char buf[200]; /* temporary line buffer */
- char prot[5]; /* protection string */
- char *start, *end;
- int ret = TRUE;
-
-#ifdef linux
- /*
- The entries in /proc/self/maps are of the form:
- 08000000-08002000 r-xp 00000000 03:41 2361
- 08002000-08003000 rw-p 00001000 03:41 2361
- 08003000-08005000 rwxp 00000000 00:00 0
- 40000000-40005000 r-xp 00000000 03:41 67219
- 40005000-40006000 rw-p 00004000 03:41 67219
- 40006000-40007000 rw-p 00000000 00:00 0
- ...
- start end perm ??? major:minor inode
-
- Only permissions start and end are used here
- */
-#else
-/*
- % cat /proc/curproc/map
- start end resident private perm type
- 0x1000 0xe000 12 0 r-x COW vnode
- 0xe000 0x10000 2 2 rwx COW vnode
- 0x10000 0x27000 4 4 rwx default
- 0x800e000 0x800f000 1 1 rw- default
- 0xefbde000 0xefbfe000 1 1 rwx default
-
- COW = "copy on write"
-
-
- % cat /proc/curproc/map on FreeBSD 3.0
- start end ? ? ? prot ? ? ? ? ? ?
- 0x8048000 0x8054000 12 14 114770 r-x 2 1 0x0 COW NC vnode
- 0x8054000 0x8055000 1 0 166664 rwx 1 0 0x2180 COW NNC vnode
- 0x8055000 0x806a000 5 0 166662 rwx 1 0 0x2180 NCOW NNC default
- 0x28054000 0x28055000 1 0 166666 rwx 1 0 0x2180 NCOW NNC default
- 0xefbde000 0xefbfe000 1 0 166663 rwx 1 0 0x2180 NCOW NNC default
-
-*/
-#endif
-
-
- if (!(fp = fopen("/proc/self/maps","r")) &&
- !(fp = fopen("/proc/curproc/map","r"))
- )
- return FALSE;
-
-#ifdef __FreeBSD__
- /*
- * *FOO* read(2) less than length of /proc/.../map fails with EFBIG
- *
- * $ dd bs=256 </proc/curproc/map
- * dd: stdin: File too large
- * 0+0 records in
- * 0+0 records out
- * 0 bytes transferred in 0.001595 secs (0 bytes/sec)
- */
- setvbuf(fp, (char *)NULL, _IOFBF, 0x4000);
-#endif
- while (fgets( buf, sizeof(buf)-1, fp)) {
-#ifdef linux
- sscanf(buf, "%x-%x %3s", (int *) &start, (int *) &end, prot);
-#else
- sscanf(buf, "%x %x %*d %*d %3s", (int *) &start, (int *) &end, prot);
- if (prot[0]!='r' && prot[0]!='-') /* FreeBSD 3.0 format */
- sscanf(buf, "%x %x %*d %*d %*d %3s", (int *) &start, (int *) &end, prot);
-#endif
- if ( end <= addr)
- continue;
- if (start <= addr && addr+size <= end) {
- if (rwflag)
- ret = (prot[0] != 'r'); /* test for reading */
- else
- ret = (prot[1] != 'w'); /* test for writing */
- }
- break;
- }
- fclose( fp);
- return ret;
-}
-
-
-/***********************************************************************
- * DEBUG_IsBadReadPtr
- *
- * Check if we are allowed to read memory at 'address'.
- */
-BOOL DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size )
-{
#ifdef __i386__
- if (!IS_SELECTOR_V86(address->seg))
- if (address->seg) /* segmented addr */
- {
- if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
- (WORD)address->seg ), size ))
- return TRUE;
- }
-#endif
- return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 1);
-}
+#include "wine/winbase16.h"
+#define DBG_V86_MODULE(seg) ((seg)>>16)
+#define IS_SELECTOR_V86(seg) DBG_V86_MODULE(seg)
-/***********************************************************************
- * DEBUG_IsBadWritePtr
- *
- * Check if we are allowed to write memory at 'address'.
- */
-BOOL DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size )
+static void DEBUG_Die(const char* msg)
{
-#ifdef __i386__
- if (!IS_SELECTOR_V86(address->seg))
- if (address->seg) /* segmented addr */
- {
- /* Note: we use IsBadReadPtr here because we are */
- /* always allowed to write to read-only segments */
- if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
- (WORD)address->seg ), size ))
- return TRUE;
- }
-#endif
- return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 0);
+ fprintf(stderr, msg);
+ exit(1);
}
+void* DEBUG_XMalloc(size_t size)
+{
+ void *res = malloc(size ? size : 1);
+ if (res == NULL)
+ DEBUG_Die("Memory exhausted.\n");
+ memset(res, 0, size);
+ return res;
+}
+
+void* DEBUG_XReAlloc(void *ptr, size_t size)
+{
+ void* res = realloc(ptr, size);
+ if ((res == NULL) && size)
+ DEBUG_Die("Memory exhausted.\n");
+ return res;
+}
+
+char* DEBUG_XStrDup(const char *str)
+{
+ char *res = strdup(str);
+ if (!res)
+ DEBUG_Die("Memory exhausted.\n");
+ return res;
+}
+
+void DEBUG_FixAddress( DBG_ADDR *addr, DWORD def)
+{
+ if (addr->seg == 0xffffffff) addr->seg = def;
+ if (!IS_SELECTOR_V86(addr->seg) && DEBUG_IsSelectorSystem(addr->seg)) addr->seg = 0;
+}
+
+BOOL DEBUG_FixSegment( DBG_ADDR* addr )
+{
+ /* V86 mode ? */
+ if (DEBUG_context.EFlags & V86_FLAG) {
+ addr->seg |= (DWORD)(GetExePtr(GetCurrentTask())) << 16;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+DWORD DEBUG_ToLinear( const DBG_ADDR *addr )
+{
+ LDT_ENTRY le;
+
+ if (IS_SELECTOR_V86(addr->seg))
+ return DOSMEM_MemoryBase(DBG_V86_MODULE(addr->seg)) + (((addr->seg)&0xFFFF)<<4) + addr->off;
+ if (DEBUG_IsSelectorSystem(addr->seg))
+ return addr->off;
+
+ if (GetThreadSelectorEntry( DEBUG_CurrThread->handle, addr->seg, &le)) {
+ return (le.HighWord.Bits.BaseHi << 24) + (le.HighWord.Bits.BaseMid << 16) + le.BaseLow + addr->off;
+ }
+ return 0;
+}
+
+int DEBUG_GetSelectorType( WORD sel )
+{
+ LDT_ENTRY le;
+
+ if (sel == 0)
+ return 32;
+ if (IS_SELECTOR_V86(sel))
+ return 16;
+ if (GetThreadSelectorEntry( DEBUG_CurrThread->handle, sel, &le))
+ return le.HighWord.Bits.Default_Big ? 32 : 16;
+ /* selector doesn't exist */
+ return 0;
+}
+
+/* Determine if sel is a system selector (i.e. not managed by Wine) */
+BOOL DEBUG_IsSelectorSystem(WORD sel)
+{
+ return !(sel & 4) || (((sel & 0xFFFF) >> 3) < 17);
+}
+#endif /* __i386__ */
+
+void DEBUG_GetCurrentAddress( DBG_ADDR *addr )
+{
+ addr->type = NULL;
+#ifdef __i386__
+ addr->seg = DEBUG_context.SegCs;
+
+ if (!DEBUG_FixSegment( addr ) && DEBUG_IsSelectorSystem(addr->seg))
+ addr->seg = 0;
+ addr->off = DEBUG_context.Eip;
+#else
+ addr->seg = 0;
+ addr->off = 0;
+#endif
+}
+
+void DEBUG_InvalLinAddr( void* addr )
+{
+ DBG_ADDR address;
+
+ address.type = NULL;
+ address.seg = 0;
+ address.off = (unsigned long)addr;
+
+ fprintf(stderr,"*** Invalid address ");
+ DEBUG_PrintAddress(&address, DEBUG_CurrThread->dbg_mode, FALSE);
+ fprintf(stderr,"\n");
+}
/***********************************************************************
* DEBUG_ReadMemory
@@ -157,11 +136,15 @@
*/
int DEBUG_ReadMemory( const DBG_ADDR *address )
{
- DBG_ADDR addr = *address;
-
- DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
- if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return 0;
- return *(int *)DBG_ADDR_TO_LIN( &addr );
+ DBG_ADDR addr = *address;
+ void* lin;
+ int value;
+
+ DEBUG_FixAddress( &addr, DEBUG_context.SegDs );
+ lin = (void*)DEBUG_ToLinear( &addr );
+ if (!DEBUG_READ_MEM_VERBOSE(lin, &value, sizeof(value)))
+ value = 0;
+ return value;
}
@@ -172,11 +155,12 @@
*/
void DEBUG_WriteMemory( const DBG_ADDR *address, int value )
{
- DBG_ADDR addr = *address;
+ DBG_ADDR addr = *address;
+ void* lin;
- DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
- if (!DBG_CHECK_WRITE_PTR( &addr, sizeof(int) )) return;
- *(int *)DBG_ADDR_TO_LIN( &addr ) = value;
+ DEBUG_FixAddress( &addr, DEBUG_context.SegDs );
+ lin = (void*)DEBUG_ToLinear( &addr );
+ DEBUG_WRITE_MEM_VERBOSE(lin, &value, sizeof(value));
}
@@ -188,15 +172,14 @@
void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
{
DBG_ADDR addr = * address;
- unsigned int * dump;
int i;
unsigned char * pnt;
- unsigned int seg2;
struct datatype * testtype;
- unsigned short int * wdump;
- DBG_FIX_ADDR_SEG( &addr, (format == 'i') ?
- CS_reg(&DEBUG_context) : DS_reg(&DEBUG_context) );
+ DEBUG_FixAddress( &addr,
+ (format == 'i') ?
+ DEBUG_context.SegCs :
+ DEBUG_context.SegDs );
/*
* Dereference pointer to get actual memory address we need to be
@@ -212,15 +195,15 @@
* else in 32-bit space. Grab it, and we
* should be all set.
*/
- seg2 = addr.seg;
+ unsigned int seg2 = addr.seg;
addr.seg = 0;
addr.off = DEBUG_GetExprValue(&addr, NULL);
addr.seg = seg2;
}
else
{
- if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
- DEBUG_TypeDerefPointer(&addr, &testtype);
+ if (DEBUG_TypeDerefPointer(&addr, &testtype) == 0)
+ return;
if( testtype != NULL || addr.type == DEBUG_TypeIntConst )
{
addr.off = DEBUG_GetExprValue(&addr, NULL);
@@ -235,135 +218,71 @@
if (format != 'i' && count > 1)
{
- DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
+ DEBUG_PrintAddress( &addr, DEBUG_CurrThread->dbg_mode, FALSE );
fprintf(stderr,": ");
}
- pnt = DBG_ADDR_TO_LIN( &addr );
+ pnt = (void*)DEBUG_ToLinear( &addr );
switch(format)
{
case 'u': {
- WCHAR *ptr = (WCHAR*)pnt;
+ WCHAR wch;
if (count == 1) count = 256;
while (count--)
{
- if (!DBG_CHECK_READ_PTR( &addr, sizeof(WCHAR) )) return;
- if (!*ptr) break;
- addr.off++;
- fputc( (char)*ptr++, stderr );
+ if (!DEBUG_READ_MEM_VERBOSE(pnt, &wch, sizeof(wch)))
+ break;
+ pnt += sizeof(wch);
+ fputc( (char)wch, stderr );
}
fprintf(stderr,"\n");
return;
}
- case 's':
+ case 's': {
+ char ch;
+
if (count == 1) count = 256;
while (count--)
{
- if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
- if (!*pnt) break;
- addr.off++;
- fputc( *pnt++, stderr );
+ if (!DEBUG_READ_MEM_VERBOSE(pnt, &ch, sizeof(ch)))
+ break;
+ pnt++;
+ fputc( ch, stderr );
}
fprintf(stderr,"\n");
return;
-
+ }
case 'i':
while (count--)
{
- DEBUG_PrintAddress( &addr, dbg_mode, TRUE );
+ DEBUG_PrintAddress( &addr, DEBUG_CurrThread->dbg_mode, TRUE );
fprintf(stderr,": ");
- if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
DEBUG_Disasm( &addr, TRUE );
fprintf(stderr,"\n");
}
return;
- case 'x':
- dump = (unsigned int *)pnt;
- for(i=0; i<count; i++)
- {
- if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
- fprintf(stderr," %8.8x", *dump++);
- addr.off += sizeof(int);
- if ((i % 4) == 3)
- {
- fprintf(stderr,"\n");
- DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
- fprintf(stderr,": ");
- }
- }
- fprintf(stderr,"\n");
- return;
-
- case 'd':
- dump = (unsigned int *)pnt;
- for(i=0; i<count; i++)
- {
- if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
- fprintf(stderr," %10d", *dump++);
- addr.off += sizeof(int);
- if ((i % 4) == 3)
- {
- fprintf(stderr,"\n");
- DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
- fprintf(stderr,": ");
- }
- }
- fprintf(stderr,"\n");
- return;
-
- case 'w':
- wdump = (unsigned short *)pnt;
- for(i=0; i<count; i++)
- {
- if (!DBG_CHECK_READ_PTR( &addr, sizeof(short) )) return;
- fprintf(stderr," %04x", *wdump++);
- addr.off += sizeof(short);
- if ((i % 8) == 7)
- {
- fprintf(stderr,"\n");
- DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
- fprintf(stderr,": ");
- }
- }
- fprintf(stderr,"\n");
- return;
-
- case 'c':
- for(i=0; i<count; i++)
- {
- if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
- if(*pnt < 0x20)
- {
- fprintf(stderr," ");
- pnt++;
- }
- else fprintf(stderr," %c", *pnt++);
- addr.off++;
- if ((i % 32) == 31)
- {
- fprintf(stderr,"\n");
- DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
- fprintf(stderr,": ");
- }
- }
- fprintf(stderr,"\n");
- return;
-
- case 'b':
- for(i=0; i<count; i++)
- {
- if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
- fprintf(stderr," %02x", (*pnt++) & 0xff);
- addr.off++;
- if ((i % 16) == 15)
- {
- fprintf(stderr,"\n");
- DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
- fprintf(stderr,": ");
- }
- }
- fprintf(stderr,"\n");
- return;
+#define DO_DUMP2(_t,_l,_f,_vv) { \
+ _t _v; \
+ for(i=0; i<count; i++) { \
+ if (!DEBUG_READ_MEM_VERBOSE(pnt, &_v, sizeof(_t))) break; \
+ fprintf(stderr,_f,(_vv)); \
+ pnt += sizeof(_t); addr.off += sizeof(_t); \
+ if ((i % (_l)) == (_l)-1) { \
+ fprintf(stderr,"\n"); \
+ DEBUG_PrintAddress( &addr, DEBUG_CurrThread->dbg_mode, FALSE );\
+ fprintf(stderr,": ");\
+ } \
+ } \
+ fprintf(stderr,"\n"); \
+ } \
+ return
+#define DO_DUMP(_t,_l,_f) DO_DUMP2(_t,_l,_f,_v)
+
+ case 'x': DO_DUMP(int, 4, " %8.8x");
+ case 'd': DO_DUMP(unsigned int, 4, " %10d");
+ case 'w': DO_DUMP(unsigned short, 8, " %04x");
+ case 'c': DO_DUMP2(char, 32, " %c", (_v < 0x20) ? ' ' : _v);
+ case 'b': DO_DUMP2(char, 16, " %02x", (_v) & 0xff);
}
}