2 * Debugger memory handling
4 * Copyright 1993 Eric Youngdale
5 * Copyright 1995 Alexandre Julliard
11 #include "wine/winbase16.h"
16 /************************************************************
18 * Check if linear pointer in [addr, addr+size[
22 ************************************************************/
24 BOOL DEBUG_checkmap_bad( const char *addr, size_t size, int rwflag)
27 char buf[200]; /* temporary line buffer */
28 char prot[5]; /* protection string */
34 The entries in /proc/self/maps are of the form:
35 08000000-08002000 r-xp 00000000 03:41 2361
36 08002000-08003000 rw-p 00001000 03:41 2361
37 08003000-08005000 rwxp 00000000 00:00 0
38 40000000-40005000 r-xp 00000000 03:41 67219
39 40005000-40006000 rw-p 00004000 03:41 67219
40 40006000-40007000 rw-p 00000000 00:00 0
42 start end perm ??? major:minor inode
44 Only permissions start and end are used here
48 % cat /proc/curproc/map
49 start end resident private perm type
50 0x1000 0xe000 12 0 r-x COW vnode
51 0xe000 0x10000 2 2 rwx COW vnode
52 0x10000 0x27000 4 4 rwx default
53 0x800e000 0x800f000 1 1 rw- default
54 0xefbde000 0xefbfe000 1 1 rwx default
59 % cat /proc/curproc/map on FreeBSD 3.0
60 start end ? ? ? prot ? ? ? ? ? ?
61 0x8048000 0x8054000 12 14 114770 r-x 2 1 0x0 COW NC vnode
62 0x8054000 0x8055000 1 0 166664 rwx 1 0 0x2180 COW NNC vnode
63 0x8055000 0x806a000 5 0 166662 rwx 1 0 0x2180 NCOW NNC default
64 0x28054000 0x28055000 1 0 166666 rwx 1 0 0x2180 NCOW NNC default
65 0xefbde000 0xefbfe000 1 0 166663 rwx 1 0 0x2180 NCOW NNC default
71 if (!(fp = fopen("/proc/self/maps","r")) &&
72 !(fp = fopen("/proc/curproc/map","r"))
76 while (fgets( buf, sizeof(buf)-1, fp)) {
78 sscanf(buf, "%x-%x %3s", (int *) &start, (int *) &end, prot);
80 sscanf(buf, "%x %x %*d %*d %3s", (int *) &start, (int *) &end, prot);
81 if (prot[0]!='r' && prot[0]!='-') /* FreeBSD 3.0 format */
82 sscanf(buf, "%x %x %*d %*d %*d %3s", (int *) &start, (int *) &end, prot);
86 if (start <= addr && addr+size <= end) {
88 ret = (prot[0] != 'r'); /* test for reading */
90 ret = (prot[1] != 'w'); /* test for writing */
99 /***********************************************************************
102 * Check if we are allowed to read memory at 'address'.
104 BOOL DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size )
106 if (!IS_SELECTOR_V86(address->seg))
107 if (address->seg) /* segmented addr */
109 if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
110 (WORD)address->seg ), size ))
113 return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 1);
117 /***********************************************************************
118 * DEBUG_IsBadWritePtr
120 * Check if we are allowed to write memory at 'address'.
122 BOOL DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size )
124 if (!IS_SELECTOR_V86(address->seg))
125 if (address->seg) /* segmented addr */
127 /* Note: we use IsBadReadPtr here because we are */
128 /* always allowed to write to read-only segments */
129 if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
130 (WORD)address->seg ), size ))
133 return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 0);
137 /***********************************************************************
140 * Read a memory value.
142 int DEBUG_ReadMemory( const DBG_ADDR *address )
144 DBG_ADDR addr = *address;
146 DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
147 if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return 0;
148 return *(int *)DBG_ADDR_TO_LIN( &addr );
152 /***********************************************************************
155 * Store a value in memory.
157 void DEBUG_WriteMemory( const DBG_ADDR *address, int value )
159 DBG_ADDR addr = *address;
161 DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
162 if (!DBG_CHECK_WRITE_PTR( &addr, sizeof(int) )) return;
163 *(int *)DBG_ADDR_TO_LIN( &addr ) = value;
167 /***********************************************************************
168 * DEBUG_ExamineMemory
170 * Implementation of the 'x' command.
172 void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
174 DBG_ADDR addr = * address;
179 struct datatype * testtype;
180 unsigned short int * wdump;
182 DBG_FIX_ADDR_SEG( &addr, (format == 'i') ?
183 CS_reg(&DEBUG_context) : DS_reg(&DEBUG_context) );
186 * Dereference pointer to get actual memory address we need to be
187 * reading. We will use the same segment as what we have already,
188 * and hope that this is a sensible thing to do.
190 if( addr.type != NULL )
192 if( addr.type == DEBUG_TypeIntConst )
195 * We know that we have the actual offset stored somewhere
196 * else in 32-bit space. Grab it, and we
201 addr.off = DEBUG_GetExprValue(&addr, NULL);
206 if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
207 DEBUG_TypeDerefPointer(&addr, &testtype);
208 if( testtype != NULL || addr.type == DEBUG_TypeIntConst )
210 addr.off = DEBUG_GetExprValue(&addr, NULL);
214 else if (!addr.seg && !addr.off)
216 fprintf(stderr,"Invalid expression\n");
220 if (format != 'i' && count > 1)
222 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
223 fprintf(stderr,": ");
226 pnt = DBG_ADDR_TO_LIN( &addr );
231 WCHAR *ptr = (WCHAR*)pnt;
232 if (count == 1) count = 256;
235 if (!DBG_CHECK_READ_PTR( &addr, sizeof(WCHAR) )) return;
238 fputc( (char)*ptr++, stderr );
240 fprintf(stderr,"\n");
244 if (count == 1) count = 256;
247 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
250 fputc( *pnt++, stderr );
252 fprintf(stderr,"\n");
258 DEBUG_PrintAddress( &addr, dbg_mode, TRUE );
259 fprintf(stderr,": ");
260 if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
261 DEBUG_Disasm( &addr, TRUE );
262 fprintf(stderr,"\n");
266 dump = (unsigned int *)pnt;
267 for(i=0; i<count; i++)
269 if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
270 fprintf(stderr," %8.8x", *dump++);
271 addr.off += sizeof(int);
274 fprintf(stderr,"\n");
275 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
276 fprintf(stderr,": ");
279 fprintf(stderr,"\n");
283 dump = (unsigned int *)pnt;
284 for(i=0; i<count; i++)
286 if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
287 fprintf(stderr," %10d", *dump++);
288 addr.off += sizeof(int);
291 fprintf(stderr,"\n");
292 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
293 fprintf(stderr,": ");
296 fprintf(stderr,"\n");
300 wdump = (unsigned short *)pnt;
301 for(i=0; i<count; i++)
303 if (!DBG_CHECK_READ_PTR( &addr, sizeof(short) )) return;
304 fprintf(stderr," %04x", *wdump++);
305 addr.off += sizeof(short);
308 fprintf(stderr,"\n");
309 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
310 fprintf(stderr,": ");
313 fprintf(stderr,"\n");
317 for(i=0; i<count; i++)
319 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
325 else fprintf(stderr," %c", *pnt++);
329 fprintf(stderr,"\n");
330 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
331 fprintf(stderr,": ");
334 fprintf(stderr,"\n");
338 for(i=0; i<count; i++)
340 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
341 fprintf(stderr," %02x", (*pnt++) & 0xff);
345 fprintf(stderr,"\n");
346 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
347 fprintf(stderr,": ");
350 fprintf(stderr,"\n");