Small fix.
[wine.git] / debugger / memory.c
blobaa1dd713cf1419ebb1f150f394c4588d29fedf52
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 "windows.h"
11 #include "debugger.h"
14 /************************************************************
16 * Check if linear pointer in [addr, addr+size[
17 * read (rwflag == 1)
18 * or
19 * write (rwflag == 0)
20 ************************************************************/
22 #if defined(linux) || defined(__FreeBSD__)
23 BOOL32 DEBUG_checkmap_bad( const char *addr, size_t size, int rwflag)
25 FILE *fp;
26 char buf[80]; /* temporary line buffer */
27 char prot[5]; /* protection string */
28 char *start, *end;
29 int ret = TRUE;
31 #ifdef linux
32 /*
33 The entries in /proc/self/maps are of the form:
34 08000000-08002000 r-xp 00000000 03:41 2361
35 08002000-08003000 rw-p 00001000 03:41 2361
36 08003000-08005000 rwxp 00000000 00:00 0
37 40000000-40005000 r-xp 00000000 03:41 67219
38 40005000-40006000 rw-p 00004000 03:41 67219
39 40006000-40007000 rw-p 00000000 00:00 0
40 ...
41 start end perm ??? major:minor inode
43 Only permissions start and end are used here
45 #else
47 % cat /proc/curproc/map
48 start end resident private perm type
49 0x1000 0xe000 12 0 r-x COW vnode
50 0xe000 0x10000 2 2 rwx COW vnode
51 0x10000 0x27000 4 4 rwx default
52 0x800e000 0x800f000 1 1 rw- default
53 0xefbde000 0xefbfe000 1 1 rwx default
55 COW = "copy on write"
57 #endif
60 #ifdef linux
61 if (!(fp = fopen("/proc/self/maps", "r")))
62 #else
63 if (!(fp = fopen("/proc/curproc/map", "r")))
64 #endif
65 return FALSE;
67 while (fgets( buf, 79, fp)) {
68 #ifdef linux
69 sscanf(buf, "%x-%x %3s", (int *) &start, (int *) &end, prot);
70 #else
71 sscanf(buf, "%x %x %*d %*d %3s", (int *) &start, (int *) &end, prot);
72 #endif
73 if ( end <= addr)
74 continue;
75 if (start <= addr && addr+size < end) {
76 if (rwflag)
77 ret = (prot[0] != 'r'); /* test for reading */
78 else
79 ret = (prot[1] != 'w'); /* test for writing */
81 break;
83 fclose( fp);
84 return ret;
86 #else /* linux || FreeBSD */
87 /* FIXME: code needed for BSD et al. */
88 BOOL32 DEBUG_checkmap_bad(char *addr, size_t size, int rwflag)
90 return FALSE;
92 #endif /* linux || FreeBSD */
95 /***********************************************************************
96 * DEBUG_IsBadReadPtr
98 * Check if we are allowed to read memory at 'address'.
100 BOOL32 DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size )
102 if (!IS_SELECTOR_V86(address->seg))
103 if (address->seg) /* segmented addr */
105 if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
106 (WORD)address->seg ), size ))
107 return TRUE;
109 return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 1);
113 /***********************************************************************
114 * DEBUG_IsBadWritePtr
116 * Check if we are allowed to write memory at 'address'.
118 BOOL32 DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size )
120 if (!IS_SELECTOR_V86(address->seg))
121 if (address->seg) /* segmented addr */
123 /* Note: we use IsBadReadPtr here because we are */
124 /* always allowed to write to read-only segments */
125 if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
126 (WORD)address->seg ), size ))
127 return TRUE;
129 return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 0);
133 /***********************************************************************
134 * DEBUG_ReadMemory
136 * Read a memory value.
138 int DEBUG_ReadMemory( const DBG_ADDR *address )
140 DBG_ADDR addr = *address;
142 DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
143 if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return 0;
144 return *(int *)DBG_ADDR_TO_LIN( &addr );
148 /***********************************************************************
149 * DEBUG_WriteMemory
151 * Store a value in memory.
153 void DEBUG_WriteMemory( const DBG_ADDR *address, int value )
155 DBG_ADDR addr = *address;
157 DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
158 if (!DBG_CHECK_WRITE_PTR( &addr, sizeof(int) )) return;
159 *(int *)DBG_ADDR_TO_LIN( &addr ) = value;
163 /***********************************************************************
164 * DEBUG_ExamineMemory
166 * Implementation of the 'x' command.
168 void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
170 DBG_ADDR addr = * address;
171 unsigned int * dump;
172 int i;
173 unsigned char * pnt;
174 unsigned int seg2;
175 struct datatype * testtype;
176 unsigned short int * wdump;
178 DBG_FIX_ADDR_SEG( &addr, (format == 'i') ?
179 CS_reg(&DEBUG_context) : DS_reg(&DEBUG_context) );
182 * Dereference pointer to get actual memory address we need to be
183 * reading. We will use the same segment as what we have already,
184 * and hope that this is a sensible thing to do.
186 if( addr.type != NULL )
188 if( addr.type == DEBUG_TypeIntConst )
191 * We know that we have the actual offset stored somewhere
192 * else in 32-bit space. Grab it, and we
193 * should be all set.
195 seg2 = addr.seg;
196 addr.seg = 0;
197 addr.off = DEBUG_GetExprValue(&addr, NULL);
198 addr.seg = seg2;
200 else
202 if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
203 DEBUG_TypeDerefPointer(&addr, &testtype);
204 if( testtype != NULL || addr.type == DEBUG_TypeIntConst )
206 addr.off = DEBUG_GetExprValue(&addr, NULL);
210 else if (!addr.seg && !addr.off)
212 fprintf(stderr,"Invalid expression\n");
213 return;
216 if (format != 'i' && count > 1)
218 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
219 fprintf(stderr,": ");
222 pnt = DBG_ADDR_TO_LIN( &addr );
224 switch(format)
226 case 's':
227 if (count == 1) count = 256;
228 while (count--)
230 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
231 if (!*pnt) break;
232 addr.off++;
233 fputc( *pnt++, stderr );
235 fprintf(stderr,"\n");
236 return;
238 case 'i':
239 while (count--)
241 DEBUG_PrintAddress( &addr, dbg_mode, TRUE );
242 fprintf(stderr,": ");
243 if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
244 DEBUG_Disasm( &addr, TRUE );
245 fprintf(stderr,"\n");
247 return;
248 case 'x':
249 dump = (unsigned int *)pnt;
250 for(i=0; i<count; i++)
252 if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
253 fprintf(stderr," %8.8x", *dump++);
254 addr.off += sizeof(int);
255 if ((i % 8) == 7)
257 fprintf(stderr,"\n");
258 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
259 fprintf(stderr,": ");
262 fprintf(stderr,"\n");
263 return;
265 case 'd':
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," %d", *dump++);
271 addr.off += sizeof(int);
272 if ((i % 8) == 7)
274 fprintf(stderr,"\n");
275 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
276 fprintf(stderr,": ");
279 fprintf(stderr,"\n");
280 return;
282 case 'w':
283 wdump = (unsigned short *)pnt;
284 for(i=0; i<count; i++)
286 if (!DBG_CHECK_READ_PTR( &addr, sizeof(short) )) return;
287 fprintf(stderr," %04x", *wdump++);
288 addr.off += sizeof(short);
289 if ((i % 8) == 7)
291 fprintf(stderr,"\n");
292 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
293 fprintf(stderr,": ");
296 fprintf(stderr,"\n");
297 return;
299 case 'c':
300 for(i=0; i<count; i++)
302 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
303 if(*pnt < 0x20)
305 fprintf(stderr," ");
306 pnt++;
308 else fprintf(stderr," %c", *pnt++);
309 addr.off++;
310 if ((i % 32) == 31)
312 fprintf(stderr,"\n");
313 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
314 fprintf(stderr,": ");
317 fprintf(stderr,"\n");
318 return;
320 case 'b':
321 for(i=0; i<count; i++)
323 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
324 fprintf(stderr," %02x", (*pnt++) & 0xff);
325 addr.off++;
326 if ((i % 16) == 15)
328 fprintf(stderr,"\n");
329 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
330 fprintf(stderr,": ");
333 fprintf(stderr,"\n");
334 return;