Release 961222
[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 char * pnt;
147     unsigned int * dump;
148     unsigned short int * wdump;
149     int i;
150
151     DBG_FIX_ADDR_SEG( &addr, (format == 'i') ?
152                              CS_reg(DEBUG_context) : DS_reg(DEBUG_context) );
153
154     if (format != 'i' && count > 1)
155     {
156         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
157         fprintf(stderr,": ");
158     }
159
160     pnt = DBG_ADDR_TO_LIN( &addr );
161
162     switch(format)
163     {
164         case 's':
165                 if (count == 1) count = 256;
166                 while (count--)
167                 {
168                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
169                     if (!*pnt) break;
170                     addr.off++;
171                     fputc( *pnt++, stderr );
172                 }
173                 fprintf(stderr,"\n");
174                 return;
175
176         case 'i':
177                 while (count--)
178                 {
179                     DEBUG_PrintAddress( &addr, dbg_mode, TRUE );
180                     fprintf(stderr,": ");
181                     if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
182                     DEBUG_Disasm( &addr );
183                     fprintf(stderr,"\n");
184                 }
185                 return;
186         case 'x':
187                 dump = (unsigned int *)pnt;
188                 for(i=0; i<count; i++) 
189                 {
190                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
191                     fprintf(stderr," %8.8x", *dump++);
192                     addr.off += sizeof(int);
193                     if ((i % 8) == 7)
194                     {
195                         fprintf(stderr,"\n");
196                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
197                         fprintf(stderr,": ");
198                     }
199                 }
200                 fprintf(stderr,"\n");
201                 return;
202         
203         case 'd':
204                 dump = (unsigned int *)pnt;
205                 for(i=0; i<count; i++) 
206                 {
207                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
208                     fprintf(stderr," %d", *dump++);
209                     addr.off += sizeof(int);
210                     if ((i % 8) == 7)
211                     {
212                         fprintf(stderr,"\n");
213                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
214                         fprintf(stderr,": ");
215                     }
216                 }
217                 fprintf(stderr,"\n");
218                 return;
219         
220         case 'w':
221                 wdump = (unsigned short *)pnt;
222                 for(i=0; i<count; i++) 
223                 {
224                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(short) )) return;
225                     fprintf(stderr," %04x", *wdump++);
226                     addr.off += sizeof(short);
227                     if ((i % 8) == 7)
228                     {
229                         fprintf(stderr,"\n");
230                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
231                         fprintf(stderr,": ");
232                     }
233                 }
234                 fprintf(stderr,"\n");
235                 return;
236         
237         case 'c':
238                 for(i=0; i<count; i++) 
239                 {
240                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
241                     if(*pnt < 0x20)
242                     {
243                         fprintf(stderr,"  ");
244                         pnt++;
245                     }
246                     else fprintf(stderr," %c", *pnt++);
247                     addr.off++;
248                     if ((i % 32) == 31)
249                     {
250                         fprintf(stderr,"\n");
251                         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
252                         fprintf(stderr,": ");
253                     }
254                 }
255                 fprintf(stderr,"\n");
256                 return;
257         
258         case 'b':
259                 for(i=0; i<count; i++) 
260                 {
261                     if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
262                     fprintf(stderr," %02x", (*pnt++) & 0xff);
263                     addr.off++;
264                     if ((i % 16) == 15)
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 }