debug.h must be last, or we get ERR() macro problems again.
[wine/multimedia.git] / debugger / memory.c
blob5b289e01c8dd994d0769c1748c3a008e03c97c36
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 #if defined(linux) || defined(__FreeBSD__) || defined(__OpenBSD__)
25 BOOL DEBUG_checkmap_bad( const char *addr, size_t size, int rwflag)
27 FILE *fp;
28 char buf[80]; /* temporary line buffer */
29 char prot[5]; /* protection string */
30 char *start, *end;
31 int ret = TRUE;
33 #ifdef linux
34 /*
35 The entries in /proc/self/maps are of the form:
36 08000000-08002000 r-xp 00000000 03:41 2361
37 08002000-08003000 rw-p 00001000 03:41 2361
38 08003000-08005000 rwxp 00000000 00:00 0
39 40000000-40005000 r-xp 00000000 03:41 67219
40 40005000-40006000 rw-p 00004000 03:41 67219
41 40006000-40007000 rw-p 00000000 00:00 0
42 ...
43 start end perm ??? major:minor inode
45 Only permissions start and end are used here
47 #else
49 % cat /proc/curproc/map
50 start end resident private perm type
51 0x1000 0xe000 12 0 r-x COW vnode
52 0xe000 0x10000 2 2 rwx COW vnode
53 0x10000 0x27000 4 4 rwx default
54 0x800e000 0x800f000 1 1 rw- default
55 0xefbde000 0xefbfe000 1 1 rwx default
57 COW = "copy on write"
59 #endif
62 #ifdef linux
63 if (!(fp = fopen("/proc/self/maps", "r")))
64 #else
65 if (!(fp = fopen("/proc/curproc/map", "r")))
66 #endif
67 return FALSE;
69 while (fgets( buf, 79, fp)) {
70 #ifdef linux
71 sscanf(buf, "%x-%x %3s", (int *) &start, (int *) &end, prot);
72 #else
73 sscanf(buf, "%x %x %*d %*d %3s", (int *) &start, (int *) &end, prot);
74 #endif
75 if ( end <= addr)
76 continue;
77 if (start <= addr && addr+size < end) {
78 if (rwflag)
79 ret = (prot[0] != 'r'); /* test for reading */
80 else
81 ret = (prot[1] != 'w'); /* test for writing */
83 break;
85 fclose( fp);
86 return ret;
88 #else /* linux || FreeBSD */
89 /* FIXME: code needed for BSD et al. */
90 BOOL DEBUG_checkmap_bad(char *addr, size_t size, int rwflag)
92 return FALSE;
94 #endif /* linux || FreeBSD */
97 /***********************************************************************
98 * DEBUG_IsBadReadPtr
100 * Check if we are allowed to read memory at 'address'.
102 BOOL DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size )
104 if (!IS_SELECTOR_V86(address->seg))
105 if (address->seg) /* segmented addr */
107 if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
108 (WORD)address->seg ), size ))
109 return TRUE;
111 return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 1);
115 /***********************************************************************
116 * DEBUG_IsBadWritePtr
118 * Check if we are allowed to write memory at 'address'.
120 BOOL DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size )
122 if (!IS_SELECTOR_V86(address->seg))
123 if (address->seg) /* segmented addr */
125 /* Note: we use IsBadReadPtr here because we are */
126 /* always allowed to write to read-only segments */
127 if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
128 (WORD)address->seg ), size ))
129 return TRUE;
131 return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 0);
135 /***********************************************************************
136 * DEBUG_ReadMemory
138 * Read a memory value.
140 int DEBUG_ReadMemory( const DBG_ADDR *address )
142 DBG_ADDR addr = *address;
144 DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
145 if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return 0;
146 return *(int *)DBG_ADDR_TO_LIN( &addr );
150 /***********************************************************************
151 * DEBUG_WriteMemory
153 * Store a value in memory.
155 void DEBUG_WriteMemory( const DBG_ADDR *address, int value )
157 DBG_ADDR addr = *address;
159 DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
160 if (!DBG_CHECK_WRITE_PTR( &addr, sizeof(int) )) return;
161 *(int *)DBG_ADDR_TO_LIN( &addr ) = value;
165 /***********************************************************************
166 * DEBUG_ExamineMemory
168 * Implementation of the 'x' command.
170 void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
172 DBG_ADDR addr = * address;
173 unsigned int * dump;
174 int i;
175 unsigned char * pnt;
176 unsigned int seg2;
177 struct datatype * testtype;
178 unsigned short int * wdump;
180 DBG_FIX_ADDR_SEG( &addr, (format == 'i') ?
181 CS_reg(&DEBUG_context) : DS_reg(&DEBUG_context) );
184 * Dereference pointer to get actual memory address we need to be
185 * reading. We will use the same segment as what we have already,
186 * and hope that this is a sensible thing to do.
188 if( addr.type != NULL )
190 if( addr.type == DEBUG_TypeIntConst )
193 * We know that we have the actual offset stored somewhere
194 * else in 32-bit space. Grab it, and we
195 * should be all set.
197 seg2 = addr.seg;
198 addr.seg = 0;
199 addr.off = DEBUG_GetExprValue(&addr, NULL);
200 addr.seg = seg2;
202 else
204 if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
205 DEBUG_TypeDerefPointer(&addr, &testtype);
206 if( testtype != NULL || addr.type == DEBUG_TypeIntConst )
208 addr.off = DEBUG_GetExprValue(&addr, NULL);
212 else if (!addr.seg && !addr.off)
214 fprintf(stderr,"Invalid expression\n");
215 return;
218 if (format != 'i' && count > 1)
220 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
221 fprintf(stderr,": ");
224 pnt = DBG_ADDR_TO_LIN( &addr );
226 switch(format)
228 case 'u': {
229 WCHAR *ptr = (WCHAR*)pnt;
230 if (count == 1) count = 256;
231 while (count--)
233 if (!DBG_CHECK_READ_PTR( &addr, sizeof(WCHAR) )) return;
234 if (!*ptr) break;
235 addr.off++;
236 fputc( (char)*ptr++, stderr );
238 fprintf(stderr,"\n");
239 return;
241 case 's':
242 if (count == 1) count = 256;
243 while (count--)
245 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
246 if (!*pnt) break;
247 addr.off++;
248 fputc( *pnt++, stderr );
250 fprintf(stderr,"\n");
251 return;
253 case 'i':
254 while (count--)
256 DEBUG_PrintAddress( &addr, dbg_mode, TRUE );
257 fprintf(stderr,": ");
258 if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
259 DEBUG_Disasm( &addr, TRUE );
260 fprintf(stderr,"\n");
262 return;
263 case 'x':
264 dump = (unsigned int *)pnt;
265 for(i=0; i<count; i++)
267 if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
268 fprintf(stderr," %8.8x", *dump++);
269 addr.off += sizeof(int);
270 if ((i % 8) == 7)
272 fprintf(stderr,"\n");
273 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
274 fprintf(stderr,": ");
277 fprintf(stderr,"\n");
278 return;
280 case 'd':
281 dump = (unsigned int *)pnt;
282 for(i=0; i<count; i++)
284 if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
285 fprintf(stderr," %d", *dump++);
286 addr.off += sizeof(int);
287 if ((i % 8) == 7)
289 fprintf(stderr,"\n");
290 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
291 fprintf(stderr,": ");
294 fprintf(stderr,"\n");
295 return;
297 case 'w':
298 wdump = (unsigned short *)pnt;
299 for(i=0; i<count; i++)
301 if (!DBG_CHECK_READ_PTR( &addr, sizeof(short) )) return;
302 fprintf(stderr," %04x", *wdump++);
303 addr.off += sizeof(short);
304 if ((i % 8) == 7)
306 fprintf(stderr,"\n");
307 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
308 fprintf(stderr,": ");
311 fprintf(stderr,"\n");
312 return;
314 case 'c':
315 for(i=0; i<count; i++)
317 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
318 if(*pnt < 0x20)
320 fprintf(stderr," ");
321 pnt++;
323 else fprintf(stderr," %c", *pnt++);
324 addr.off++;
325 if ((i % 32) == 31)
327 fprintf(stderr,"\n");
328 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
329 fprintf(stderr,": ");
332 fprintf(stderr,"\n");
333 return;
335 case 'b':
336 for(i=0; i<count; i++)
338 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
339 fprintf(stderr," %02x", (*pnt++) & 0xff);
340 addr.off++;
341 if ((i % 16) == 15)
343 fprintf(stderr,"\n");
344 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
345 fprintf(stderr,": ");
348 fprintf(stderr,"\n");
349 return;