Added a default program option in wine.conf in section [programs] key
[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 's':
227                 if (count == 1) count = 256;
228                 while (count--)
229                 {
230                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
231                     if (!*pnt) break;
232                     addr.off++;
233                     fputc( *pnt++, stderr );
234                 }
235                 fprintf(stderr,"\n");
236                 return;
237
238         case 'i':
239                 while (count--)
240                 {
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");
246                 }
247                 return;
248         case 'x':
249                 dump = (unsigned int *)pnt;
250                 for(i=0; i<count; i++) 
251                 {
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)
256                     {
257                         fprintf(stderr,"\n");
258                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
259                         fprintf(stderr,": ");
260                     }
261                 }
262                 fprintf(stderr,"\n");
263                 return;
264         
265         case 'd':
266                 dump = (unsigned int *)pnt;
267                 for(i=0; i<count; i++) 
268                 {
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)
273                     {
274                         fprintf(stderr,"\n");
275                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
276                         fprintf(stderr,": ");
277                     }
278                 }
279                 fprintf(stderr,"\n");
280                 return;
281         
282         case 'w':
283                 wdump = (unsigned short *)pnt;
284                 for(i=0; i<count; i++) 
285                 {
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)
290                     {
291                         fprintf(stderr,"\n");
292                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
293                         fprintf(stderr,": ");
294                     }
295                 }
296                 fprintf(stderr,"\n");
297                 return;
298         
299         case 'c':
300                 for(i=0; i<count; i++) 
301                 {
302                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
303                     if(*pnt < 0x20)
304                     {
305                         fprintf(stderr,"  ");
306                         pnt++;
307                     }
308                     else fprintf(stderr," %c", *pnt++);
309                     addr.off++;
310                     if ((i % 32) == 31)
311                     {
312                         fprintf(stderr,"\n");
313                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
314                         fprintf(stderr,": ");
315                     }
316                 }
317                 fprintf(stderr,"\n");
318                 return;
319         
320         case 'b':
321                 for(i=0; i<count; i++) 
322                 {
323                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
324                     fprintf(stderr," %02x", (*pnt++) & 0xff);
325                     addr.off++;
326                     if ((i % 16) == 15)
327                     {
328                         fprintf(stderr,"\n");
329                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
330                         fprintf(stderr,": ");
331                     }
332                 }
333                 fprintf(stderr,"\n");
334                 return;
335         }
336 }