Moved everything out of windows.h.
[wine] / debugger / memory.c
1 /*
2  * Debugger memory handling
3  *
4  * Copyright 1993 Eric Youngdale
5  * Copyright 1995 Alexandre Julliard
6  */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include "windows.h"
11 #include "debugger.h"
12
13
14 /************************************************************
15  *   
16  *  Check if linear pointer in [addr, addr+size[
17  *     read  (rwflag == 1)
18  *   or
19  *     write (rwflag == 0)
20  ************************************************************/
21
22 #if defined(linux) || defined(__FreeBSD__)
23 BOOL32 DEBUG_checkmap_bad( const char *addr, size_t size, int rwflag)
24 {
25   FILE *fp;
26   char buf[80];      /* temporary line buffer */
27   char prot[5];      /* protection string */
28   char *start, *end;
29   int ret = TRUE;
30
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
42
43      Only permissions start and end are used here
44      */
45 #else
46 /*
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
54     
55     COW = "copy on write"
56 */
57 #endif
58
59   
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; 
66
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 */
80     }
81     break;
82   }
83   fclose( fp);
84   return ret;
85 }
86 #else  /* linux || FreeBSD */
87 /* FIXME: code needed for BSD et al. */
88 BOOL32 DEBUG_checkmap_bad(char *addr, size_t size, int rwflag)
89 {
90     return FALSE;
91 }
92 #endif  /* linux || FreeBSD */
93
94
95 /***********************************************************************
96  *           DEBUG_IsBadReadPtr
97  *
98  * Check if we are allowed to read memory at 'address'.
99  */
100 BOOL32 DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size )
101 {
102     if (!IS_SELECTOR_V86(address->seg))
103     if (address->seg)  /* segmented addr */
104     {
105         if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
106                                               (WORD)address->seg ), size ))
107             return TRUE;
108     }
109     return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 1);
110 }
111
112
113 /***********************************************************************
114  *           DEBUG_IsBadWritePtr
115  *
116  * Check if we are allowed to write memory at 'address'.
117  */
118 BOOL32 DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size )
119 {
120     if (!IS_SELECTOR_V86(address->seg))
121     if (address->seg)  /* segmented addr */
122     {
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;
128     }
129     return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 0);
130 }
131
132
133 /***********************************************************************
134  *           DEBUG_ReadMemory
135  *
136  * Read a memory value.
137  */
138 int DEBUG_ReadMemory( const DBG_ADDR *address )
139 {
140     DBG_ADDR addr = *address;
141
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 );
145 }
146
147
148 /***********************************************************************
149  *           DEBUG_WriteMemory
150  *
151  * Store a value in memory.
152  */
153 void DEBUG_WriteMemory( const DBG_ADDR *address, int value )
154 {
155     DBG_ADDR addr = *address;
156
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;
160 }
161
162
163 /***********************************************************************
164  *           DEBUG_ExamineMemory
165  *
166  * Implementation of the 'x' command.
167  */
168 void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
169 {
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;
177
178     DBG_FIX_ADDR_SEG( &addr, (format == 'i') ?
179                              CS_reg(&DEBUG_context) : DS_reg(&DEBUG_context) );
180
181     /*
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.
185      */
186     if( addr.type != NULL )
187       {
188         if( addr.type == DEBUG_TypeIntConst )
189           {
190             /*
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.
194              */
195             seg2 = addr.seg;
196             addr.seg = 0;
197             addr.off = DEBUG_GetExprValue(&addr, NULL);
198             addr.seg = seg2;
199           }
200         else
201           {
202             if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
203             DEBUG_TypeDerefPointer(&addr, &testtype);
204             if( testtype != NULL || addr.type == DEBUG_TypeIntConst )
205               {
206                 addr.off = DEBUG_GetExprValue(&addr, NULL);
207               }
208           }
209       }
210     else if (!addr.seg && !addr.off)
211     {
212         fprintf(stderr,"Invalid expression\n");
213         return;
214     }
215
216     if (format != 'i' && count > 1)
217     {
218         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
219         fprintf(stderr,": ");
220     }
221
222     pnt = DBG_ADDR_TO_LIN( &addr );
223
224     switch(format)
225     {
226         case 'u': {
227                 WCHAR *ptr = (WCHAR*)pnt;
228                 if (count == 1) count = 256;
229                 while (count--)
230                 {
231                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(WCHAR) )) return;
232                     if (!*ptr) break;
233                     addr.off++;
234                     fputc( (char)*ptr++, stderr );
235                 }
236                 fprintf(stderr,"\n");
237                 return;
238             }
239         case 's':
240                 if (count == 1) count = 256;
241                 while (count--)
242                 {
243                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
244                     if (!*pnt) break;
245                     addr.off++;
246                     fputc( *pnt++, stderr );
247                 }
248                 fprintf(stderr,"\n");
249                 return;
250
251         case 'i':
252                 while (count--)
253                 {
254                     DEBUG_PrintAddress( &addr, dbg_mode, TRUE );
255                     fprintf(stderr,": ");
256                     if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
257                     DEBUG_Disasm( &addr, TRUE );
258                     fprintf(stderr,"\n");
259                 }
260                 return;
261         case 'x':
262                 dump = (unsigned int *)pnt;
263                 for(i=0; i<count; i++) 
264                 {
265                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
266                     fprintf(stderr," %8.8x", *dump++);
267                     addr.off += sizeof(int);
268                     if ((i % 8) == 7)
269                     {
270                         fprintf(stderr,"\n");
271                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
272                         fprintf(stderr,": ");
273                     }
274                 }
275                 fprintf(stderr,"\n");
276                 return;
277         
278         case 'd':
279                 dump = (unsigned int *)pnt;
280                 for(i=0; i<count; i++) 
281                 {
282                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
283                     fprintf(stderr," %d", *dump++);
284                     addr.off += sizeof(int);
285                     if ((i % 8) == 7)
286                     {
287                         fprintf(stderr,"\n");
288                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
289                         fprintf(stderr,": ");
290                     }
291                 }
292                 fprintf(stderr,"\n");
293                 return;
294         
295         case 'w':
296                 wdump = (unsigned short *)pnt;
297                 for(i=0; i<count; i++) 
298                 {
299                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(short) )) return;
300                     fprintf(stderr," %04x", *wdump++);
301                     addr.off += sizeof(short);
302                     if ((i % 8) == 7)
303                     {
304                         fprintf(stderr,"\n");
305                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
306                         fprintf(stderr,": ");
307                     }
308                 }
309                 fprintf(stderr,"\n");
310                 return;
311         
312         case 'c':
313                 for(i=0; i<count; i++) 
314                 {
315                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
316                     if(*pnt < 0x20)
317                     {
318                         fprintf(stderr,"  ");
319                         pnt++;
320                     }
321                     else fprintf(stderr," %c", *pnt++);
322                     addr.off++;
323                     if ((i % 32) == 31)
324                     {
325                         fprintf(stderr,"\n");
326                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
327                         fprintf(stderr,": ");
328                     }
329                 }
330                 fprintf(stderr,"\n");
331                 return;
332         
333         case 'b':
334                 for(i=0; i<count; i++) 
335                 {
336                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
337                     fprintf(stderr," %02x", (*pnt++) & 0xff);
338                     addr.off++;
339                     if ((i % 16) == 15)
340                     {
341                         fprintf(stderr,"\n");
342                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
343                         fprintf(stderr,": ");
344                     }
345                 }
346                 fprintf(stderr,"\n");
347                 return;
348         }
349 }