2 * Debugger memory handling
4 * Copyright 1993 Eric Youngdale
5 * Copyright 1995 Alexandre Julliard
11 #include "wine/winbase16.h"
16 /************************************************************
18 * Check if linear pointer in [addr, addr+size[
22 ************************************************************/
24 BOOL
DEBUG_checkmap_bad( const char *addr
, size_t size
, int rwflag
)
27 char buf
[200]; /* temporary line buffer */
28 char prot
[5]; /* protection string */
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
42 start end perm ??? major:minor inode
44 Only permissions start and end are used here
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
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
71 if (!(fp
= fopen("/proc/self/maps","r")) &&
72 !(fp
= fopen("/proc/curproc/map","r"))
78 * *FOO* read(2) less than length of /proc/.../map fails with EFBIG
80 * $ dd bs=256 </proc/curproc/map
81 * dd: stdin: File too large
84 * 0 bytes transferred in 0.001595 secs (0 bytes/sec)
86 setvbuf(fp
, (char *)NULL
, _IOFBF
, 0x4000);
88 while (fgets( buf
, sizeof(buf
)-1, fp
)) {
90 sscanf(buf
, "%x-%x %3s", (int *) &start
, (int *) &end
, prot
);
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
);
98 if (start
<= addr
&& addr
+size
<= end
) {
100 ret
= (prot
[0] != 'r'); /* test for reading */
102 ret
= (prot
[1] != 'w'); /* test for writing */
111 /***********************************************************************
114 * Check if we are allowed to read memory at 'address'.
116 BOOL
DEBUG_IsBadReadPtr( const DBG_ADDR
*address
, int size
)
119 if (!IS_SELECTOR_V86(address
->seg
))
120 if (address
->seg
) /* segmented addr */
122 if (IsBadReadPtr16( (SEGPTR
)MAKELONG( (WORD
)address
->off
,
123 (WORD
)address
->seg
), size
))
127 return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address
), size
, 1);
131 /***********************************************************************
132 * DEBUG_IsBadWritePtr
134 * Check if we are allowed to write memory at 'address'.
136 BOOL
DEBUG_IsBadWritePtr( const DBG_ADDR
*address
, int size
)
139 if (!IS_SELECTOR_V86(address
->seg
))
140 if (address
->seg
) /* segmented addr */
142 /* Note: we use IsBadReadPtr here because we are */
143 /* always allowed to write to read-only segments */
144 if (IsBadReadPtr16( (SEGPTR
)MAKELONG( (WORD
)address
->off
,
145 (WORD
)address
->seg
), size
))
149 return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address
), size
, 0);
153 /***********************************************************************
156 * Read a memory value.
158 int DEBUG_ReadMemory( const DBG_ADDR
*address
)
160 DBG_ADDR addr
= *address
;
162 DBG_FIX_ADDR_SEG( &addr
, DS_reg(&DEBUG_context
) );
163 if (!DBG_CHECK_READ_PTR( &addr
, sizeof(int) )) return 0;
164 return *(int *)DBG_ADDR_TO_LIN( &addr
);
168 /***********************************************************************
171 * Store a value in memory.
173 void DEBUG_WriteMemory( const DBG_ADDR
*address
, int value
)
175 DBG_ADDR addr
= *address
;
177 DBG_FIX_ADDR_SEG( &addr
, DS_reg(&DEBUG_context
) );
178 if (!DBG_CHECK_WRITE_PTR( &addr
, sizeof(int) )) return;
179 *(int *)DBG_ADDR_TO_LIN( &addr
) = value
;
183 /***********************************************************************
184 * DEBUG_ExamineMemory
186 * Implementation of the 'x' command.
188 void DEBUG_ExamineMemory( const DBG_ADDR
*address
, int count
, char format
)
190 DBG_ADDR addr
= * address
;
195 struct datatype
* testtype
;
196 unsigned short int * wdump
;
198 DBG_FIX_ADDR_SEG( &addr
, (format
== 'i') ?
199 CS_reg(&DEBUG_context
) : DS_reg(&DEBUG_context
) );
202 * Dereference pointer to get actual memory address we need to be
203 * reading. We will use the same segment as what we have already,
204 * and hope that this is a sensible thing to do.
206 if( addr
.type
!= NULL
)
208 if( addr
.type
== DEBUG_TypeIntConst
)
211 * We know that we have the actual offset stored somewhere
212 * else in 32-bit space. Grab it, and we
217 addr
.off
= DEBUG_GetExprValue(&addr
, NULL
);
222 if (!DBG_CHECK_READ_PTR( &addr
, 1 )) return;
223 DEBUG_TypeDerefPointer(&addr
, &testtype
);
224 if( testtype
!= NULL
|| addr
.type
== DEBUG_TypeIntConst
)
226 addr
.off
= DEBUG_GetExprValue(&addr
, NULL
);
230 else if (!addr
.seg
&& !addr
.off
)
232 fprintf(stderr
,"Invalid expression\n");
236 if (format
!= 'i' && count
> 1)
238 DEBUG_PrintAddress( &addr
, dbg_mode
, FALSE
);
239 fprintf(stderr
,": ");
242 pnt
= DBG_ADDR_TO_LIN( &addr
);
247 WCHAR
*ptr
= (WCHAR
*)pnt
;
248 if (count
== 1) count
= 256;
251 if (!DBG_CHECK_READ_PTR( &addr
, sizeof(WCHAR
) )) return;
254 fputc( (char)*ptr
++, stderr
);
256 fprintf(stderr
,"\n");
260 if (count
== 1) count
= 256;
263 if (!DBG_CHECK_READ_PTR( &addr
, sizeof(char) )) return;
266 fputc( *pnt
++, stderr
);
268 fprintf(stderr
,"\n");
274 DEBUG_PrintAddress( &addr
, dbg_mode
, TRUE
);
275 fprintf(stderr
,": ");
276 if (!DBG_CHECK_READ_PTR( &addr
, 1 )) return;
277 DEBUG_Disasm( &addr
, TRUE
);
278 fprintf(stderr
,"\n");
282 dump
= (unsigned int *)pnt
;
283 for(i
=0; i
<count
; i
++)
285 if (!DBG_CHECK_READ_PTR( &addr
, sizeof(int) )) return;
286 fprintf(stderr
," %8.8x", *dump
++);
287 addr
.off
+= sizeof(int);
290 fprintf(stderr
,"\n");
291 DEBUG_PrintAddress( &addr
, dbg_mode
, FALSE
);
292 fprintf(stderr
,": ");
295 fprintf(stderr
,"\n");
299 dump
= (unsigned int *)pnt
;
300 for(i
=0; i
<count
; i
++)
302 if (!DBG_CHECK_READ_PTR( &addr
, sizeof(int) )) return;
303 fprintf(stderr
," %10d", *dump
++);
304 addr
.off
+= sizeof(int);
307 fprintf(stderr
,"\n");
308 DEBUG_PrintAddress( &addr
, dbg_mode
, FALSE
);
309 fprintf(stderr
,": ");
312 fprintf(stderr
,"\n");
316 wdump
= (unsigned short *)pnt
;
317 for(i
=0; i
<count
; i
++)
319 if (!DBG_CHECK_READ_PTR( &addr
, sizeof(short) )) return;
320 fprintf(stderr
," %04x", *wdump
++);
321 addr
.off
+= sizeof(short);
324 fprintf(stderr
,"\n");
325 DEBUG_PrintAddress( &addr
, dbg_mode
, FALSE
);
326 fprintf(stderr
,": ");
329 fprintf(stderr
,"\n");
333 for(i
=0; i
<count
; i
++)
335 if (!DBG_CHECK_READ_PTR( &addr
, sizeof(char) )) return;
341 else fprintf(stderr
," %c", *pnt
++);
345 fprintf(stderr
,"\n");
346 DEBUG_PrintAddress( &addr
, dbg_mode
, FALSE
);
347 fprintf(stderr
,": ");
350 fprintf(stderr
,"\n");
354 for(i
=0; i
<count
; i
++)
356 if (!DBG_CHECK_READ_PTR( &addr
, sizeof(char) )) return;
357 fprintf(stderr
," %02x", (*pnt
++) & 0xff);
361 fprintf(stderr
,"\n");
362 DEBUG_PrintAddress( &addr
, dbg_mode
, FALSE
);
363 fprintf(stderr
,": ");
366 fprintf(stderr
,"\n");