Fixed last error code when trying to load unknown VxD with CreateFile.
[wine] / debugger / memory.c
1 /*
2  * Debugger memory handling
3  *
4  * Copyright 1993 Eric Youngdale
5  * Copyright 1995 Alexandre Julliard
6  */
7
8 #include "config.h"
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include "wine/winbase16.h"
12 #include "debugger.h"
13 #include "miscemu.h"
14
15
16 /************************************************************
17  *   
18  *  Check if linear pointer in [addr, addr+size[
19  *     read  (rwflag == 1)
20  *   or
21  *     write (rwflag == 0)
22  ************************************************************/
23
24 BOOL DEBUG_checkmap_bad( const char *addr, size_t size, int rwflag)
25 {
26   FILE *fp;
27   char buf[200];      /* 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
59     % cat /proc/curproc/map on FreeBSD 3.0
60     start     end       ?  ?  ?      prot ? ? ?   ?   ?  ?
61     0x8048000 0x8054000 12 14 114770 r-x  2 1 0x0 COW NC vnode
62     0x8054000 0x8055000 1 0 166664 rwx 1 0 0x2180 COW NNC vnode
63     0x8055000 0x806a000 5 0 166662 rwx 1 0 0x2180 NCOW NNC default
64     0x28054000 0x28055000 1 0 166666 rwx 1 0 0x2180 NCOW NNC default
65     0xefbde000 0xefbfe000 1 0 166663 rwx 1 0 0x2180 NCOW NNC default
66
67 */
68 #endif
69
70   
71   if (!(fp = fopen("/proc/self/maps","r")) && 
72       !(fp = fopen("/proc/curproc/map","r"))
73   )
74     return FALSE; 
75
76 #ifdef __FreeBSD__
77   /*
78    * *FOO*  read(2) less than length of /proc/.../map fails with EFBIG
79    *
80    * $ dd bs=256 </proc/curproc/map 
81    * dd: stdin: File too large
82    * 0+0 records in
83    * 0+0 records out
84    * 0 bytes transferred in 0.001595 secs (0 bytes/sec)
85    */
86   setvbuf(fp, (char *)NULL, _IOFBF, 0x4000);
87 #endif
88   while (fgets( buf, sizeof(buf)-1, fp)) {
89 #ifdef linux
90     sscanf(buf, "%x-%x %3s", (int *) &start, (int *) &end, prot);
91 #else
92     sscanf(buf, "%x %x %*d %*d %3s", (int *) &start, (int *) &end, prot);
93     if (prot[0]!='r' && prot[0]!='-') /* FreeBSD 3.0 format */
94        sscanf(buf, "%x %x %*d %*d %*d %3s", (int *) &start, (int *) &end, prot);
95 #endif
96     if ( end <= addr)
97       continue;
98     if (start <= addr && addr+size <= end) {
99       if (rwflag) 
100         ret = (prot[0] != 'r'); /* test for reading */
101       else
102         ret = (prot[1] != 'w'); /* test for writing */
103     }
104     break;
105   }
106   fclose( fp);
107   return ret;
108 }
109
110
111 /***********************************************************************
112  *           DEBUG_IsBadReadPtr
113  *
114  * Check if we are allowed to read memory at 'address'.
115  */
116 BOOL DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size )
117 {
118     if (!IS_SELECTOR_V86(address->seg))
119     if (address->seg)  /* segmented addr */
120     {
121         if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
122                                               (WORD)address->seg ), size ))
123             return TRUE;
124     }
125     return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 1);
126 }
127
128
129 /***********************************************************************
130  *           DEBUG_IsBadWritePtr
131  *
132  * Check if we are allowed to write memory at 'address'.
133  */
134 BOOL DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size )
135 {
136     if (!IS_SELECTOR_V86(address->seg))
137     if (address->seg)  /* segmented addr */
138     {
139         /* Note: we use IsBadReadPtr here because we are */
140         /* always allowed to write to read-only segments */
141         if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
142                                               (WORD)address->seg ), size ))
143             return TRUE;
144     }
145     return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 0);
146 }
147
148
149 /***********************************************************************
150  *           DEBUG_ReadMemory
151  *
152  * Read a memory value.
153  */
154 int DEBUG_ReadMemory( const DBG_ADDR *address )
155 {
156     DBG_ADDR addr = *address;
157
158     DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
159     if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return 0;
160     return *(int *)DBG_ADDR_TO_LIN( &addr );
161 }
162
163
164 /***********************************************************************
165  *           DEBUG_WriteMemory
166  *
167  * Store a value in memory.
168  */
169 void DEBUG_WriteMemory( const DBG_ADDR *address, int value )
170 {
171     DBG_ADDR addr = *address;
172
173     DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
174     if (!DBG_CHECK_WRITE_PTR( &addr, sizeof(int) )) return;
175     *(int *)DBG_ADDR_TO_LIN( &addr ) = value;
176 }
177
178
179 /***********************************************************************
180  *           DEBUG_ExamineMemory
181  *
182  * Implementation of the 'x' command.
183  */
184 void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
185 {
186     DBG_ADDR addr =     * address;
187     unsigned int        * dump;
188     int                   i;
189     unsigned char       * pnt;
190     unsigned int          seg2;
191     struct datatype     * testtype;
192     unsigned short int  * wdump;
193
194     DBG_FIX_ADDR_SEG( &addr, (format == 'i') ?
195                              CS_reg(&DEBUG_context) : DS_reg(&DEBUG_context) );
196
197     /*
198      * Dereference pointer to get actual memory address we need to be
199      * reading.  We will use the same segment as what we have already,
200      * and hope that this is a sensible thing to do.
201      */
202     if( addr.type != NULL )
203       {
204         if( addr.type == DEBUG_TypeIntConst )
205           {
206             /*
207              * We know that we have the actual offset stored somewhere
208              * else in 32-bit space.  Grab it, and we
209              * should be all set.
210              */
211             seg2 = addr.seg;
212             addr.seg = 0;
213             addr.off = DEBUG_GetExprValue(&addr, NULL);
214             addr.seg = seg2;
215           }
216         else
217           {
218             if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
219             DEBUG_TypeDerefPointer(&addr, &testtype);
220             if( testtype != NULL || addr.type == DEBUG_TypeIntConst )
221               {
222                 addr.off = DEBUG_GetExprValue(&addr, NULL);
223               }
224           }
225       }
226     else if (!addr.seg && !addr.off)
227     {
228         fprintf(stderr,"Invalid expression\n");
229         return;
230     }
231
232     if (format != 'i' && count > 1)
233     {
234         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
235         fprintf(stderr,": ");
236     }
237
238     pnt = DBG_ADDR_TO_LIN( &addr );
239
240     switch(format)
241     {
242         case 'u': {
243                 WCHAR *ptr = (WCHAR*)pnt;
244                 if (count == 1) count = 256;
245                 while (count--)
246                 {
247                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(WCHAR) )) return;
248                     if (!*ptr) break;
249                     addr.off++;
250                     fputc( (char)*ptr++, stderr );
251                 }
252                 fprintf(stderr,"\n");
253                 return;
254             }
255         case 's':
256                 if (count == 1) count = 256;
257                 while (count--)
258                 {
259                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
260                     if (!*pnt) break;
261                     addr.off++;
262                     fputc( *pnt++, stderr );
263                 }
264                 fprintf(stderr,"\n");
265                 return;
266
267         case 'i':
268                 while (count--)
269                 {
270                     DEBUG_PrintAddress( &addr, dbg_mode, TRUE );
271                     fprintf(stderr,": ");
272                     if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
273                     DEBUG_Disasm( &addr, TRUE );
274                     fprintf(stderr,"\n");
275                 }
276                 return;
277         case 'x':
278                 dump = (unsigned int *)pnt;
279                 for(i=0; i<count; i++) 
280                 {
281                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
282                     fprintf(stderr," %8.8x", *dump++);
283                     addr.off += sizeof(int);
284                     if ((i % 4) == 3)
285                     {
286                         fprintf(stderr,"\n");
287                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
288                         fprintf(stderr,": ");
289                     }
290                 }
291                 fprintf(stderr,"\n");
292                 return;
293         
294         case 'd':
295                 dump = (unsigned int *)pnt;
296                 for(i=0; i<count; i++) 
297                 {
298                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
299                     fprintf(stderr," %10d", *dump++);
300                     addr.off += sizeof(int);
301                     if ((i % 4) == 3)
302                     {
303                         fprintf(stderr,"\n");
304                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
305                         fprintf(stderr,": ");
306                     }
307                 }
308                 fprintf(stderr,"\n");
309                 return;
310         
311         case 'w':
312                 wdump = (unsigned short *)pnt;
313                 for(i=0; i<count; i++) 
314                 {
315                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(short) )) return;
316                     fprintf(stderr," %04x", *wdump++);
317                     addr.off += sizeof(short);
318                     if ((i % 8) == 7)
319                     {
320                         fprintf(stderr,"\n");
321                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
322                         fprintf(stderr,": ");
323                     }
324                 }
325                 fprintf(stderr,"\n");
326                 return;
327         
328         case 'c':
329                 for(i=0; i<count; i++) 
330                 {
331                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
332                     if(*pnt < 0x20)
333                     {
334                         fprintf(stderr,"  ");
335                         pnt++;
336                     }
337                     else fprintf(stderr," %c", *pnt++);
338                     addr.off++;
339                     if ((i % 32) == 31)
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         case 'b':
350                 for(i=0; i<count; i++) 
351                 {
352                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
353                     fprintf(stderr," %02x", (*pnt++) & 0xff);
354                     addr.off++;
355                     if ((i % 16) == 15)
356                     {
357                         fprintf(stderr,"\n");
358                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
359                         fprintf(stderr,": ");
360                     }
361                 }
362                 fprintf(stderr,"\n");
363                 return;
364         }
365 }