- new internal interface for item manipulation (cut/paste/new folder/delete/rename)
[wine.git] / debugger / memory.c
blob63d1d52d02e263ecab13612146f51ad3f9b42a53
1 /*
2 * Debugger memory handling
4 * Copyright 1993 Eric Youngdale
5 * Copyright 1995 Alexandre Julliard
6 */
8 #include "config.h"
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include "wine/winbase16.h"
12 #include "debugger.h"
13 #include "miscemu.h"
16 /************************************************************
18 * Check if linear pointer in [addr, addr+size[
19 * read (rwflag == 1)
20 * or
21 * write (rwflag == 0)
22 ************************************************************/
24 BOOL DEBUG_checkmap_bad( const char *addr, size_t size, int rwflag)
26 FILE *fp;
27 char buf[200]; /* temporary line buffer */
28 char prot[5]; /* protection string */
29 char *start, *end;
30 int ret = TRUE;
32 #ifdef linux
33 /*
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
41 ...
42 start end perm ??? major:minor inode
44 Only permissions start and end are used here
46 #else
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
56 COW = "copy on write"
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
68 #endif
71 if (!(fp = fopen("/proc/self/maps","r")) &&
72 !(fp = fopen("/proc/curproc/map","r"))
74 return FALSE;
76 #ifdef __FreeBSD__
78 * *FOO* read(2) less than length of /proc/.../map fails with EFBIG
80 * $ dd bs=256 </proc/curproc/map
81 * dd: stdin: File too large
82 * 0+0 records in
83 * 0+0 records out
84 * 0 bytes transferred in 0.001595 secs (0 bytes/sec)
86 setvbuf(fp, (char *)NULL, _IOFBF, 0x4000);
87 #endif
88 while (fgets( buf, sizeof(buf)-1, fp)) {
89 #ifdef linux
90 sscanf(buf, "%x-%x %3s", (int *) &start, (int *) &end, prot);
91 #else
92 sscanf(buf, "%x %x %*d %*d %3s", (int *) &start, (int *) &end, prot);
93 if (prot[0]!='r' && prot[0]!='-') /* FreeBSD 3.0 format */
94 sscanf(buf, "%x %x %*d %*d %*d %3s", (int *) &start, (int *) &end, prot);
95 #endif
96 if ( end <= addr)
97 continue;
98 if (start <= addr && addr+size <= end) {
99 if (rwflag)
100 ret = (prot[0] != 'r'); /* test for reading */
101 else
102 ret = (prot[1] != 'w'); /* test for writing */
104 break;
106 fclose( fp);
107 return ret;
111 /***********************************************************************
112 * DEBUG_IsBadReadPtr
114 * Check if we are allowed to read memory at 'address'.
116 BOOL DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size )
118 #ifdef __i386__
119 if (!IS_SELECTOR_V86(address->seg))
120 if (address->seg) /* segmented addr */
122 if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
123 (WORD)address->seg ), size ))
124 return TRUE;
126 #endif
127 return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 1);
131 /***********************************************************************
132 * DEBUG_IsBadWritePtr
134 * Check if we are allowed to write memory at 'address'.
136 BOOL DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size )
138 #ifdef __i386__
139 if (!IS_SELECTOR_V86(address->seg))
140 if (address->seg) /* segmented addr */
142 /* Note: we use IsBadReadPtr here because we are */
143 /* always allowed to write to read-only segments */
144 if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
145 (WORD)address->seg ), size ))
146 return TRUE;
148 #endif
149 return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 0);
153 /***********************************************************************
154 * DEBUG_ReadMemory
156 * Read a memory value.
158 int DEBUG_ReadMemory( const DBG_ADDR *address )
160 DBG_ADDR addr = *address;
162 DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
163 if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return 0;
164 return *(int *)DBG_ADDR_TO_LIN( &addr );
168 /***********************************************************************
169 * DEBUG_WriteMemory
171 * Store a value in memory.
173 void DEBUG_WriteMemory( const DBG_ADDR *address, int value )
175 DBG_ADDR addr = *address;
177 DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
178 if (!DBG_CHECK_WRITE_PTR( &addr, sizeof(int) )) return;
179 *(int *)DBG_ADDR_TO_LIN( &addr ) = value;
183 /***********************************************************************
184 * DEBUG_ExamineMemory
186 * Implementation of the 'x' command.
188 void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
190 DBG_ADDR addr = * address;
191 unsigned int * dump;
192 int i;
193 unsigned char * pnt;
194 unsigned int seg2;
195 struct datatype * testtype;
196 unsigned short int * wdump;
198 DBG_FIX_ADDR_SEG( &addr, (format == 'i') ?
199 CS_reg(&DEBUG_context) : DS_reg(&DEBUG_context) );
202 * Dereference pointer to get actual memory address we need to be
203 * reading. We will use the same segment as what we have already,
204 * and hope that this is a sensible thing to do.
206 if( addr.type != NULL )
208 if( addr.type == DEBUG_TypeIntConst )
211 * We know that we have the actual offset stored somewhere
212 * else in 32-bit space. Grab it, and we
213 * should be all set.
215 seg2 = addr.seg;
216 addr.seg = 0;
217 addr.off = DEBUG_GetExprValue(&addr, NULL);
218 addr.seg = seg2;
220 else
222 if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
223 DEBUG_TypeDerefPointer(&addr, &testtype);
224 if( testtype != NULL || addr.type == DEBUG_TypeIntConst )
226 addr.off = DEBUG_GetExprValue(&addr, NULL);
230 else if (!addr.seg && !addr.off)
232 fprintf(stderr,"Invalid expression\n");
233 return;
236 if (format != 'i' && count > 1)
238 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
239 fprintf(stderr,": ");
242 pnt = DBG_ADDR_TO_LIN( &addr );
244 switch(format)
246 case 'u': {
247 WCHAR *ptr = (WCHAR*)pnt;
248 if (count == 1) count = 256;
249 while (count--)
251 if (!DBG_CHECK_READ_PTR( &addr, sizeof(WCHAR) )) return;
252 if (!*ptr) break;
253 addr.off++;
254 fputc( (char)*ptr++, stderr );
256 fprintf(stderr,"\n");
257 return;
259 case 's':
260 if (count == 1) count = 256;
261 while (count--)
263 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
264 if (!*pnt) break;
265 addr.off++;
266 fputc( *pnt++, stderr );
268 fprintf(stderr,"\n");
269 return;
271 case 'i':
272 while (count--)
274 DEBUG_PrintAddress( &addr, dbg_mode, TRUE );
275 fprintf(stderr,": ");
276 if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
277 DEBUG_Disasm( &addr, TRUE );
278 fprintf(stderr,"\n");
280 return;
281 case 'x':
282 dump = (unsigned int *)pnt;
283 for(i=0; i<count; i++)
285 if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
286 fprintf(stderr," %8.8x", *dump++);
287 addr.off += sizeof(int);
288 if ((i % 4) == 3)
290 fprintf(stderr,"\n");
291 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
292 fprintf(stderr,": ");
295 fprintf(stderr,"\n");
296 return;
298 case 'd':
299 dump = (unsigned int *)pnt;
300 for(i=0; i<count; i++)
302 if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
303 fprintf(stderr," %10d", *dump++);
304 addr.off += sizeof(int);
305 if ((i % 4) == 3)
307 fprintf(stderr,"\n");
308 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
309 fprintf(stderr,": ");
312 fprintf(stderr,"\n");
313 return;
315 case 'w':
316 wdump = (unsigned short *)pnt;
317 for(i=0; i<count; i++)
319 if (!DBG_CHECK_READ_PTR( &addr, sizeof(short) )) return;
320 fprintf(stderr," %04x", *wdump++);
321 addr.off += sizeof(short);
322 if ((i % 8) == 7)
324 fprintf(stderr,"\n");
325 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
326 fprintf(stderr,": ");
329 fprintf(stderr,"\n");
330 return;
332 case 'c':
333 for(i=0; i<count; i++)
335 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
336 if(*pnt < 0x20)
338 fprintf(stderr," ");
339 pnt++;
341 else fprintf(stderr," %c", *pnt++);
342 addr.off++;
343 if ((i % 32) == 31)
345 fprintf(stderr,"\n");
346 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
347 fprintf(stderr,": ");
350 fprintf(stderr,"\n");
351 return;
353 case 'b':
354 for(i=0; i<count; i++)
356 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
357 fprintf(stderr," %02x", (*pnt++) & 0xff);
358 addr.off++;
359 if ((i % 16) == 15)
361 fprintf(stderr,"\n");
362 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
363 fprintf(stderr,": ");
366 fprintf(stderr,"\n");
367 return;