Release 970305
[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 #ifdef linux
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   /* 
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
41
42      Only permissions start and end are used here
43      */
44   
45   if (!(fp = fopen("/proc/self/maps", "r")))
46     return FALSE; 
47
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 */
57     }
58     break;
59   }
60   fclose( fp);
61   return ret;
62 }
63 #else  /* linux */
64 /* FIXME: code needed for BSD et al. */
65 BOOL32 DEBUG_checkmap_bad(char *addr, size_t size, int rwflag)
66 {
67     return FALSE;
68 }
69 #endif  /* linux */
70
71
72 /***********************************************************************
73  *           DEBUG_IsBadReadPtr
74  *
75  * Check if we are allowed to read memory at 'address'.
76  */
77 BOOL32 DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size )
78 {
79     if (address->seg)  /* segmented addr */
80     {
81         if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
82                                               (WORD)address->seg ), size ))
83             return TRUE;
84     }
85     return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 1);
86 }
87
88
89 /***********************************************************************
90  *           DEBUG_IsBadWritePtr
91  *
92  * Check if we are allowed to write memory at 'address'.
93  */
94 BOOL32 DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size )
95 {
96     if (address->seg)  /* segmented addr */
97     {
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;
103     }
104     return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 0);
105 }
106
107
108 /***********************************************************************
109  *           DEBUG_ReadMemory
110  *
111  * Read a memory value.
112  */
113 int DEBUG_ReadMemory( const DBG_ADDR *address )
114 {
115     DBG_ADDR addr = *address;
116
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 );
120 }
121
122
123 /***********************************************************************
124  *           DEBUG_WriteMemory
125  *
126  * Store a value in memory.
127  */
128 void DEBUG_WriteMemory( const DBG_ADDR *address, int value )
129 {
130     DBG_ADDR addr = *address;
131
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;
135 }
136
137
138 /***********************************************************************
139  *           DEBUG_ExamineMemory
140  *
141  * Implementation of the 'x' command.
142  */
143 void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
144 {
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;
152
153     DBG_FIX_ADDR_SEG( &addr, (format == 'i') ?
154                              CS_reg(&DEBUG_context) : DS_reg(&DEBUG_context) );
155
156     /*
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.
160      */
161     if( addr.type != NULL )
162       {
163         if( addr.type == DEBUG_TypeIntConst )
164           {
165             /*
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.
169              */
170             seg2 = addr.seg;
171             addr.seg = 0;
172             addr.off = DEBUG_GetExprValue(&addr, NULL);
173             addr.seg = seg2;
174           }
175         else
176           {
177             if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
178             DEBUG_TypeDerefPointer(&addr, &testtype);
179             if( testtype != NULL || addr.type == DEBUG_TypeIntConst )
180               {
181                 addr.off = DEBUG_GetExprValue(&addr, NULL);
182               }
183           }
184       }
185     else if (!addr.seg && !addr.off)
186     {
187         fprintf(stderr,"Invalid expression\n");
188         return;
189     }
190
191     if (format != 'i' && count > 1)
192     {
193         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
194         fprintf(stderr,": ");
195     }
196
197     pnt = DBG_ADDR_TO_LIN( &addr );
198
199     switch(format)
200     {
201         case 's':
202                 if (count == 1) count = 256;
203                 while (count--)
204                 {
205                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
206                     if (!*pnt) break;
207                     addr.off++;
208                     fputc( *pnt++, stderr );
209                 }
210                 fprintf(stderr,"\n");
211                 return;
212
213         case 'i':
214                 while (count--)
215                 {
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");
221                 }
222                 return;
223         case 'x':
224                 dump = (unsigned int *)pnt;
225                 for(i=0; i<count; i++) 
226                 {
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)
231                     {
232                         fprintf(stderr,"\n");
233                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
234                         fprintf(stderr,": ");
235                     }
236                 }
237                 fprintf(stderr,"\n");
238                 return;
239         
240         case 'd':
241                 dump = (unsigned int *)pnt;
242                 for(i=0; i<count; i++) 
243                 {
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)
248                     {
249                         fprintf(stderr,"\n");
250                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
251                         fprintf(stderr,": ");
252                     }
253                 }
254                 fprintf(stderr,"\n");
255                 return;
256         
257         case 'w':
258                 wdump = (unsigned short *)pnt;
259                 for(i=0; i<count; i++) 
260                 {
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)
265                     {
266                         fprintf(stderr,"\n");
267                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
268                         fprintf(stderr,": ");
269                     }
270                 }
271                 fprintf(stderr,"\n");
272                 return;
273         
274         case 'c':
275                 for(i=0; i<count; i++) 
276                 {
277                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
278                     if(*pnt < 0x20)
279                     {
280                         fprintf(stderr,"  ");
281                         pnt++;
282                     }
283                     else fprintf(stderr," %c", *pnt++);
284                     addr.off++;
285                     if ((i % 32) == 31)
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 'b':
296                 for(i=0; i<count; i++) 
297                 {
298                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
299                     fprintf(stderr," %02x", (*pnt++) & 0xff);
300                     addr.off++;
301                     if ((i % 16) == 15)
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 }