Large-scale renaming of all Win32 functions and types to use the
[wine.git] / debugger / memory.c
blobc9e69e32ad5aed43f027e6a7545e64eb5b3aff83
1 /*
2 * Debugger memory handling
4 * Copyright 1993 Eric Youngdale
5 * Copyright 1995 Alexandre Julliard
6 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include "wine/winbase16.h"
11 #include "debugger.h"
12 #include "miscemu.h"
15 /************************************************************
17 * Check if linear pointer in [addr, addr+size[
18 * read (rwflag == 1)
19 * or
20 * write (rwflag == 0)
21 ************************************************************/
23 #if defined(linux) || defined(__FreeBSD__) || defined(__OpenBSD__)
24 BOOL DEBUG_checkmap_bad( const char *addr, size_t size, int rwflag)
26 FILE *fp;
27 char buf[80]; /* 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"
58 #endif
61 #ifdef linux
62 if (!(fp = fopen("/proc/self/maps", "r")))
63 #else
64 if (!(fp = fopen("/proc/curproc/map", "r")))
65 #endif
66 return FALSE;
68 while (fgets( buf, 79, fp)) {
69 #ifdef linux
70 sscanf(buf, "%x-%x %3s", (int *) &start, (int *) &end, prot);
71 #else
72 sscanf(buf, "%x %x %*d %*d %3s", (int *) &start, (int *) &end, prot);
73 #endif
74 if ( end <= addr)
75 continue;
76 if (start <= addr && addr+size < end) {
77 if (rwflag)
78 ret = (prot[0] != 'r'); /* test for reading */
79 else
80 ret = (prot[1] != 'w'); /* test for writing */
82 break;
84 fclose( fp);
85 return ret;
87 #else /* linux || FreeBSD */
88 /* FIXME: code needed for BSD et al. */
89 BOOL DEBUG_checkmap_bad(char *addr, size_t size, int rwflag)
91 return FALSE;
93 #endif /* linux || FreeBSD */
96 /***********************************************************************
97 * DEBUG_IsBadReadPtr
99 * Check if we are allowed to read memory at 'address'.
101 BOOL DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size )
103 if (!IS_SELECTOR_V86(address->seg))
104 if (address->seg) /* segmented addr */
106 if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
107 (WORD)address->seg ), size ))
108 return TRUE;
110 return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 1);
114 /***********************************************************************
115 * DEBUG_IsBadWritePtr
117 * Check if we are allowed to write memory at 'address'.
119 BOOL DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size )
121 if (!IS_SELECTOR_V86(address->seg))
122 if (address->seg) /* segmented addr */
124 /* Note: we use IsBadReadPtr here because we are */
125 /* always allowed to write to read-only segments */
126 if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
127 (WORD)address->seg ), size ))
128 return TRUE;
130 return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 0);
134 /***********************************************************************
135 * DEBUG_ReadMemory
137 * Read a memory value.
139 int DEBUG_ReadMemory( const DBG_ADDR *address )
141 DBG_ADDR addr = *address;
143 DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
144 if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return 0;
145 return *(int *)DBG_ADDR_TO_LIN( &addr );
149 /***********************************************************************
150 * DEBUG_WriteMemory
152 * Store a value in memory.
154 void DEBUG_WriteMemory( const DBG_ADDR *address, int value )
156 DBG_ADDR addr = *address;
158 DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
159 if (!DBG_CHECK_WRITE_PTR( &addr, sizeof(int) )) return;
160 *(int *)DBG_ADDR_TO_LIN( &addr ) = value;
164 /***********************************************************************
165 * DEBUG_ExamineMemory
167 * Implementation of the 'x' command.
169 void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
171 DBG_ADDR addr = * address;
172 unsigned int * dump;
173 int i;
174 unsigned char * pnt;
175 unsigned int seg2;
176 struct datatype * testtype;
177 unsigned short int * wdump;
179 DBG_FIX_ADDR_SEG( &addr, (format == 'i') ?
180 CS_reg(&DEBUG_context) : DS_reg(&DEBUG_context) );
183 * Dereference pointer to get actual memory address we need to be
184 * reading. We will use the same segment as what we have already,
185 * and hope that this is a sensible thing to do.
187 if( addr.type != NULL )
189 if( addr.type == DEBUG_TypeIntConst )
192 * We know that we have the actual offset stored somewhere
193 * else in 32-bit space. Grab it, and we
194 * should be all set.
196 seg2 = addr.seg;
197 addr.seg = 0;
198 addr.off = DEBUG_GetExprValue(&addr, NULL);
199 addr.seg = seg2;
201 else
203 if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
204 DEBUG_TypeDerefPointer(&addr, &testtype);
205 if( testtype != NULL || addr.type == DEBUG_TypeIntConst )
207 addr.off = DEBUG_GetExprValue(&addr, NULL);
211 else if (!addr.seg && !addr.off)
213 fprintf(stderr,"Invalid expression\n");
214 return;
217 if (format != 'i' && count > 1)
219 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
220 fprintf(stderr,": ");
223 pnt = DBG_ADDR_TO_LIN( &addr );
225 switch(format)
227 case 'u': {
228 WCHAR *ptr = (WCHAR*)pnt;
229 if (count == 1) count = 256;
230 while (count--)
232 if (!DBG_CHECK_READ_PTR( &addr, sizeof(WCHAR) )) return;
233 if (!*ptr) break;
234 addr.off++;
235 fputc( (char)*ptr++, stderr );
237 fprintf(stderr,"\n");
238 return;
240 case 's':
241 if (count == 1) count = 256;
242 while (count--)
244 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
245 if (!*pnt) break;
246 addr.off++;
247 fputc( *pnt++, stderr );
249 fprintf(stderr,"\n");
250 return;
252 case 'i':
253 while (count--)
255 DEBUG_PrintAddress( &addr, dbg_mode, TRUE );
256 fprintf(stderr,": ");
257 if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
258 DEBUG_Disasm( &addr, TRUE );
259 fprintf(stderr,"\n");
261 return;
262 case 'x':
263 dump = (unsigned int *)pnt;
264 for(i=0; i<count; i++)
266 if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
267 fprintf(stderr," %8.8x", *dump++);
268 addr.off += sizeof(int);
269 if ((i % 8) == 7)
271 fprintf(stderr,"\n");
272 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
273 fprintf(stderr,": ");
276 fprintf(stderr,"\n");
277 return;
279 case 'd':
280 dump = (unsigned int *)pnt;
281 for(i=0; i<count; i++)
283 if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
284 fprintf(stderr," %d", *dump++);
285 addr.off += sizeof(int);
286 if ((i % 8) == 7)
288 fprintf(stderr,"\n");
289 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
290 fprintf(stderr,": ");
293 fprintf(stderr,"\n");
294 return;
296 case 'w':
297 wdump = (unsigned short *)pnt;
298 for(i=0; i<count; i++)
300 if (!DBG_CHECK_READ_PTR( &addr, sizeof(short) )) return;
301 fprintf(stderr," %04x", *wdump++);
302 addr.off += sizeof(short);
303 if ((i % 8) == 7)
305 fprintf(stderr,"\n");
306 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
307 fprintf(stderr,": ");
310 fprintf(stderr,"\n");
311 return;
313 case 'c':
314 for(i=0; i<count; i++)
316 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
317 if(*pnt < 0x20)
319 fprintf(stderr," ");
320 pnt++;
322 else fprintf(stderr," %c", *pnt++);
323 addr.off++;
324 if ((i % 32) == 31)
326 fprintf(stderr,"\n");
327 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
328 fprintf(stderr,": ");
331 fprintf(stderr,"\n");
332 return;
334 case 'b':
335 for(i=0; i<count; i++)
337 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
338 fprintf(stderr," %02x", (*pnt++) & 0xff);
339 addr.off++;
340 if ((i % 16) == 15)
342 fprintf(stderr,"\n");
343 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
344 fprintf(stderr,": ");
347 fprintf(stderr,"\n");
348 return;