/* * Debugger memory handling * * Copyright 1993 Eric Youngdale * Copyright 1995 Alexandre Julliard */ #include #include #include "windows.h" #include "debugger.h" /************************************************************ * * Check if linear pointer in [addr, addr+size[ * read (rwflag == 1) * or * write (rwflag == 0) ************************************************************/ #ifdef linux BOOL32 DEBUG_checkmap_bad( const char *addr, size_t size, int rwflag) { FILE *fp; char buf[80]; /* temporary line buffer */ char prot[5]; /* protection string */ char *start, *end; int ret = TRUE; /* The entries in /proc/self/maps are of the form: 08000000-08002000 r-xp 00000000 03:41 2361 08002000-08003000 rw-p 00001000 03:41 2361 08003000-08005000 rwxp 00000000 00:00 0 40000000-40005000 r-xp 00000000 03:41 67219 40005000-40006000 rw-p 00004000 03:41 67219 40006000-40007000 rw-p 00000000 00:00 0 ... start end perm ??? major:minor inode Only permissions start and end are used here */ if (!(fp = fopen("/proc/self/maps", "r"))) return FALSE; while (fgets( buf, 79, fp)) { sscanf(buf, "%x-%x %3s", (int *) &start, (int *) &end, prot); if ( end < addr) continue; if (start <= addr && addr+size < end) { if (rwflag) ret = (prot[0] != 'r'); /* test for reading */ else ret = (prot[1] != 'w'); /* test for writing */ } break; } fclose( fp); return ret; } #else /* linux */ /* FIXME: code needed for BSD et al. */ BOOL32 DEBUG_checkmap_bad(char *addr, size_t size, int rwflag) { return FALSE; } #endif /* linux */ /*********************************************************************** * DEBUG_IsBadReadPtr * * Check if we are allowed to read memory at 'address'. */ BOOL32 DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size ) { if (address->seg) /* segmented addr */ { if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off, (WORD)address->seg ), size )) return TRUE; } return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 1); } /*********************************************************************** * DEBUG_IsBadWritePtr * * Check if we are allowed to write memory at 'address'. */ BOOL32 DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size ) { if (address->seg) /* segmented addr */ { /* Note: we use IsBadReadPtr here because we are */ /* always allowed to write to read-only segments */ if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off, (WORD)address->seg ), size )) return TRUE; } return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 0); } /*********************************************************************** * DEBUG_ReadMemory * * Read a memory value. */ int DEBUG_ReadMemory( const DBG_ADDR *address ) { DBG_ADDR addr = *address; DBG_FIX_ADDR_SEG( &addr, DS_reg(DEBUG_context) ); if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return 0; return *(int *)DBG_ADDR_TO_LIN( &addr ); } /*********************************************************************** * DEBUG_WriteMemory * * Store a value in memory. */ void DEBUG_WriteMemory( const DBG_ADDR *address, int value ) { DBG_ADDR addr = *address; DBG_FIX_ADDR_SEG( &addr, DS_reg(DEBUG_context) ); if (!DBG_CHECK_WRITE_PTR( &addr, sizeof(int) )) return; *(int *)DBG_ADDR_TO_LIN( &addr ) = value; } /*********************************************************************** * DEBUG_ExamineMemory * * Implementation of the 'x' command. */ void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format ) { DBG_ADDR addr = *address; unsigned char * pnt; unsigned int * dump; unsigned short int * wdump; int i; DBG_FIX_ADDR_SEG( &addr, (format == 'i') ? CS_reg(DEBUG_context) : DS_reg(DEBUG_context) ); if (format != 'i' && count > 1) { DEBUG_PrintAddress( &addr, dbg_mode ); fprintf(stderr,": "); } pnt = DBG_ADDR_TO_LIN( &addr ); switch(format) { case 's': if (count == 1) count = 256; while (count--) { if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return; if (!*pnt) break; addr.off++; fputc( *pnt++, stderr ); } fprintf(stderr,"\n"); return; case 'i': while (count--) { DEBUG_PrintAddress( &addr, dbg_mode ); fprintf(stderr,": "); if (!DBG_CHECK_READ_PTR( &addr, 1 )) return; DEBUG_Disasm( &addr ); fprintf(stderr,"\n"); } return; case 'x': dump = (unsigned int *)pnt; for(i=0; i