Release 970202
[wine/multimedia.git] / debugger / memory.c
blob9f0cb52f576c72c9464284beb3e371997f253fc7
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 #ifdef linux
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 /*
32 The entries in /proc/self/maps are of the form:
33 08000000-08002000 r-xp 00000000 03:41 2361
34 08002000-08003000 rw-p 00001000 03:41 2361
35 08003000-08005000 rwxp 00000000 00:00 0
36 40000000-40005000 r-xp 00000000 03:41 67219
37 40005000-40006000 rw-p 00004000 03:41 67219
38 40006000-40007000 rw-p 00000000 00:00 0
39 ...
40 start end perm ??? major:minor inode
42 Only permissions start and end are used here
45 if (!(fp = fopen("/proc/self/maps", "r")))
46 return FALSE;
48 while (fgets( buf, 79, fp)) {
49 sscanf(buf, "%x-%x %3s", (int *) &start, (int *) &end, prot);
50 if ( end < addr)
51 continue;
52 if (start <= addr && addr+size < end) {
53 if (rwflag)
54 ret = (prot[0] != 'r'); /* test for reading */
55 else
56 ret = (prot[1] != 'w'); /* test for writing */
58 break;
60 fclose( fp);
61 return ret;
63 #else /* linux */
64 /* FIXME: code needed for BSD et al. */
65 BOOL32 DEBUG_checkmap_bad(char *addr, size_t size, int rwflag)
67 return FALSE;
69 #endif /* linux */
72 /***********************************************************************
73 * DEBUG_IsBadReadPtr
75 * Check if we are allowed to read memory at 'address'.
77 BOOL32 DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size )
79 if (address->seg) /* segmented addr */
81 if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
82 (WORD)address->seg ), size ))
83 return TRUE;
85 return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 1);
89 /***********************************************************************
90 * DEBUG_IsBadWritePtr
92 * Check if we are allowed to write memory at 'address'.
94 BOOL32 DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size )
96 if (address->seg) /* segmented addr */
98 /* Note: we use IsBadReadPtr here because we are */
99 /* always allowed to write to read-only segments */
100 if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
101 (WORD)address->seg ), size ))
102 return TRUE;
104 return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 0);
108 /***********************************************************************
109 * DEBUG_ReadMemory
111 * Read a memory value.
113 int DEBUG_ReadMemory( const DBG_ADDR *address )
115 DBG_ADDR addr = *address;
117 DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
118 if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return 0;
119 return *(int *)DBG_ADDR_TO_LIN( &addr );
123 /***********************************************************************
124 * DEBUG_WriteMemory
126 * Store a value in memory.
128 void DEBUG_WriteMemory( const DBG_ADDR *address, int value )
130 DBG_ADDR addr = *address;
132 DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
133 if (!DBG_CHECK_WRITE_PTR( &addr, sizeof(int) )) return;
134 *(int *)DBG_ADDR_TO_LIN( &addr ) = value;
138 /***********************************************************************
139 * DEBUG_ExamineMemory
141 * Implementation of the 'x' command.
143 void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
145 DBG_ADDR addr = * address;
146 unsigned int * dump;
147 int i;
148 unsigned char * pnt;
149 unsigned int seg2;
150 struct datatype * testtype;
151 unsigned short int * wdump;
153 DBG_FIX_ADDR_SEG( &addr, (format == 'i') ?
154 CS_reg(&DEBUG_context) : DS_reg(&DEBUG_context) );
157 * Dereference pointer to get actual memory address we need to be
158 * reading. We will use the same segment as what we have already,
159 * and hope that this is a sensible thing to do.
161 if( addr.type != NULL )
163 if( addr.type == DEBUG_TypeIntConst )
166 * We know that we have the actual offset stored somewhere
167 * else in 32-bit space. Grab it, and we
168 * should be all set.
170 seg2 = addr.seg;
171 addr.seg = 0;
172 addr.off = DEBUG_GetExprValue(&addr, NULL);
173 addr.seg = seg2;
175 else
177 if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
178 DEBUG_TypeDerefPointer(&addr, &testtype);
179 if( testtype != NULL || addr.type == DEBUG_TypeIntConst )
181 addr.off = DEBUG_GetExprValue(&addr, NULL);
185 else if (!addr.seg && !addr.off)
187 fprintf(stderr,"Invalid expression\n");
188 return;
191 if (format != 'i' && count > 1)
193 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
194 fprintf(stderr,": ");
197 pnt = DBG_ADDR_TO_LIN( &addr );
199 switch(format)
201 case 's':
202 if (count == 1) count = 256;
203 while (count--)
205 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
206 if (!*pnt) break;
207 addr.off++;
208 fputc( *pnt++, stderr );
210 fprintf(stderr,"\n");
211 return;
213 case 'i':
214 while (count--)
216 DEBUG_PrintAddress( &addr, dbg_mode, TRUE );
217 fprintf(stderr,": ");
218 if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
219 DEBUG_Disasm( &addr, TRUE );
220 fprintf(stderr,"\n");
222 return;
223 case 'x':
224 dump = (unsigned int *)pnt;
225 for(i=0; i<count; i++)
227 if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
228 fprintf(stderr," %8.8x", *dump++);
229 addr.off += sizeof(int);
230 if ((i % 8) == 7)
232 fprintf(stderr,"\n");
233 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
234 fprintf(stderr,": ");
237 fprintf(stderr,"\n");
238 return;
240 case 'd':
241 dump = (unsigned int *)pnt;
242 for(i=0; i<count; i++)
244 if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
245 fprintf(stderr," %d", *dump++);
246 addr.off += sizeof(int);
247 if ((i % 8) == 7)
249 fprintf(stderr,"\n");
250 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
251 fprintf(stderr,": ");
254 fprintf(stderr,"\n");
255 return;
257 case 'w':
258 wdump = (unsigned short *)pnt;
259 for(i=0; i<count; i++)
261 if (!DBG_CHECK_READ_PTR( &addr, sizeof(short) )) return;
262 fprintf(stderr," %04x", *wdump++);
263 addr.off += sizeof(short);
264 if ((i % 8) == 7)
266 fprintf(stderr,"\n");
267 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
268 fprintf(stderr,": ");
271 fprintf(stderr,"\n");
272 return;
274 case 'c':
275 for(i=0; i<count; i++)
277 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
278 if(*pnt < 0x20)
280 fprintf(stderr," ");
281 pnt++;
283 else fprintf(stderr," %c", *pnt++);
284 addr.off++;
285 if ((i % 32) == 31)
287 fprintf(stderr,"\n");
288 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
289 fprintf(stderr,": ");
292 fprintf(stderr,"\n");
293 return;
295 case 'b':
296 for(i=0; i<count; i++)
298 if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
299 fprintf(stderr," %02x", (*pnt++) & 0xff);
300 addr.off++;
301 if ((i % 16) == 15)
303 fprintf(stderr,"\n");
304 DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
305 fprintf(stderr,": ");
308 fprintf(stderr,"\n");
309 return;