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